codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI1); if (!codec_dai)
codec_dai = snd_soc_card_get_codec_dai(card, CHT_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(ctx->mclk); if (ret < 0) {
dev_err(card->dev, "could not configure MCLK state"); 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 when codec is * runtime suspended. Codec needs clock for jack detection and button * press. MCLK is turned off with clock framework or ACPI.
*/
ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
48000 * 512, SND_SOC_CLOCK_IN); if (ret < 0) {
dev_err(card->dev, "can't set codec sysclk: %d\n", ret); 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(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");
/* The DSP will convert the FE rate to 48k, stereo, 24bits */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) ||
(cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) {
/* set SSP0 to 16-bit */
params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
/* * Default mode for SSP configuration is TDM 4 slot, override config * with explicit setting to I2S 2ch 16-bit. 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_fmt(snd_soc_rtd_to_codec(rtd, 0),
SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_BC_FC
); 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, 16); if (ret < 0) {
dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret;
}
} else {
/* set SSP2 to 24-bit */
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
/* * Default mode for SSP configuration is TDM 4 slot
*/
ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_codec(rtd, 0),
SND_SOC_DAIFMT_DSP_B |
SND_SOC_DAIFMT_IB_NF |
SND_SOC_DAIFMT_BC_FC); if (ret < 0) {
dev_err(rtd->dev, "can't set format to TDM %d\n", ret); return ret;
}
/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_codec(rtd, 0), 0xF, 0xF, 4, 24); if (ret < 0) {
dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); return ret;
}
} return 0;
}
/* use space before codec name to simplify card ID, and simplify driver name */ #define SOF_CARD_RT5645_NAME "bytcht rt5645"/* card name 'sof-bytcht rt5645' */ #define SOF_CARD_RT5650_NAME "bytcht rt5650"/* card name 'sof-bytcht rt5650' */ #define SOF_DRIVER_NAME "SOF"
#define CARD_RT5645_NAME "chtrt5645" #define CARD_RT5650_NAME "chtrt5650" #define DRIVER_NAME NULL /* card name will be used for driver name */
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); if (!drv) return -ENOMEM;
mach = pdev->dev.platform_data;
for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { if (acpi_dev_found(snd_soc_cards[i].codec_id) &&
(!strncmp(snd_soc_cards[i].codec_id, mach->id, 8))) {
dev_dbg(&pdev->dev, "found codec %s\n", snd_soc_cards[i].codec_id);
card = snd_soc_cards[i].soc_card;
drv->acpi_card = &snd_soc_cards[i];
found = true; break;
}
}
if (!found) {
dev_err(&pdev->dev, "No matching HID found in supported list\n"); return -ENODEV;
}
card->dev = &pdev->dev;
/* set correct codec name */ for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) if (cht_dailink[i].num_codecs &&
!strcmp(cht_dailink[i].codecs->name, "i2c-10EC5645: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(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name), "i2c-%s", acpi_dev_name(adev));
cht_dailink[dai_index].codecs->name = cht_rt5645_codec_name;
} else {
dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); return -ENOENT;
}
/* acpi_get_first_physical_node() returns a borrowed ref, no need to deref */
codec_dev = acpi_get_first_physical_node(adev);
acpi_dev_put(adev); if (!codec_dev) return -EPROBE_DEFER;
/* * 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;
drv->mclk = devm_clk_get(&pdev->dev, mclk_name); if (IS_ERR(drv->mclk)) {
dev_err(&pdev->dev, "Failed to get MCLK from %s: %ld\n",
mclk_name, PTR_ERR(drv->mclk)); return PTR_ERR(drv->mclk);
}
snd_soc_card_set_drvdata(card, drv);
sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
/* set card and driver name */ if (sof_parent) {
snd_soc_card_chtrt5645.name = SOF_CARD_RT5645_NAME;
snd_soc_card_chtrt5645.driver_name = SOF_DRIVER_NAME;
snd_soc_card_chtrt5650.name = SOF_CARD_RT5650_NAME;
snd_soc_card_chtrt5650.driver_name = SOF_DRIVER_NAME;
} else {
snd_soc_card_chtrt5645.name = CARD_RT5645_NAME;
snd_soc_card_chtrt5645.driver_name = DRIVER_NAME;
snd_soc_card_chtrt5650.name = CARD_RT5650_NAME;
snd_soc_card_chtrt5650.driver_name = DRIVER_NAME;
}
/* set pm ops */ if (sof_parent)
pdev->dev.driver->pm = &snd_soc_pm_ops;
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.