data = fw->data + len;
len = fw->size - len; while (len) { if (len < 12) {
dev_err(component->dev, "%s short data block of %zd\n",
name, len); goto err;
}
/* If we've got user supplied MBC settings use them */ if (control->pdata.num_mbc_cfgs) { struct wm8958_mbc_cfg *cfg
= &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
snd_soc_component_write(component, i + WM8958_MBC_BAND_1_K_1,
cfg->coeff_regs[i]);
for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++)
snd_soc_component_write(component,
i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1,
cfg->cutoff_regs[i]);
}
/* Run the DSP */
snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
WM8958_DSP2_RUNR);
/* If we've got user supplied settings use them */ if (control->pdata.num_mbc_cfgs) { struct wm8958_mbc_cfg *cfg
= &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++)
snd_soc_component_write(component, i + 0x2800,
cfg->combined_regs[i]);
}
if (control->pdata.num_vss_cfgs) { struct wm8958_vss_cfg *cfg
= &control->pdata.vss_cfgs[wm8994->vss_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_component_write(component, i + 0x2600, cfg->regs[i]);
}
if (control->pdata.num_vss_hpf_cfgs) { struct wm8958_vss_hpf_cfg *cfg
= &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_component_write(component, i + 0x2400, cfg->regs[i]);
}
/* Run the DSP */
snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
WM8958_DSP2_RUNR);
/* Enable the algorithms we've selected */
ena = 0; if (wm8994->mbc_ena[path])
ena |= 0x8; if (wm8994->hpf2_ena[path])
ena |= 0x4; if (wm8994->hpf1_ena[path])
ena |= 0x2; if (wm8994->vss_ena[path])
ena |= 0x1;
snd_soc_component_write(component, 0x2201, ena);
/* Switch the DSP into the data path */
snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
}
staticvoid wm8958_dsp_start_enh_eq(struct snd_soc_component *component, int path)
{ struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); struct wm8994 *control = wm8994->wm8994; int i;
/* If we've got user supplied settings use them */ if (control->pdata.num_enh_eq_cfgs) { struct wm8958_enh_eq_cfg *cfg
= &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_component_write(component, i + 0x2200,
cfg->regs[i]);
}
/* Run the DSP */
snd_soc_component_write(component, WM8958_DSP2_EXECCONTROL,
WM8958_DSP2_RUNR);
/* Switch the DSP into the data path */
snd_soc_component_update_bits(component, WM8958_DSP2_CONFIG,
WM8958_MBC_SEL_MASK | WM8958_MBC_ENA,
path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA);
}
staticvoid wm8958_dsp_apply(struct snd_soc_component *component, int path, int start)
{ struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); int pwr_reg = snd_soc_component_read(component, WM8994_POWER_MANAGEMENT_5); int ena, reg, aif;
/* Do we have both an active AIF and an active algorithm? */
ena = wm8994->mbc_ena[path] || wm8994->vss_ena[path] ||
wm8994->hpf1_ena[path] || wm8994->hpf2_ena[path] ||
wm8994->enh_eq_ena[path]; if (!pwr_reg)
ena = 0;
if (start && ena) { /* If the DSP is already running then noop */ if (reg & WM8958_DSP2_ENA) return;
/* If either AIFnCLK is not yet enabled postpone */ if (!(snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1)
& WM8994_AIF1CLK_ENA_MASK) &&
!(snd_soc_component_read(component, WM8994_AIF2_CLOCKING_1)
& WM8994_AIF2CLK_ENA_MASK)) return;
/* Switch the clock over to the appropriate AIF */
snd_soc_component_update_bits(component, WM8994_CLOCKING_1,
WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA,
aif << WM8958_DSP2CLK_SRC_SHIFT |
WM8958_DSP2CLK_ENA);
int wm8958_aif_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event)
{ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct wm8994 *control = dev_get_drvdata(component->dev->parent); int i;
if (control->type != WM8958) return0;
switch (event) { case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_PRE_PMU: for (i = 0; i < 3; i++)
wm8958_dsp_apply(component, i, 1); break; case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_PRE_PMD: for (i = 0; i < 3; i++)
wm8958_dsp_apply(component, i, 0); break;
}
return0;
}
/* Check if DSP2 is in use on another AIF */ staticint wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif)
{ int i;
for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) { if (i == aif) continue; if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] ||
wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i]) return1;
}
return0;
}
staticint wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); struct wm8994 *control = wm8994->wm8994; int value = ucontrol->value.enumerated.item[0]; int reg;
/* Don't allow on the fly reconfiguration */
reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY;
if (value >= control->pdata.num_mbc_cfgs) return -EINVAL;
/* We need an array of texts for the enum API */
wm8994->mbc_texts = kmalloc_array(pdata->num_mbc_cfgs, sizeof(char *),
GFP_KERNEL); if (!wm8994->mbc_texts) return;
for (i = 0; i < pdata->num_mbc_cfgs; i++)
wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
ret = snd_soc_add_component_controls(wm8994->hubs.component,
mbc_control, 1); if (ret != 0)
dev_err(wm8994->hubs.component->dev, "Failed to add MBC mode controls: %d\n", ret);
}
/* We need an array of texts for the enum API */
wm8994->vss_texts = kmalloc_array(pdata->num_vss_cfgs, sizeof(char *),
GFP_KERNEL); if (!wm8994->vss_texts) return;
for (i = 0; i < pdata->num_vss_cfgs; i++)
wm8994->vss_texts[i] = pdata->vss_cfgs[i].name;
/* We need an array of texts for the enum API */
wm8994->vss_hpf_texts = kmalloc_array(pdata->num_vss_hpf_cfgs, sizeof(char *),
GFP_KERNEL); if (!wm8994->vss_hpf_texts) return;
for (i = 0; i < pdata->num_vss_hpf_cfgs; i++)
wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name;
/* We need an array of texts for the enum API */
wm8994->enh_eq_texts = kmalloc_array(pdata->num_enh_eq_cfgs, sizeof(char *),
GFP_KERNEL); if (!wm8994->enh_eq_texts) return;
for (i = 0; i < pdata->num_enh_eq_cfgs; i++)
wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name;
ret = snd_soc_add_component_controls(wm8994->hubs.component,
eq_control, 1); if (ret != 0)
dev_err(wm8994->hubs.component->dev, "Failed to add enhanced EQ controls: %d\n",
ret);
}
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.218Bemerkung:
(vorverarbeitet am 2026-10-14)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.