/* * struct imx_card_plat_data - specific info for codecs * * @fs_mul: ratio of mclk/fs for normal mode * @tdm_fs_mul: ratio of mclk/fs for tdm mode * @support_rates: supported sample rate * @support_tdm_rates: supported sample rate for tdm mode * @support_channels: supported channels * @support_tdm_channels: supported channels for tdm mode * @num_fs_mul: ARRAY_SIZE of fs_mul * @num_tdm_fs_mul: ARRAY_SIZE of tdm_fs_mul * @num_rates: ARRAY_SIZE of support_rates * @num_tdm_rates: ARRAY_SIZE of support_tdm_rates * @num_channels: ARRAY_SIZE of support_channels * @num_tdm_channels: ARRAY_SIZE of support_tdm_channels * @type: codec type
*/ struct imx_card_plat_data { struct imx_akcodec_fs_mul *fs_mul; struct imx_akcodec_tdm_fs_mul *tdm_fs_mul; const u32 *support_rates; const u32 *support_tdm_rates; const u32 *support_channels; const u32 *support_tdm_channels; unsignedint num_fs_mul; unsignedint num_tdm_fs_mul; unsignedint num_rates; unsignedint num_tdm_rates; unsignedint num_channels; unsignedint num_tdm_channels; unsignedint num_codecs; enum codec_type type;
};
/* * struct dai_link_data - specific info for dai link * * @slots: slot number * @slot_width: slot width value * @cpu_sysclk_id: sysclk id for cpu dai * @one2one_ratio: true if mclk equal to bclk
*/ struct dai_link_data { unsignedint slots; unsignedint slot_width; unsignedint cpu_sysclk_id; bool one2one_ratio;
};
/* * struct imx_card_data - platform device data * * @plat_data: pointer of imx_card_plat_data * @dapm_routes: pointer of dapm_routes * @link_data: private data for dai link * @card: card instance * @num_dapm_routes: number of dapm_routes * @asrc_rate: asrc rates * @asrc_format: asrc format
*/ struct imx_card_data { struct imx_card_plat_data *plat_data; struct snd_soc_dapm_route *dapm_routes; struct dai_link_data *link_data; struct snd_soc_card card; int num_dapm_routes;
u32 asrc_rate;
snd_pcm_format_t asrc_format;
};
staticbool format_is_dsd(struct snd_pcm_hw_params *params)
{
snd_pcm_format_t format = params_format(params);
switch (format) { case SNDRV_PCM_FORMAT_DSD_U8: case SNDRV_PCM_FORMAT_DSD_U16_LE: case SNDRV_PCM_FORMAT_DSD_U16_BE: case SNDRV_PCM_FORMAT_DSD_U32_LE: case SNDRV_PCM_FORMAT_DSD_U32_BE: returntrue; default: returnfalse;
}
}
staticbool codec_is_akcodec(unsignedint type)
{ switch (type) { case CODEC_AK4458: case CODEC_AK4497: case CODEC_AK5558: case CODEC_AK5552: case CODEC_CS42888: case CODEC_WM8524: returntrue; default: break;
} returnfalse;
}
ret = snd_soc_dai_set_fmt(cpu_dai, snd_soc_daifmt_clock_provider_flipped(fmt)); if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set cpu dai fmt: %d\n", ret); return ret;
}
ret = snd_soc_dai_set_tdm_slot(cpu_dai,
BIT(slots) - 1,
BIT(slots) - 1,
slots, slot_width); if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret); return ret;
}
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_fmt(codec_dai, fmt); if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set codec dai[%d] fmt: %d\n", i, ret); return ret;
}
if (format_is_tdm(link_data)) {
ret = snd_soc_dai_set_tdm_slot(codec_dai,
BIT(slots) - 1,
BIT(slots) - 1,
slots, slot_width); if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set codec dai[%d] tdm slot: %d\n", i, ret); return ret;
}
}
}
if (format_is_dsd(params)) { /* Use the maximum freq from DSD512 (512*44100 = 22579200) */ if (!(params_rate(params) % 11025))
mclk_freq = IMX_CARD_MCLK_22P5792MHZ; else
mclk_freq = IMX_CARD_MCLK_24P576MHZ;
}
ret = snd_soc_dai_set_sysclk(cpu_dai, link_data->cpu_sysclk_id, mclk_freq,
SND_SOC_CLOCK_OUT); if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set cpui dai mclk1 rate (%lu): %d\n", mclk_freq, ret); return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, SND_SOC_CLOCK_IN); if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set codec dai mclk rate (%lu): %d\n", mclk_freq, ret); return ret;
}
if (constraint_channels.count) {
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraint_channels); if (ret) return ret;
}
if (constraint_rates.count) {
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraint_rates); if (ret) return ret;
}
if (data->plat_data->type == CODEC_AK5558)
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
ak5558_hw_rule_rate, link_data,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
ret = of_property_read_string(np, "link-name", &link->name); if (ret) { return dev_err_probe(card->dev, ret, "error getting codec dai_link name\n");
}
cpu = of_get_child_by_name(np, "cpu"); if (!cpu) {
dev_err(dev, "%s: Can't find cpu DT node\n", link->name);
ret = -EINVAL; goto err;
}
ret = snd_soc_of_get_dlc(cpu, &args, link->cpus, 0); if (ret) {
dev_err_probe(card->dev, ret, "%s: error getting cpu dai info\n", link->name); goto err;
}
if (of_node_name_eq(args.np, "sai")) { /* sai sysclk id */
link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1;
/* sai may support mclk/bclk = 1 */ if (of_property_read_bool(np, "fsl,mclk-equal-bclk")) {
link_data->one2one_ratio = true;
} else { int i;
/* * i.MX8MQ don't support one2one ratio, then * with ak4497 only 16bit case is supported.
*/ for (i = 0; i < ARRAY_SIZE(ak4497_fs_mul); i++) { if (ak4497_fs_mul[i].rmin == 705600 &&
ak4497_fs_mul[i].rmax == 768000) {
ak4497_fs_mul[i].wmin = 32;
ak4497_fs_mul[i].wmax = 32;
}
}
}
}
ret = of_property_read_u32(args.np, "fsl,asrc-rate", &data->asrc_rate); if (ret) {
dev_err(dev, "failed to get output rate\n");
ret = -EINVAL; goto err;
}
ret = of_property_read_u32(args.np, "fsl,asrc-format", &asrc_fmt);
data->asrc_format = (__force snd_pcm_format_t)asrc_fmt; if (ret) { /* Fallback to old binding; translate to asrc_format */
ret = of_property_read_u32(args.np, "fsl,asrc-width", &width); if (ret) {
dev_err(dev, "failed to decide output format\n"); goto err;
}
if (width == 24)
data->asrc_format = SNDRV_PCM_FORMAT_S24_LE; else
data->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
}
} elseif (!strncmp(link->name, "HiFi-ASRC-BE", 12)) { /* DPCM backend */ /* * No need to have link->platforms. alloced dlc[1] will be just wasted, * but it won't leak.
*/
link->no_pcm = 1;
link->platforms = NULL;
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.