/* * PLL modes, to be used for clk_id for set_sysclk callback. * * The default behavior (AUTO) is to take the first matching entry in the clock * table, which is intended to be the PLL based one if there is more than one. * * Setting the clock source using simple-card (clocks or * system-clock-frequency property) sets clk_id = 0 = ADC3XXX_PLL_AUTO.
*/ #define ADC3XXX_PLL_AUTO 0 /* Use first available mode */ #define ADC3XXX_PLL_ENABLE 1 /* Use PLL for clock generation */ #define ADC3XXX_PLL_BYPASS 2 /* Don't use PLL for clock generation */
staticint adc3xxx_get_divs(struct device *dev, int mclk, int rate, int pll_mode)
{ int i;
dev_dbg(dev, "mclk = %d, rate = %d, clock mode %u\n",
mclk, rate, pll_mode); for (i = 0; i < ARRAY_SIZE(adc3xxx_divs); i++) { conststruct adc3xxx_rate_divs *mode = &adc3xxx_divs[i];
/* Skip this entry if it doesn't fulfill the intended clock * mode requirement. We consider anything besides the two * modes below to be the same as ADC3XXX_PLL_AUTO.
*/ if ((pll_mode == ADC3XXX_PLL_BYPASS && mode->pll_p) ||
(pll_mode == ADC3XXX_PLL_ENABLE && !mode->pll_p)) continue;
dev_info(dev, "Master clock rate %d and sample rate %d is not supported\n",
mclk, rate); return -EINVAL;
}
staticint adc3xxx_pll_delay(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event)
{ /* 10msec delay needed after PLL power-up to allow * PLL and dividers to stabilize (datasheet p13).
*/
usleep_range(10000, 20000);
staticconst DECLARE_TLV_DB_SCALE(pga_tlv, 0, 50, 0); staticconst DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 50, 0); staticconst DECLARE_TLV_DB_SCALE(adc_fine_tlv, -40, 10, 0); /* AGC target: 8 values: -5.5, -8, -10, -12, -14, -17, -20, -24 dB */ /* It would be nice to declare these in the order above, but empirically * TLV_DB_SCALE_ITEM doesn't take lightly to the increment (second) parameter * being negative, despite there being examples to the contrary in other * drivers. So declare these in the order from lowest to highest, and * set the invert flag in the SOC_DOUBLE_R_TLV declaration instead.
*/ staticconst DECLARE_TLV_DB_RANGE(agc_target_tlv,
0, 0, TLV_DB_SCALE_ITEM(-2400, 0, 0),
1, 3, TLV_DB_SCALE_ITEM(-2000, 300, 0),
4, 6, TLV_DB_SCALE_ITEM(-1200, 200, 0),
7, 7, TLV_DB_SCALE_ITEM(-550, 0, 0)); /* Since the 'disabled' value (mute) is at the highest value in the dB * range (i.e. just before -32 dB) rather than the lowest, we need to resort * to using a TLV_DB_RANGE in order to get the mute value in the right place.
*/ staticconst DECLARE_TLV_DB_RANGE(agc_thresh_tlv,
0, 30, TLV_DB_SCALE_ITEM(-9000, 200, 0),
31, 31, TLV_DB_SCALE_ITEM(0, 0, 1)); /* disabled = mute */ /* AGC hysteresis: 4 values: 1, 2, 4 dB, disabled (= mute) */ staticconst DECLARE_TLV_DB_RANGE(agc_hysteresis_tlv,
0, 1, TLV_DB_SCALE_ITEM(100, 100, 0),
2, 2, TLV_DB_SCALE_ITEM(400, 0, 0),
3, 3, TLV_DB_SCALE_ITEM(0, 0, 1)); /* disabled = mute */ staticconst DECLARE_TLV_DB_SCALE(agc_max_tlv, 0, 50, 0); /* Input attenuation: -6 dB or 0 dB */ staticconst DECLARE_TLV_DB_SCALE(input_attenuation_tlv, -600, 600, 0);
staticconststruct snd_kcontrol_new adc3xxx_snd_controls[] = {
SOC_DOUBLE_R_TLV("PGA Capture Volume", ADC3XXX_LEFT_APGA_CTRL,
ADC3XXX_RIGHT_APGA_CTRL, 0, 80, 0, pga_tlv),
SOC_DOUBLE("PGA Capture Switch", ADC3XXX_ADC_FGA, 7, 3, 1, 1),
SOC_DOUBLE_R("AGC Capture Switch", ADC3XXX_LEFT_CHN_AGC_1,
ADC3XXX_RIGHT_CHN_AGC_1, 7, 1, 0),
SOC_DOUBLE_R_TLV("AGC Target Level Capture Volume", ADC3XXX_LEFT_CHN_AGC_1,
ADC3XXX_RIGHT_CHN_AGC_2, 4, 0x07, 1, agc_target_tlv),
SOC_DOUBLE_R_TLV("AGC Noise Threshold Capture Volume", ADC3XXX_LEFT_CHN_AGC_2,
ADC3XXX_RIGHT_CHN_AGC_2, 1, 0x1f, 1, agc_thresh_tlv),
SOC_DOUBLE_R_TLV("AGC Hysteresis Capture Volume", ADC3XXX_LEFT_CHN_AGC_2,
ADC3XXX_RIGHT_CHN_AGC_2, 6, 3, 0, agc_hysteresis_tlv),
SOC_DOUBLE_R("AGC Clip Stepping Capture Switch", ADC3XXX_LEFT_CHN_AGC_2,
ADC3XXX_RIGHT_CHN_AGC_2, 0, 1, 0), /* * Oddly enough, the data sheet says the default value * for the left/right AGC maximum gain register field * (ADC3XXX_LEFT/RIGHT_CHN_AGC_3 bits 0..6) is 0x7f = 127 * (verified empirically) even though this value (indeed, above * 0x50) is specified as 'Reserved. Do not use.' in the accompanying * table in the data sheet.
*/
SOC_DOUBLE_R_TLV("AGC Maximum Capture Volume", ADC3XXX_LEFT_CHN_AGC_3,
ADC3XXX_RIGHT_CHN_AGC_3, 0, 0x50, 0, agc_max_tlv),
SOC_DOUBLE_R("AGC Attack Time", ADC3XXX_LEFT_CHN_AGC_4,
ADC3XXX_RIGHT_CHN_AGC_4, 3, 0x1f, 0), /* Would like to have the multipliers as LR pairs, but there is * no SOC_ENUM_foo which accepts two values in separate registers.
*/
SOC_ENUM("AGC Left Attack Time Multiplier", left_agc_attack_mult_enum),
SOC_ENUM("AGC Right Attack Time Multiplier", right_agc_attack_mult_enum),
SOC_DOUBLE_R("AGC Decay Time", ADC3XXX_LEFT_CHN_AGC_5,
ADC3XXX_RIGHT_CHN_AGC_5, 3, 0x1f, 0),
SOC_ENUM("AGC Left Decay Time Multiplier", left_agc_decay_mult_enum),
SOC_ENUM("AGC Right Decay Time Multiplier", right_agc_decay_mult_enum),
SOC_DOUBLE_R("AGC Noise Debounce", ADC3XXX_LEFT_CHN_AGC_6,
ADC3XXX_RIGHT_CHN_AGC_6, 0, 0x1f, 0),
SOC_DOUBLE_R("AGC Signal Debounce", ADC3XXX_LEFT_CHN_AGC_7,
ADC3XXX_RIGHT_CHN_AGC_7, 0, 0x0f, 0), /* Read only register */
SOC_DOUBLE_R_S_TLV("AGC Applied Capture Volume", ADC3XXX_LEFT_AGC_GAIN,
ADC3XXX_RIGHT_AGC_GAIN, 0, -24, 40, 6, 0, adc_tlv), /* ADC soft stepping */
SOC_ENUM("ADC Soft Stepping", adc_softstepping_enum), /* Left/Right Input attenuation */
SOC_SINGLE_TLV("Left Input IN_1L Capture Volume",
ADC3XXX_LEFT_PGA_SEL_1, 0, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Left Input IN_2L Capture Volume",
ADC3XXX_LEFT_PGA_SEL_1, 2, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Left Input IN_3L Capture Volume",
ADC3XXX_LEFT_PGA_SEL_1, 4, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Left Input IN_1R Capture Volume",
ADC3XXX_LEFT_PGA_SEL_2, 0, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Left Input DIF_2L_3L Capture Volume",
ADC3XXX_LEFT_PGA_SEL_1, 6, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Left Input DIF_1L_1R Capture Volume",
ADC3XXX_LEFT_PGA_SEL_2, 4, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Left Input DIF_2R_3R Capture Volume",
ADC3XXX_LEFT_PGA_SEL_2, 2, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Right Input IN_1R Capture Volume",
ADC3XXX_RIGHT_PGA_SEL_1, 0, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Right Input IN_2R Capture Volume",
ADC3XXX_RIGHT_PGA_SEL_1, 2, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Right Input IN_3R Capture Volume",
ADC3XXX_RIGHT_PGA_SEL_1, 4, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Right Input IN_1L Capture Volume",
ADC3XXX_RIGHT_PGA_SEL_2, 0, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Right Input DIF_2R_3R Capture Volume",
ADC3XXX_RIGHT_PGA_SEL_1, 6, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Right Input DIF_1L_1R Capture Volume",
ADC3XXX_RIGHT_PGA_SEL_2, 4, 1, 1, input_attenuation_tlv),
SOC_SINGLE_TLV("Right Input DIF_2L_3L Capture Volume",
ADC3XXX_RIGHT_PGA_SEL_2, 2, 1, 1, input_attenuation_tlv),
SOC_DOUBLE_R_S_TLV("ADC Volume Control Capture Volume", ADC3XXX_LADC_VOL,
ADC3XXX_RADC_VOL, 0, -24, 40, 6, 0, adc_tlv), /* Empirically, the following doesn't work the way it's supposed * to. Values 0, -0.1, -0.2 and -0.3 dB result in the same level, and * -0.4 dB drops about 0.12 dB on a specific chip.
*/
SOC_DOUBLE_TLV("ADC Fine Volume Control Capture Volume", ADC3XXX_ADC_FGA,
4, 0, 4, 1, adc_fine_tlv),
SOC_SINGLE("Left ADC Unselected CM Bias Capture Switch",
ADC3XXX_LEFT_PGA_SEL_2, 6, 1, 0),
SOC_SINGLE("Right ADC Unselected CM Bias Capture Switch",
ADC3XXX_RIGHT_PGA_SEL_2, 6, 1, 0),
SOC_ENUM("Dither Control DC Offset", dither_dc_offset_enum),
/* Coefficient memory for miniDSP. */ /* For the default PRB_R1 processing block, the only available * filter is the first order IIR.
*/
/* Left Digital Mic input for left ADC */ staticconststruct snd_kcontrol_new left_input_dmic_controls[] = {
SOC_DAPM_SINGLE("Left ADC Capture Switch",
ADC3XXX_ADC_DIGITAL, 3, 0x1, 0),
};
/* Right Digital Mic input for Right ADC */ staticconststruct snd_kcontrol_new right_input_dmic_controls[] = {
SOC_DAPM_SINGLE("Right ADC Capture Switch",
ADC3XXX_ADC_DIGITAL, 2, 0x1, 0),
};
if (offset < ADC3XXX_GPIO_PINS) { /* GPIO1 is offset 0, GPIO2 is offset 1 */ /* We check here that the GPIO pins are either not configured * in the DT, or that they purposely are set as outputs. * (Input mode not yet implemented).
*/ if (adc3xxx->gpio_cfg[offset] != 0 &&
adc3xxx->gpio_cfg[offset] != ADC3XXX_GPIO_GPO + 1) return -EINVAL;
} elseif (offset >= ADC3XXX_GPIO_PINS && offset < ADC3XXX_GPIOS_MAX) { /* MICBIAS1 is offset 2, MICBIAS2 is offset 3 */ /* We check here if the MICBIAS pins are in fact configured * as GPOs.
*/ if (!adc3xxx->micbias_gpo[offset - ADC3XXX_GPIO_PINS]) return -EINVAL;
}
/* For the MICBIAS pins, they are by definition outputs. */ if (offset >= ADC3XXX_GPIO_PINS) { unsignedint vg; unsignedint micbias = offset - ADC3XXX_GPIO_PINS;
/* With only GPIO outputs configured, we never get the .direction_out call, * so we set the output mode and output value in the same call. Hence * .set in practice does the same thing as .direction_out .
*/ staticint adc3xxx_gpio_set(struct gpio_chip *chip, unsignedint offset, int value)
{ return adc3xxx_gpio_direction_out(chip, offset, value);
}
/* Even though we only support GPIO output for now, some GPIO clients * want to read the current pin state using the .get callback.
*/ staticint adc3xxx_gpio_get(struct gpio_chip *chip, unsignedint offset)
{ struct adc3xxx *adc3xxx = gpiochip_get_data(chip); unsignedint regval; int ret;
/* We only allow output pins, so just read the value prevously set. */ if (offset >= ADC3XXX_GPIO_PINS) { /* MICBIAS pins */ unsignedint micbias = offset - ADC3XXX_GPIO_PINS;
ret = regmap_read(adc3xxx->regmap, ADC3XXX_MICBIAS_CTRL, ®val); if (ret) return ret; return ((regval >> adc3xxx_micbias_shift[micbias]) & ADC3XXX_MICBIAS_MASK) !=
ADC3XXX_MICBIAS_OFF;
}
ret = regmap_read(adc3xxx->regmap, adc3xxx_gpio_ctrl_reg[offset], ®val); if (ret) return ret; return !!(regval & ADC3XXX_GPIO_CTRL_OUTPUT_CTRL_MASK);
}
ret = gpiochip_add_data(&adc3xxx->gpio_chip, adc3xxx); if (ret)
dev_err(adc3xxx->dev, "Failed to add gpios: %d\n", ret);
/* Set up potential GPIO configuration from the devicetree. * This allows us to set up things which are not software * controllable GPIOs, such as PDM microphone I/O,
*/ for (gpio = 0; gpio < ADC3XXX_GPIO_PINS; gpio++) { unsignedint cfg = adc3xxx->gpio_cfg[gpio];
if (cfg) {
cfg--; /* actual value to use is stored +1 */
regmap_update_bits(adc3xxx->regmap,
adc3xxx_gpio_ctrl_reg[gpio],
ADC3XXX_GPIO_CTRL_CFG_MASK,
cfg << ADC3XXX_GPIO_CTRL_CFG_SHIFT);
}
}
/* Set up micbias voltage. */ /* If pin is configured as GPO, set off initially. */ for (micbias = 0; micbias < ADC3XXX_MICBIAS_PINS; micbias++) { unsignedint vg;
if (adc3xxx->micbias_gpo[micbias])
vg = ADC3XXX_MICBIAS_OFF; else
vg = adc3xxx->micbias_vg[micbias];
if (!of_property_read_u32(np, propname, &val)) { if (val & ~15 || val == 7 || val >= 11) {
dev_err(dev, "Invalid property value for '%s'\n", propname); return -EINVAL;
} if (val == ADC3XXX_GPIO_GPI)
dev_warn(dev, "GPIO Input read not yet implemented\n");
*cfg = val + 1; /* 0 => not set up, all others shifted +1 */
} return 0;
}
/* * match both interface format and signal polarities since they * are fixed
*/ switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK)) { case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF:
format = ADC3XXX_FORMAT_I2S; break; case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF:
format = ADC3XXX_FORMAT_DSP; break; case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF:
format = ADC3XXX_FORMAT_DSP; break; case SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF:
format = ADC3XXX_FORMAT_RJF; break; case SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF:
format = ADC3XXX_FORMAT_LJF; break; default:
dev_err(component->dev, "Invalid DAI format\n"); return -EINVAL;
}
/* set clock direction and format */
ret = snd_soc_component_update_bits(component,
ADC3XXX_INTERFACE_CTRL_1,
ADC3XXX_CLKDIR_MASK | ADC3XXX_FORMAT_MASK,
clkdir | format); if (ret < 0) return ret; return 0;
}
adc3xxx->rst_pin = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(adc3xxx->rst_pin)) { return dev_err_probe(dev, PTR_ERR(adc3xxx->rst_pin), "Failed to request rst_pin\n");
}
adc3xxx->mclk = devm_clk_get(dev, NULL); if (IS_ERR(adc3xxx->mclk)) { /* * The chip itself supports running off the BCLK either * directly or via the PLL, but the driver does not (yet), so * having a specified mclk is required. Otherwise, we could * use the lack of a clocks property to indicate when BCLK is * intended as the clock source.
*/ return dev_err_probe(dev, PTR_ERR(adc3xxx->mclk), "Failed to acquire MCLK\n");
} elseif (adc3xxx->mclk) {
ret = clk_prepare_enable(adc3xxx->mclk); if (ret < 0) return ret;
dev_dbg(dev, "Enabled MCLK, freq %lu Hz\n", clk_get_rate(adc3xxx->mclk));
}
/* Configure mode for DMDIN/GPIO1 pin */
ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmdin-gpio1", &adc3xxx->gpio_cfg[0]); if (ret < 0) goto err_unprepare_mclk; /* Configure mode for DMCLK/GPIO2 pin */
ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmclk-gpio2", &adc3xxx->gpio_cfg[1]); if (ret < 0) goto err_unprepare_mclk; /* Configure mode for MICBIAS1: as Mic Bias output or GPO */
ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias1-gpo", &adc3xxx->micbias_gpo[0]); if (ret < 0) goto err_unprepare_mclk; /* Configure mode for MICBIAS2: as Mic Bias output or GPO */
ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias2-gpo", &adc3xxx->micbias_gpo[1]); if (ret < 0) goto err_unprepare_mclk; /* Configure voltage for MICBIAS1 pin (ON voltage when used as GPO) */
ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias1-vg", &adc3xxx->micbias_vg[0]); if (ret < 0) goto err_unprepare_mclk; /* Configure voltage for MICBIAS2 pin (ON voltage when used as GPO) */
ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias2-vg", &adc3xxx->micbias_vg[1]); if (ret < 0) goto err_unprepare_mclk;
adc3xxx->regmap = devm_regmap_init_i2c(i2c, &adc3xxx_regmap); if (IS_ERR(adc3xxx->regmap)) {
ret = PTR_ERR(adc3xxx->regmap); goto err_unprepare_mclk;
}
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.