codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI); 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)) { if (ctx->mclk) {
ret = clk_prepare_enable(ctx->mclk); if (ret < 0) {
dev_err(card->dev, "could not configure MCLK state"); return ret;
}
}
/* set codec PLL source to the 19.2MHz platform clock (MCLK) */
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
CHT_PLAT_CLK_3_HZ, 48000 * 512); if (ret < 0) {
dev_err(card->dev, "can't set codec pll: %d\n", ret); return ret;
}
/* set codec sysclk source to PLL */
ret = snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_PLL1,
48000 * 512, SND_SOC_CLOCK_IN); if (ret < 0) {
dev_err(card->dev, "can't set codec sysclk: %d\n", ret); return ret;
}
} else { /* Set codec sysclk source to its internal clock because codec * PLL will be off when idle and MCLK will also be off by ACPI * when codec is runtime suspended. Codec needs clock for jack * detection and button press.
*/
ret = snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK,
48000 * 512, SND_SOC_CLOCK_IN); if (ret < 0) {
dev_err(card->dev, "failed to set codec sysclk: %d\n", ret); return ret;
}
if (ctx->mclk)
clk_disable_unprepare(ctx->mclk);
} return 0;
}
if (devm_acpi_dev_add_driver_gpios(component->dev, cht_rt5672_gpios))
dev_warn(runtime->dev, "Unable to add GPIO mapping table\n");
/* Select codec ASRC clock source to track I2S1 clock, because codec * is in slave mode and 100fs I2S format (BCLK = 100 * LRCLK) cannot * be supported by RT5672. Otherwise, ASRC will be disabled and cause * noise.
*/
rt5670_sel_asrc_clk_src(component,
RT5670_DA_STEREO_FILTER
| RT5670_DA_MONO_L_FILTER
| RT5670_DA_MONO_R_FILTER
| RT5670_AD_STEREO_FILTER
| RT5670_AD_MONO_L_FILTER
| RT5670_AD_MONO_R_FILTER,
RT5670_CLK_SEL_I2S1_ASRC);
if (ctx->use_ssp0) {
ret = snd_soc_dapm_add_routes(&runtime->card->dapm,
cht_audio_ssp0_map,
ARRAY_SIZE(cht_audio_ssp0_map));
} else {
ret = snd_soc_dapm_add_routes(&runtime->card->dapm,
cht_audio_ssp2_map,
ARRAY_SIZE(cht_audio_ssp2_map));
} if (ret) return ret;
ret = snd_soc_card_jack_new_pins(runtime->card, "Headset",
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2,
&ctx->headset,
cht_bsw_headset_pins,
ARRAY_SIZE(cht_bsw_headset_pins)); if (ret) return ret;
rt5670_set_jack_detect(component, &ctx->headset); if (ctx->mclk) { /* * 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(ctx->mclk); if (!ret)
clk_disable_unprepare(ctx->mclk);
ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
if (ret) {
dev_err(runtime->dev, "unable to set MCLK rate\n"); return ret;
}
} return 0;
}
/* The DSP will convert the FE rate to 48k, stereo, 24bits */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
if (ctx->use_ssp0) { /* 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;
}
/* * The default mode for the cpu-dai is TDM 4 slot. The default mode * for the codec-dai is I2S. So we need to either set the cpu-dai to * I2S mode to match the codec-dai, or set the codec-dai to TDM 4 slot * (or program both to yet another mode). * One board, the Lenovo Miix 2 10, uses not 1 but 2 codecs connected * to SSP2. The second piggy-backed, output-only codec is inside the * keyboard-dock (which has extra speakers). Unlike the main rt5672 * codec, we cannot configure this codec, it is hard coded to use * 2 channel 24 bit I2S. For this to work we must use I2S mode on this * board. Since we only support 2 channels anyways, there is no need * for TDM on any cht-bsw-rt5672 designs. So we use I2S 2ch everywhere.
*/
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;
}
for_each_card_components(card, component) { if (!strncmp(component->name,
ctx->codec_name, sizeof(ctx->codec_name))) {
dev_dbg(component->dev, "enabling jack detect for resume.\n");
rt5670_jack_resume(component); break;
}
}
return 0;
}
/* use space before codec name to simplify card ID, and simplify driver name */ #define SOF_CARD_NAME "bytcht rt5672"/* card name will be 'sof-bytcht rt5672' */ #define SOF_DRIVER_NAME "SOF"
#define CARD_NAME "cht-bsw-rt5672" #define DRIVER_NAME NULL /* card name will be used for driver name */
/* find index of codec dai */ for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { if (cht_dailink[i].num_codecs &&
!strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) {
dai_index = i; break;
}
}
/* fixup codec name based on HID */
adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); if (adev) {
snprintf(drv->codec_name, sizeof(drv->codec_name), "i2c-%s", acpi_dev_name(adev));
cht_dailink[dai_index].codecs->name = drv->codec_name;
} else {
dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); return -ENOENT;
}
acpi_dev_put(adev);
/* Use SSP0 on Bay Trail CR devices */ if (soc_intel_is_byt() && mach->mach_params.acpi_ipc_irq_index == 0) {
cht_dailink[dai_index].cpus->dai_name = "ssp0-port";
drv->use_ssp0 = true;
}
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.