mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-06-21 15:43:21 +02:00
ASoC: update auto format selection method
Current DAI supports auto format selection. It allow to have array like
below.
(X) static u64 xxx_auto_formats[] = {
(A) /* First Priority */
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J,
/* Second Priority */
(B) SND_SOC_POSSIBLE_DAIFMT_DSP_A |
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
};
It try to find available format from I2S/LEFT_J first (A).
Then, try to find from I2S/LEFT_J/DSP_A/DSP_B if couldn't find (A)+(B).
(OR:ed)
In this method, it can't handle if there is format combination.
For example, some driver has pattern.
Pattern1
I2S/RIFHT_J/LEFT_J (FORMAT) and NB_NF/IB_IF/IB_NF/NB_IF (INV)_
Pattern2
DSP_A/DSP_B (FORMAT) and NB_NF/ IB_NF
Because it will try to OR Pattern1 and Pattern2, un-supported
pattern might be selected.
This patch update method not to use OR, and assumes full format array.
Above sample (X) need to be
static u64 xxx_auto_formats[] = {
/* First Priority */
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J,
/* Second Priority */
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
};
Note: It doesn't support Multi CPU/Codec for now
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://patch.msgid.link/87jys836k8.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
97c7d3d203
commit
c6b09cda39
@@ -81,10 +81,10 @@ struct clk;
|
||||
/*
|
||||
* define GATED -> CONT. GATED will be selected if both are selected.
|
||||
* see
|
||||
* snd_soc_runtime_get_dai_fmt()
|
||||
* soc_dai_convert_possiblefmt_to_daifmt()
|
||||
*/
|
||||
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT 16
|
||||
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
|
||||
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
|
||||
#define SND_SOC_POSSIBLE_DAIFMT_GATED (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
|
||||
#define SND_SOC_POSSIBLE_DAIFMT_CONT (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
|
||||
|
||||
@@ -184,8 +184,7 @@ int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio);
|
||||
void snd_soc_dai_set_bclk_clk(struct snd_soc_dai *dai, struct clk *bclk);
|
||||
|
||||
/* Digital Audio interface formatting */
|
||||
int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd);
|
||||
u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority);
|
||||
unsigned int snd_soc_dai_auto_select_format(const struct snd_soc_pcm_runtime *rtd);
|
||||
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
|
||||
|
||||
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
|
||||
|
||||
+1
-144
@@ -1284,148 +1284,6 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtimes);
|
||||
|
||||
static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai_link *dai_link = rtd->dai_link;
|
||||
struct snd_soc_dai *dai, *not_used;
|
||||
u64 pos, possible_fmt;
|
||||
unsigned int mask = 0, dai_fmt = 0;
|
||||
int i, j, priority, pri, until;
|
||||
|
||||
/*
|
||||
* Get selectable format from each DAIs.
|
||||
*
|
||||
****************************
|
||||
* NOTE
|
||||
* Using .auto_selectable_formats is not mandatory,
|
||||
* we can select format manually from Sound Card.
|
||||
* When use it, driver should list well tested format only.
|
||||
****************************
|
||||
*
|
||||
* ex)
|
||||
* auto_selectable_formats (= SND_SOC_POSSIBLE_xxx)
|
||||
* (A) (B) (C)
|
||||
* DAI0_: { 0x000F, 0x00F0, 0x0F00 };
|
||||
* DAI1 : { 0xF000, 0x0F00 };
|
||||
* (X) (Y)
|
||||
*
|
||||
* "until" will be 3 in this case (MAX array size from DAI0 and DAI1)
|
||||
* Here is dev_dbg() message and comments
|
||||
*
|
||||
* priority = 1
|
||||
* DAI0: (pri, fmt) = (1, 000000000000000F) // 1st check (A) DAI1 is not selected
|
||||
* DAI1: (pri, fmt) = (0, 0000000000000000) // Necessary Waste
|
||||
* DAI0: (pri, fmt) = (1, 000000000000000F) // 2nd check (A)
|
||||
* DAI1: (pri, fmt) = (1, 000000000000F000) // (X)
|
||||
* priority = 2
|
||||
* DAI0: (pri, fmt) = (2, 00000000000000FF) // 3rd check (A) + (B)
|
||||
* DAI1: (pri, fmt) = (1, 000000000000F000) // (X)
|
||||
* DAI0: (pri, fmt) = (2, 00000000000000FF) // 4th check (A) + (B)
|
||||
* DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y)
|
||||
* priority = 3
|
||||
* DAI0: (pri, fmt) = (3, 0000000000000FFF) // 5th check (A) + (B) + (C)
|
||||
* DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y)
|
||||
* found auto selected format: 0000000000000F00
|
||||
*/
|
||||
until = snd_soc_dai_get_fmt_max_priority(rtd);
|
||||
for (priority = 1; priority <= until; priority++) {
|
||||
for_each_rtd_dais(rtd, j, not_used) {
|
||||
|
||||
possible_fmt = ULLONG_MAX;
|
||||
for_each_rtd_dais(rtd, i, dai) {
|
||||
u64 fmt = 0;
|
||||
|
||||
pri = (j >= i) ? priority : priority - 1;
|
||||
fmt = snd_soc_dai_get_fmt(dai, pri);
|
||||
possible_fmt &= fmt;
|
||||
}
|
||||
if (possible_fmt)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
/* Not Found */
|
||||
return;
|
||||
found:
|
||||
/*
|
||||
* convert POSSIBLE_DAIFMT to DAIFMT
|
||||
*
|
||||
* Some basic/default settings on each is defined as 0.
|
||||
* see
|
||||
* SND_SOC_DAIFMT_NB_NF
|
||||
* SND_SOC_DAIFMT_GATED
|
||||
*
|
||||
* SND_SOC_DAIFMT_xxx_MASK can't notice it if Sound Card specify
|
||||
* these value, and will be overwrite to auto selected value.
|
||||
*
|
||||
* To avoid such issue, loop from 63 to 0 here.
|
||||
* Small number of SND_SOC_POSSIBLE_xxx will be Hi priority.
|
||||
* Basic/Default settings of each part and above are defined
|
||||
* as Hi priority (= small number) of SND_SOC_POSSIBLE_xxx.
|
||||
*/
|
||||
for (i = 63; i >= 0; i--) {
|
||||
pos = 1ULL << i;
|
||||
switch (possible_fmt & pos) {
|
||||
/*
|
||||
* for format
|
||||
*/
|
||||
case SND_SOC_POSSIBLE_DAIFMT_I2S:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_RIGHT_J:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_LEFT_J:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_DSP_A:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_DSP_B:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_AC97:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_PDM:
|
||||
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | i;
|
||||
break;
|
||||
/*
|
||||
* for clock
|
||||
*/
|
||||
case SND_SOC_POSSIBLE_DAIFMT_CONT:
|
||||
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_CONT;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_GATED:
|
||||
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_GATED;
|
||||
break;
|
||||
/*
|
||||
* for clock invert
|
||||
*/
|
||||
case SND_SOC_POSSIBLE_DAIFMT_NB_NF:
|
||||
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_NF;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_NB_IF:
|
||||
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_IF;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_IB_NF:
|
||||
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_NF;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_IB_IF:
|
||||
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_IF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some driver might have very complex limitation.
|
||||
* In such case, user want to auto-select non-limitation part,
|
||||
* and want to manually specify complex part.
|
||||
*
|
||||
* Or for example, if both CPU and Codec can be clock provider,
|
||||
* but because of its quality, user want to specify it manually.
|
||||
*
|
||||
* Use manually specified settings if sound card did.
|
||||
*/
|
||||
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK))
|
||||
mask |= SND_SOC_DAIFMT_FORMAT_MASK;
|
||||
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_MASK))
|
||||
mask |= SND_SOC_DAIFMT_CLOCK_MASK;
|
||||
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_INV_MASK))
|
||||
mask |= SND_SOC_DAIFMT_INV_MASK;
|
||||
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK))
|
||||
mask |= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
|
||||
|
||||
dai_link->dai_fmt |= (dai_fmt & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime
|
||||
* @rtd: The runtime for which the DAI link format should be changed
|
||||
@@ -1504,8 +1362,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
snd_soc_runtime_get_dai_fmt(rtd);
|
||||
ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
|
||||
ret = snd_soc_runtime_set_dai_fmt(rtd, snd_soc_dai_auto_select_format(rtd));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
||||
+163
-46
@@ -138,68 +138,185 @@ void snd_soc_dai_set_bclk_clk(struct snd_soc_dai *dai, struct clk *bclk)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_clk);
|
||||
|
||||
int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd)
|
||||
static int soc_dai_fmt_match_cnt(u64 fmt)
|
||||
{
|
||||
struct snd_soc_dai *dai;
|
||||
int i, max = 0;
|
||||
int cnt = 0;
|
||||
|
||||
/*
|
||||
* return max num if *ALL* DAIs have .auto_selectable_formats
|
||||
*/
|
||||
for_each_rtd_dais(rtd, i, dai) {
|
||||
if (dai->driver->ops &&
|
||||
dai->driver->ops->num_auto_selectable_formats)
|
||||
max = max(max, dai->driver->ops->num_auto_selectable_formats);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if (fmt & SND_SOC_POSSIBLE_DAIFMT_FORMAT_MASK)
|
||||
cnt++;
|
||||
if (fmt & SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK)
|
||||
cnt++;
|
||||
if (fmt & SND_SOC_POSSIBLE_DAIFMT_INV_MASK)
|
||||
cnt++;
|
||||
|
||||
return max;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dai_get_fmt - get supported audio format.
|
||||
* @dai: DAI
|
||||
* @priority: priority level of supported audio format.
|
||||
*
|
||||
* This should return only formats implemented with high
|
||||
* quality by the DAI so that the core can configure a
|
||||
* format which will work well with other devices.
|
||||
* For example devices which don't support both edges of the
|
||||
* LRCLK signal in I2S style formats should only list DSP
|
||||
* modes. This will mean that sometimes fewer formats
|
||||
* are reported here than are supported by set_fmt().
|
||||
*/
|
||||
u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority)
|
||||
static void soc_dai_auto_select_format(u64 fmt, const struct snd_soc_pcm_runtime *rtd,
|
||||
int idx, u64 *best_fmt)
|
||||
{
|
||||
const struct snd_soc_dai_ops *ops = dai->driver->ops;
|
||||
u64 fmt = 0;
|
||||
int i, max = 0, until = priority;
|
||||
struct snd_soc_dai *dai;
|
||||
const struct snd_soc_dai_ops *ops;
|
||||
int max_idx = rtd->dai_link->num_cpus + rtd->dai_link->num_codecs;
|
||||
u64 available_fmt;
|
||||
|
||||
/*
|
||||
* Collect auto_selectable_formats until priority
|
||||
* NOTE
|
||||
* It doesn't support Multi CPU/Codec for now
|
||||
*/
|
||||
if (rtd->dai_link->num_cpus != 1 ||
|
||||
rtd->dai_link->num_codecs != 1)
|
||||
return;
|
||||
|
||||
if (idx >= max_idx)
|
||||
return;
|
||||
|
||||
dai = rtd->dais[idx];
|
||||
ops = dai->driver->ops;
|
||||
|
||||
/* zero chance of auto select format */
|
||||
if (!ops || !ops->num_auto_selectable_formats)
|
||||
return;
|
||||
|
||||
/*
|
||||
****************************
|
||||
* NOTE
|
||||
****************************
|
||||
* Using .auto_selectable_formats is not mandatory,
|
||||
* It try to find best formats as much as possible, but automatically selecting the
|
||||
* perfect format is impossible. So you can select full or missing format manually
|
||||
* from Sound Card.
|
||||
*
|
||||
* ex)
|
||||
* auto_selectable_formats[] = { A, B, C };
|
||||
* (A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx)
|
||||
* CPU Codec
|
||||
* (A)[0] I2S/LEFT_J : IB_NF/IB_IF (X)[0] I2S/DSP_A: NB_NF : GATED
|
||||
* (B)[1] DSP_A/DSP_B: NB_NF/IB_NF (Y)[1] LEFT_J: NB_NF : GATED
|
||||
* (C)[2] ...
|
||||
*
|
||||
* priority = 1 : A
|
||||
* priority = 2 : A | B
|
||||
* priority = 3 : A | B | C
|
||||
* priority = 4 : A | B | C
|
||||
* 1. (A) -> (X) : I2S :update best format
|
||||
* 2. (A) -> (Y) : LEFT_J
|
||||
* 3. (B) -> (X) : DSP_A/NB_NF :update best format
|
||||
* 4. (B) -> (Y) : NB_NF
|
||||
* 5. (C) -> (X) ...
|
||||
* 6. (C) -> (Y) ...
|
||||
* ...
|
||||
*
|
||||
* In above case GATED will not be selected
|
||||
*/
|
||||
if (ops)
|
||||
max = ops->num_auto_selectable_formats;
|
||||
|
||||
if (max < until)
|
||||
until = max;
|
||||
/* find best formats */
|
||||
for (int i = 0; i < ops->num_auto_selectable_formats; i++) {
|
||||
available_fmt = fmt & ops->auto_selectable_formats[i];
|
||||
|
||||
if (ops && ops->auto_selectable_formats)
|
||||
for (i = 0; i < until; i++)
|
||||
fmt |= ops->auto_selectable_formats[i];
|
||||
/* In case of last DAI */
|
||||
if (idx + 1 >= max_idx) {
|
||||
int cnt1 = soc_dai_fmt_match_cnt(*best_fmt);
|
||||
int cnt2 = soc_dai_fmt_match_cnt(available_fmt);
|
||||
|
||||
return fmt;
|
||||
if (cnt1 < cnt2)
|
||||
*best_fmt = available_fmt;
|
||||
}
|
||||
/* parse with next DAI */
|
||||
else {
|
||||
soc_dai_auto_select_format(available_fmt, rtd, idx + 1, best_fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int soc_dai_convert_possiblefmt_to_daifmt(u64 possible_fmt, unsigned int configured_fmt)
|
||||
{
|
||||
unsigned int fmt = 0;
|
||||
unsigned int mask = 0;
|
||||
|
||||
/*
|
||||
* convert POSSIBLE_DAIFMT to DAIFMT
|
||||
*
|
||||
* Some basic/default settings on each is defined as 0.
|
||||
* see
|
||||
* SND_SOC_DAIFMT_NB_NF
|
||||
* SND_SOC_DAIFMT_GATED
|
||||
*
|
||||
* SND_SOC_DAIFMT_xxx_MASK can't notice it if Sound Card specify
|
||||
* these value, and will be overwrite to auto selected value.
|
||||
*
|
||||
* To avoid such issue, loop from 63 to 0 here.
|
||||
* Small number of SND_SOC_POSSIBLE_xxx will be Hi priority.
|
||||
* Basic/Default settings of each part and above are defined
|
||||
* as Hi priority (= small number) of SND_SOC_POSSIBLE_xxx.
|
||||
*/
|
||||
for (int i = 63; i >= 0; i--) {
|
||||
u64 pos = 1ULL << i;
|
||||
|
||||
switch (possible_fmt & pos) {
|
||||
/*
|
||||
* for format
|
||||
*/
|
||||
case SND_SOC_POSSIBLE_DAIFMT_I2S:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_RIGHT_J:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_LEFT_J:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_DSP_A:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_DSP_B:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_AC97:
|
||||
case SND_SOC_POSSIBLE_DAIFMT_PDM:
|
||||
fmt = (fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | i;
|
||||
break;
|
||||
/*
|
||||
* for clock
|
||||
*/
|
||||
case SND_SOC_POSSIBLE_DAIFMT_CONT:
|
||||
fmt = (fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_CONT;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_GATED:
|
||||
fmt = (fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_GATED;
|
||||
break;
|
||||
/*
|
||||
* for clock invert
|
||||
*/
|
||||
case SND_SOC_POSSIBLE_DAIFMT_NB_NF:
|
||||
fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_NF;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_NB_IF:
|
||||
fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_IF;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_IB_NF:
|
||||
fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_NF;
|
||||
break;
|
||||
case SND_SOC_POSSIBLE_DAIFMT_IB_IF:
|
||||
fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_IF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some driver might have very complex limitation.
|
||||
* In such case, user want to auto-select non-limitation part,
|
||||
* and want to manually specify complex part.
|
||||
*
|
||||
* Or for example, if both CPU and Codec can be clock provider,
|
||||
* but because of its quality, user want to specify it manually.
|
||||
*
|
||||
* Ignore already configured format if exist
|
||||
*/
|
||||
if (!(configured_fmt & SND_SOC_DAIFMT_FORMAT_MASK))
|
||||
mask |= SND_SOC_DAIFMT_FORMAT_MASK;
|
||||
if (!(configured_fmt & SND_SOC_DAIFMT_CLOCK_MASK))
|
||||
mask |= SND_SOC_DAIFMT_CLOCK_MASK;
|
||||
if (!(configured_fmt & SND_SOC_DAIFMT_INV_MASK))
|
||||
mask |= SND_SOC_DAIFMT_INV_MASK;
|
||||
if (!(configured_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK))
|
||||
mask |= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
|
||||
|
||||
return configured_fmt | (fmt & mask);
|
||||
}
|
||||
|
||||
unsigned int snd_soc_dai_auto_select_format(const struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai_link *dai_link = rtd->dai_link;
|
||||
u64 possible_fmt = 0;
|
||||
|
||||
soc_dai_auto_select_format(~0, rtd, 0, &possible_fmt);
|
||||
|
||||
return soc_dai_convert_possiblefmt_to_daifmt(possible_fmt, dai_link->dai_fmt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user