/* Default: jack-detect on JD1_1, internal mic on in2, headsetmic on in3 */ staticunsignedlong byt_rt5651_quirk = BYT_RT5651_DEFAULT_QUIRKS |
BYT_RT5651_IN2_MAP;
codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1); if (!codec_dai)
codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2); if (!codec_dai) {
dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n"); return -EIO;
}
if (SND_SOC_DAPM_EVENT_ON(event)) {
ret = clk_prepare_enable(priv->mclk); if (ret < 0) {
dev_err(card->dev, "could not configure MCLK state"); return ret;
}
ret = byt_rt5651_prepare_and_enable_pll1(codec_dai, 48000, 50);
} else { /* * Set codec clock source to internal clock before * turning off the platform clock. Codec needs clock * for Jack detection and button press
*/
ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK,
48000 * 512,
SND_SOC_CLOCK_IN); if (!ret)
clk_disable_unprepare(priv->mclk);
}
if (ret < 0) {
dev_err(card->dev, "can't set codec sysclk: %d\n", ret); return ret;
}
/* * Note this MUST be called before snd_soc_register_card(), so that the props * are in place before the codec component driver's probe function parses them.
*/ staticint byt_rt5651_add_codec_device_props(struct device *i2c_dev, struct byt_rt5651_private *priv)
{ struct property_entry props[MAX_NO_PROPS] = {}; struct fwnode_handle *fwnode; int cnt = 0; int ret;
if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,dmic-en");
if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
fwnode = fwnode_create_software_node(props, NULL); if (IS_ERR(fwnode)) { /* put_device(i2c_dev) is handled in caller */ return PTR_ERR(fwnode);
}
ret = device_add_software_node(i2c_dev, to_software_node(fwnode));
fwnode_handle_put(fwnode);
return ret;
}
staticint byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
{ struct snd_soc_card *card = runtime->card; struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component; struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); conststruct snd_soc_dapm_route *custom_map; int num_routes; int report; int ret;
card->dapm.idle_bias_off = true;
/* Start with RC clk for jack-detect (we disable MCLK below) */ if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
snd_soc_component_update_bits(codec, RT5651_GLB_CLK,
RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_RCCLK);
switch (BYT_RT5651_MAP(byt_rt5651_quirk)) { case BYT_RT5651_IN1_MAP:
custom_map = byt_rt5651_intmic_in1_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map); break; case BYT_RT5651_IN2_MAP:
custom_map = byt_rt5651_intmic_in2_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map); break; case BYT_RT5651_IN1_IN2_MAP:
custom_map = byt_rt5651_intmic_in1_in2_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map); break; default:
custom_map = byt_rt5651_intmic_dmic_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
}
ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); if (ret) return ret;
if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
ret = snd_soc_dapm_add_routes(&card->dapm,
byt_rt5651_ssp2_aif2_map,
ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
} elseif (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
ret = snd_soc_dapm_add_routes(&card->dapm,
byt_rt5651_ssp0_aif1_map,
ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
} elseif (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
ret = snd_soc_dapm_add_routes(&card->dapm,
byt_rt5651_ssp0_aif2_map,
ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
} else {
ret = snd_soc_dapm_add_routes(&card->dapm,
byt_rt5651_ssp2_aif1_map,
ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
} if (ret) return ret;
ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
ARRAY_SIZE(byt_rt5651_controls)); if (ret) {
dev_err(card->dev, "unable to add card controls\n"); return ret;
}
/* * The firmware might enable the clock at boot (this information * may or may not be reflected in the enable clock register). * To change the rate we must disable the clock first to cover * these cases. Due to common clock framework restrictions that * do not allow to disable a clock that has not been enabled, * we need to enable the clock first.
*/
ret = clk_prepare_enable(priv->mclk); if (!ret)
clk_disable_unprepare(priv->mclk);
if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
ret = clk_set_rate(priv->mclk, 25000000); else
ret = clk_set_rate(priv->mclk, 19200000);
if (ret)
dev_err(card->dev, "unable to set MCLK rate\n");
/* The DSP will convert the FE rate to 48k, stereo */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
(byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) { /* set SSP0 to 16-bit */
params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
bits = 16;
} else { /* set SSP2 to 24-bit */
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
bits = 24;
}
/* * Default mode for SSP configuration is TDM 4 slot, override config * with explicit setting to I2S 2ch. The word length is set with * dai_set_tdm_slot() since there is no other API exposed
*/
ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0),
SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_BP_FP
);
if (ret < 0) {
dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret;
}
ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); if (ret < 0) {
dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret;
}
if (!BYT_RT5651_JDSRC(byt_rt5651_quirk)) return 0;
for_each_card_components(card, component) { if (!strcmp(component->name, byt_rt5651_codec_name)) {
dev_dbg(component->dev, "re-enabling jack detect after resume\n");
snd_soc_component_set_jack(component, &priv->jack,
priv->hp_detect); break;
}
}
return 0;
}
/* use space before codec name to simplify card ID, and simplify driver name */ #define SOF_CARD_NAME "bytcht rt5651"/* card name will be 'sof-bytcht rt5651' */ #define SOF_DRIVER_NAME "SOF"
#define CARD_NAME "bytcr-rt5651" #define DRIVER_NAME NULL /* card name will be used for driver name */
staticconststruct acpi_gpio_mapping cht_rt5651_gpios[] = { /* * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources, * other boards may have I2cSerialBusV2, GpioInt, GpioIo instead. * We want the GpioIo one for the ext-amp-enable-gpio.
*/
{ "ext-amp-enable-gpios", &ext_amp_enable_gpios, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
{ },
};
struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
u64 aif_value; /* 1: AIF1, 2: AIF2 */
u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
};
/* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) { if (byt_rt5651_dais[i].num_codecs &&
!strcmp(byt_rt5651_dais[i].codecs->name, "i2c-10EC5651:00")) {
dai_index = i; break;
}
}
/* fixup codec name based on HID */
adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); if (adev) {
snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), "i2c-%s", acpi_dev_name(adev));
byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
} else {
dev_err(dev, "Error cannot find '%s' dev\n", mach->id); return -ENOENT;
}
/* * swap SSP0 if bytcr is detected * (will be overridden if DMI quirk is detected)
*/ if (soc_intel_is_byt()) { if (mach->mach_params.acpi_ipc_irq_index == 0)
is_bytcr = true;
}
if (is_bytcr) { /* * Baytrail CR platforms may have CHAN package in BIOS, try * to find relevant routing quirk based as done on Windows * platforms. We have to read the information directly from the * BIOS, at this stage the card is not created and the links * with the codec driver/pdata are non-existent
*/
struct acpi_chan_package chan_package = { 0 };
/* format specified: 2 64-bit integers */ struct acpi_buffer format = {sizeof("NN"), "NN"}; struct acpi_buffer state = {0, NULL}; struct snd_soc_acpi_package_context pkg_ctx; bool pkg_found = false;
/* Must be called before register_card, also see declaration comment. */
ret_val = byt_rt5651_add_codec_device_props(codec_dev, priv); if (ret_val) goto err_device;
/* Cherry Trail devices use an external amplifier enable gpio */ if (soc_intel_is_cht() && !byt_rt5651_gpios)
byt_rt5651_gpios = cht_rt5651_gpios;
if (byt_rt5651_gpios) {
devm_acpi_dev_add_driver_gpios(codec_dev, byt_rt5651_gpios);
priv->ext_amp_gpio = devm_fwnode_gpiod_get(dev, codec_dev->fwnode, "ext-amp-enable",
GPIOD_OUT_LOW, "speaker-amp"); if (IS_ERR(priv->ext_amp_gpio)) {
ret_val = PTR_ERR(priv->ext_amp_gpio); switch (ret_val) { case -ENOENT:
priv->ext_amp_gpio = NULL; break; default:
dev_err(dev, "Failed to get ext-amp-enable GPIO: %d\n", ret_val);
fallthrough; case -EPROBE_DEFER: goto err;
}
}
priv->hp_detect = devm_fwnode_gpiod_get(dev, codec_dev->fwnode, "hp-detect",
GPIOD_IN, "hp-detect"); if (IS_ERR(priv->hp_detect)) {
ret_val = PTR_ERR(priv->hp_detect); switch (ret_val) { case -ENOENT:
priv->hp_detect = NULL; break; default:
dev_err(dev, "Failed to get hp-detect GPIO: %d\n", ret_val);
fallthrough; case -EPROBE_DEFER: goto err;
}
}
}
if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
priv->mclk = devm_clk_get_optional(dev, "pmc_plt_clk_3"); if (IS_ERR(priv->mclk)) {
ret_val = dev_err_probe(dev, PTR_ERR(priv->mclk), "Failed to get MCLK from pmc_plt_clk_3\n"); goto err;
} /* * Fall back to bit clock usage when clock is not * available likely due to missing dependencies.
*/ if (!priv->mclk)
byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
}
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.