if (!gpiod_get_value_cansleep(priv->gpio_headset_detect)) return0;
/* Enable headset mic bias regulator so that the ADC reading works */
ret = snd_soc_dapm_force_enable_pin(dapm, "headset-mic-bias"); if (ret < 0) {
pr_err("%s: Failed to enable headset mic bias regulator (%d), assuming headphones\n",
__func__, ret); return SND_JACK_HEADPHONE;
}
snd_soc_dapm_sync(dapm);
/* Sleep for a small amount of time to get the value to stabilize */
msleep(20);
ret = iio_read_channel_processed(priv->adc_headset_detect, &adc); if (ret) {
pr_err("%s: Failed to read ADC (%d), assuming headphones\n",
__func__, ret);
jack_type = SND_JACK_HEADPHONE; goto out;
}
pr_debug("%s: ADC value is %d\n", __func__, adc);
if (!rate)
rate = priv->fll1_rate; /* *Ifnonewrateisrequested,setFLL1toasanedefaultforjack *detection.
*/ if (!rate)
rate = DEFAULT_FLL1_RATE;
if (rate != priv->fll1_rate && priv->fll1_rate) { /* while reconfiguring, switch to MCLK2 for SYSCLK */
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
MCLK2_RATE, SND_SOC_CLOCK_IN); if (ret < 0) {
dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret); return ret;
}
}
ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
MCLK1_RATE, rate); if (ret < 0) {
dev_err(card->dev, "Failed to set FLL1 rate: %d\n", ret); return ret;
}
priv->fll1_rate = rate;
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_FLL1,
priv->fll1_rate, SND_SOC_CLOCK_IN); if (ret < 0) {
dev_err(card->dev, "Failed to set SYSCLK source: %d\n", ret); return ret;
}
ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, 0,
SAMSUNG_I2S_OPCLK_PCLK); if (ret < 0) {
dev_err(card->dev, "Failed to set OPCLK source: %d\n", ret); return ret;
}
/* AIF1CLK should be at least 3MHz for "optimal performance" */ if (params_rate(params) == 8000 || params_rate(params) == 11025)
pll_out = params_rate(params) * 512; else
pll_out = params_rate(params) * 256;
/* Use MCLK2 as SYSCLK for boot */
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, MCLK2_RATE,
SND_SOC_CLOCK_IN); if (ret < 0) {
dev_err(aif1_dai->dev, "Failed to switch to MCLK2: %d\n", ret); return ret;
}
if (!priv->gpio_headset_detect) {
ret = snd_soc_card_jack_new_pins(card, "Headset",
SND_JACK_HEADSET | SND_JACK_MECHANICAL |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3 |
SND_JACK_BTN_4 | SND_JACK_BTN_5,
&priv->headset_jack,
headset_jack_pins,
ARRAY_SIZE(headset_jack_pins)); if (ret) return ret;
wm8958_mic_detect(aif1_dai->component, &priv->headset_jack,
NULL, NULL, NULL, NULL);
} else { /* Some devices (n8000, t310) use a GPIO to detect the jack. */
ret = snd_soc_card_jack_new_pins(card, "Headset",
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2,
&priv->headset_jack,
headset_jack_pins,
ARRAY_SIZE(headset_jack_pins)); if (ret) {
dev_err(card->dev, "Failed to set up headset pins: %d\n", ret); return ret;
}
ret = snd_soc_jack_add_zones(&priv->headset_jack,
ARRAY_SIZE(headset_jack_zones),
headset_jack_zones); if (ret) {
dev_err(card->dev, "Failed to set up headset zones: %d\n", ret); return ret;
}
ret = snd_soc_jack_add_gpios(&priv->headset_jack,
ARRAY_SIZE(headset_gpio),
headset_gpio); if (ret)
dev_err(card->dev, "Failed to set up headset jack GPIOs: %d\n",
ret);
priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH); if (IS_ERR(priv->gpio_fm_sel)) return dev_err_probe(dev, PTR_ERR(priv->gpio_fm_sel), "Failed to get FM selection GPIO\n");
priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel",
GPIOD_OUT_HIGH); if (IS_ERR(priv->gpio_lineout_sel)) return dev_err_probe(dev, PTR_ERR(priv->gpio_lineout_sel), "Failed to get line out selection GPIO\n");
priv->gpio_headset_detect = devm_gpiod_get_optional(dev, "headset-detect", GPIOD_IN); if (IS_ERR(priv->gpio_headset_detect)) return dev_err_probe(dev, PTR_ERR(priv->gpio_headset_detect), "Failed to get headset jack detect GPIO\n");
if (priv->gpio_headset_detect) {
priv->adc_headset_detect = devm_iio_channel_get(dev, "headset-detect"); if (IS_ERR(priv->adc_headset_detect)) return dev_err_probe(dev,
PTR_ERR(priv->adc_headset_detect), "Failed to get ADC channel\n");
ret = iio_get_channel_type(priv->adc_headset_detect,
&channel_type); if (ret) {
dev_err(dev, "Failed to get ADC channel type\n"); return ret;
}
if (channel_type != IIO_VOLTAGE) {
dev_err(dev, "ADC channel is not voltage\n"); return -EINVAL;
}
priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key",
GPIOD_IN); if (IS_ERR(priv->gpio_headset_key)) return dev_err_probe(dev,
PTR_ERR(priv->gpio_headset_key), "Failed to get headset key GPIO\n");
ret = of_property_read_u32_array(dev->of_node, "samsung,headset-4pole-threshold-microvolt",
fourpole_threshold,
ARRAY_SIZE(fourpole_threshold)); if (ret) {
dev_err(dev, "Failed to get 4-pole jack detection threshold\n"); return ret;
}
if (fourpole_threshold[0] > fourpole_threshold[1]) {
dev_err(dev, "Invalid 4-pole jack detection threshold value\n"); return -EINVAL;
}
ret = of_property_read_u32_array(dev->of_node, "samsung,headset-button-threshold-microvolt",
button_threshold,
ARRAY_SIZE(button_threshold)); if (ret) {
dev_err(dev, "Failed to get headset button detection threshold\n"); 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.