// SPDX-License-Identifier: GPL-2.0-or-later /* * Common code for ADAU1X61 and ADAU1X81 codecs * * Copyright 2011-2014 Analog Devices Inc. * Author: Lars-Peter Clausen <lars@metafoo.de>
*/
if (SND_SOC_DAPM_EVENT_ON(event)) {
adau->pll_regs[5] = 1;
} else {
adau->pll_regs[5] = 0; /* Bypass the PLL when disabled, otherwise registers will become
* inaccessible. */
regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL, 0);
}
/* The PLL register is 6 bytes long and can only be written at once. */
regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
if (SND_SOC_DAPM_EVENT_ON(event)) {
mdelay(5);
regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL,
ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL);
}
/* * If we are capturing, toggle the ADOSR bit in Converter Control 0 to * avoid losing SNR (workaround from ADI). This must be done after * the ADC(s) have been enabled. According to the data sheet, it is * normally illegal to set this bit when the sampling rate is 96 kHz, * but according to ADI it is acceptable for this workaround.
*/
regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
ADAU17X1_CONVERTER0_ADOSR, ADAU17X1_CONVERTER0_ADOSR);
regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
ADAU17X1_CONVERTER0_ADOSR, 0);
return 0;
}
staticconstchar * const adau17x1_mono_stereo_text[] = { "Stereo", "Mono Left Channel (L+R)", "Mono Right Channel (L+R)", "Mono (L+R)",
};
/* * The MUX register for the Capture and Playback MUXs selects either DSP as * source/destination or one of the TDM slots. The TDM slot is selected via * snd_soc_dai_set_tdm_slot(), so we only expose whether to go to the DSP or * directly to the DAI interface with this control.
*/ staticint adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct adau *adau = snd_soc_component_get_drvdata(component); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct snd_soc_dapm_update update = {}; unsignedint stream = e->shift_l; unsignedint val, change; int reg;
if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL;
switch (ucontrol->value.enumerated.item[0]) { case 0:
val = 0;
adau->dsp_bypass[stream] = false; break; default:
val = (adau->tdm_slot[stream] * 2) + 1;
adau->dsp_bypass[stream] = true; break;
}
staticbool adau17x1_has_dsp(struct adau *adau)
{ switch (adau->type) { case ADAU1761: case ADAU1381: case ADAU1781: returntrue; default: returnfalse;
}
}
/* Chip has a DSP but we're pretending it doesn't. */ staticbool adau17x1_has_disused_dsp(struct adau *adau)
{ switch (adau->type) { case ADAU1761_AS_1361: returntrue; default: returnfalse;
}
}
staticbool adau17x1_has_safeload(struct adau *adau)
{ switch (adau->type) { case ADAU1761: case ADAU1781: returntrue; default: returnfalse;
}
}
staticint adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, unsignedint freq_in, unsignedint freq_out)
{ struct snd_soc_component *component = dai->component; struct adau *adau = snd_soc_component_get_drvdata(component); int ret;
if (freq_in < 8000000 || freq_in > 27000000) return -EINVAL;
ret = adau_calc_pll_cfg(freq_in, freq_out, adau->pll_regs); if (ret < 0) return ret;
/* The PLL register is 6 bytes long and can only be written at once. */
ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
adau->pll_regs, ARRAY_SIZE(adau->pll_regs)); if (ret) return ret;
switch (params_rate(params)) { case 48000: case 8000: case 12000: case 16000: case 24000: case 32000: case 96000:
pll_rate = 48000 * 1024; break; case 44100: case 7350: case 11025: case 14700: case 22050: case 29400: case 88200:
pll_rate = 44100 * 1024; break; default: return -EINVAL;
}
if (adau17x1_has_dsp(adau) || adau17x1_has_disused_dsp(adau))
regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div); if (adau17x1_has_dsp(adau))
regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
if (adau->sigmadsp) {
ret = adau17x1_setup_firmware(component, params_rate(params)); if (ret < 0) return ret;
}
if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) return 0;
switch (params_width(params)) { case 16:
val = ADAU17X1_SERIAL_PORT1_DELAY16; break; case 24:
val = ADAU17X1_SERIAL_PORT1_DELAY8; break; case 32:
val = ADAU17X1_SERIAL_PORT1_DELAY0; break; default: return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_NF:
ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL; break; case SND_SOC_DAIFMT_NB_IF:
lrclk_pol = !lrclk_pol; break; case SND_SOC_DAIFMT_IB_IF:
ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
lrclk_pol = !lrclk_pol; break; default: return -EINVAL;
}
if (lrclk_pol)
ctrl0 |= ADAU17X1_SERIAL_PORT0_LRCLK_POL;
/* Set the mask to update all relevant bits in ADAU17X1_SERIAL_PORT0 */
ctrl0_mask = ADAU17X1_SERIAL_PORT0_MASTER |
ADAU17X1_SERIAL_PORT0_LRCLK_POL |
ADAU17X1_SERIAL_PORT0_BCLK_POL |
ADAU17X1_SERIAL_PORT0_PULSE_MODE;
switch (reg) { case ADAU17X1_CLOCK_CONTROL: case ADAU17X1_PLL_CONTROL: case ADAU17X1_REC_POWER_MGMT: case ADAU17X1_MICBIAS: case ADAU17X1_SERIAL_PORT0: case ADAU17X1_SERIAL_PORT1: case ADAU17X1_CONVERTER0: case ADAU17X1_CONVERTER1: case ADAU17X1_LEFT_INPUT_DIGITAL_VOL: case ADAU17X1_RIGHT_INPUT_DIGITAL_VOL: case ADAU17X1_ADC_CONTROL: case ADAU17X1_PLAY_POWER_MGMT: case ADAU17X1_DAC_CONTROL0: case ADAU17X1_DAC_CONTROL1: case ADAU17X1_DAC_CONTROL2: case ADAU17X1_SERIAL_PORT_PAD: case ADAU17X1_CONTROL_PORT_PAD0: case ADAU17X1_CONTROL_PORT_PAD1: case ADAU17X1_DSP_SAMPLING_RATE: case ADAU17X1_SERIAL_INPUT_ROUTE: case ADAU17X1_SERIAL_OUTPUT_ROUTE: case ADAU17X1_DSP_ENABLE: case ADAU17X1_DSP_RUN: case ADAU17X1_SERIAL_SAMPLING_RATE: returntrue; default: break;
} returnfalse;
}
EXPORT_SYMBOL_GPL(adau17x1_readable_register);
bool adau17x1_volatile_register(struct device *dev, unsignedint reg)
{ /* SigmaDSP parameter and program memory */ if (reg < 0x4000) returntrue;
switch (reg) { /* The PLL register is 6 bytes long */ case ADAU17X1_PLL_CONTROL: case ADAU17X1_PLL_CONTROL + 1: case ADAU17X1_PLL_CONTROL + 2: case ADAU17X1_PLL_CONTROL + 3: case ADAU17X1_PLL_CONTROL + 4: case ADAU17X1_PLL_CONTROL + 5: returntrue; default: break;
}
/* Check if sample rate is the same as before. If it is there is no * point in performing the below steps as the call to * sigmadsp_setup(...) will return directly when it finds the sample * rate to be the same as before. By checking this we can prevent an * audiable popping noise which occours when toggling DSP_RUN.
*/ if (adau->sigmadsp->current_samplerate == rate) return 0;
snd_soc_dapm_mutex_lock(dapm);
ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr); if (ret) goto err;
ret = regmap_read(adau->regmap, ADAU17X1_DSP_RUN, &dsp_run); if (ret) goto err;
ret = sigmadsp_setup(adau->sigmadsp, rate); if (ret) {
regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0); goto err;
}
regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
regmap_write(adau->regmap, ADAU17X1_DSP_RUN, dsp_run);
err:
snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
int adau17x1_add_widgets(struct snd_soc_component *component)
{ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct adau *adau = snd_soc_component_get_drvdata(component); int ret;
ret = snd_soc_add_component_controls(component, adau17x1_controls,
ARRAY_SIZE(adau17x1_controls)); if (ret) return ret;
ret = snd_soc_dapm_new_controls(dapm, adau17x1_dapm_widgets,
ARRAY_SIZE(adau17x1_dapm_widgets)); if (ret) return ret;
if (adau17x1_has_dsp(adau)) {
ret = snd_soc_dapm_new_controls(dapm, adau17x1_dsp_dapm_widgets,
ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); if (ret) return ret;
if (!adau->sigmadsp) return 0;
ret = sigmadsp_attach(adau->sigmadsp, component); if (ret) {
dev_err(component->dev, "Failed to attach firmware: %d\n",
ret); return ret;
}
}
/* write data to safeload addresses. Check if len is not a multiple of * 4 bytes, if so we need to zero pad.
*/
nbr_words = len / ADAU17X1_WORD_SIZE; if ((len - nbr_words * ADAU17X1_WORD_SIZE) == 0) {
ret = regmap_raw_write(sigmadsp->control_data,
ADAU17X1_SAFELOAD_DATA, bytes, len);
} else {
nbr_words++;
memset(data, 0, ADAU17X1_SAFELOAD_DATA_SIZE);
memcpy(data, bytes, len);
ret = regmap_raw_write(sigmadsp->control_data,
ADAU17X1_SAFELOAD_DATA, data,
nbr_words * ADAU17X1_WORD_SIZE);
}
if (ret < 0) return ret;
/* Write target address, target address is offset by 1 */
addr_offset = addr - 1;
put_unaligned_be32(addr_offset, buf);
ret = regmap_raw_write(sigmadsp->control_data,
ADAU17X1_SAFELOAD_TARGET_ADDRESS, buf, ADAU17X1_WORD_SIZE); if (ret < 0) return ret;
/* write nbr of words to trigger address */
put_unaligned_be32(nbr_words, buf);
ret = regmap_raw_write(sigmadsp->control_data,
ADAU17X1_SAFELOAD_TRIGGER, buf, ADAU17X1_WORD_SIZE); if (ret < 0) return ret;
adau = devm_kzalloc(dev, sizeof(*adau), GFP_KERNEL); if (!adau) return -ENOMEM;
/* Clock is optional (for the driver) */
adau->mclk = devm_clk_get_optional(dev, "mclk"); if (IS_ERR(adau->mclk)) return PTR_ERR(adau->mclk);
if (adau->mclk) {
adau->clk_src = ADAU17X1_CLK_SRC_PLL_AUTO;
/* * Any valid PLL output rate will work at this point, use one * that is likely to be chosen later as well. The register will * be written when the PLL is powered up for the first time.
*/
ret = adau_calc_pll_cfg(clk_get_rate(adau->mclk), 48000 * 1024,
adau->pll_regs); if (ret < 0) return ret;
ret = clk_prepare_enable(adau->mclk); if (ret) return ret;
}
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.