Skip to content

Commit c6b09cd

Browse files
morimotobroonie
authored andcommitted
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>
1 parent 97c7d3d commit c6b09cd

3 files changed

Lines changed: 166 additions & 193 deletions

File tree

include/sound/soc-dai.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ struct clk;
8181
/*
8282
* define GATED -> CONT. GATED will be selected if both are selected.
8383
* see
84-
* snd_soc_runtime_get_dai_fmt()
84+
* soc_dai_convert_possiblefmt_to_daifmt()
8585
*/
8686
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT 16
87-
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
87+
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
8888
#define SND_SOC_POSSIBLE_DAIFMT_GATED (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
8989
#define SND_SOC_POSSIBLE_DAIFMT_CONT (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
9090

@@ -184,8 +184,7 @@ int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio);
184184
void snd_soc_dai_set_bclk_clk(struct snd_soc_dai *dai, struct clk *bclk);
185185

186186
/* Digital Audio interface formatting */
187-
int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd);
188-
u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority);
187+
unsigned int snd_soc_dai_auto_select_format(const struct snd_soc_pcm_runtime *rtd);
189188
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
190189

191190
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,

sound/soc/soc-core.c

Lines changed: 1 addition & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,148 +1284,6 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card,
12841284
}
12851285
EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtimes);
12861286

1287-
static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd)
1288-
{
1289-
struct snd_soc_dai_link *dai_link = rtd->dai_link;
1290-
struct snd_soc_dai *dai, *not_used;
1291-
u64 pos, possible_fmt;
1292-
unsigned int mask = 0, dai_fmt = 0;
1293-
int i, j, priority, pri, until;
1294-
1295-
/*
1296-
* Get selectable format from each DAIs.
1297-
*
1298-
****************************
1299-
* NOTE
1300-
* Using .auto_selectable_formats is not mandatory,
1301-
* we can select format manually from Sound Card.
1302-
* When use it, driver should list well tested format only.
1303-
****************************
1304-
*
1305-
* ex)
1306-
* auto_selectable_formats (= SND_SOC_POSSIBLE_xxx)
1307-
* (A) (B) (C)
1308-
* DAI0_: { 0x000F, 0x00F0, 0x0F00 };
1309-
* DAI1 : { 0xF000, 0x0F00 };
1310-
* (X) (Y)
1311-
*
1312-
* "until" will be 3 in this case (MAX array size from DAI0 and DAI1)
1313-
* Here is dev_dbg() message and comments
1314-
*
1315-
* priority = 1
1316-
* DAI0: (pri, fmt) = (1, 000000000000000F) // 1st check (A) DAI1 is not selected
1317-
* DAI1: (pri, fmt) = (0, 0000000000000000) // Necessary Waste
1318-
* DAI0: (pri, fmt) = (1, 000000000000000F) // 2nd check (A)
1319-
* DAI1: (pri, fmt) = (1, 000000000000F000) // (X)
1320-
* priority = 2
1321-
* DAI0: (pri, fmt) = (2, 00000000000000FF) // 3rd check (A) + (B)
1322-
* DAI1: (pri, fmt) = (1, 000000000000F000) // (X)
1323-
* DAI0: (pri, fmt) = (2, 00000000000000FF) // 4th check (A) + (B)
1324-
* DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y)
1325-
* priority = 3
1326-
* DAI0: (pri, fmt) = (3, 0000000000000FFF) // 5th check (A) + (B) + (C)
1327-
* DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y)
1328-
* found auto selected format: 0000000000000F00
1329-
*/
1330-
until = snd_soc_dai_get_fmt_max_priority(rtd);
1331-
for (priority = 1; priority <= until; priority++) {
1332-
for_each_rtd_dais(rtd, j, not_used) {
1333-
1334-
possible_fmt = ULLONG_MAX;
1335-
for_each_rtd_dais(rtd, i, dai) {
1336-
u64 fmt = 0;
1337-
1338-
pri = (j >= i) ? priority : priority - 1;
1339-
fmt = snd_soc_dai_get_fmt(dai, pri);
1340-
possible_fmt &= fmt;
1341-
}
1342-
if (possible_fmt)
1343-
goto found;
1344-
}
1345-
}
1346-
/* Not Found */
1347-
return;
1348-
found:
1349-
/*
1350-
* convert POSSIBLE_DAIFMT to DAIFMT
1351-
*
1352-
* Some basic/default settings on each is defined as 0.
1353-
* see
1354-
* SND_SOC_DAIFMT_NB_NF
1355-
* SND_SOC_DAIFMT_GATED
1356-
*
1357-
* SND_SOC_DAIFMT_xxx_MASK can't notice it if Sound Card specify
1358-
* these value, and will be overwrite to auto selected value.
1359-
*
1360-
* To avoid such issue, loop from 63 to 0 here.
1361-
* Small number of SND_SOC_POSSIBLE_xxx will be Hi priority.
1362-
* Basic/Default settings of each part and above are defined
1363-
* as Hi priority (= small number) of SND_SOC_POSSIBLE_xxx.
1364-
*/
1365-
for (i = 63; i >= 0; i--) {
1366-
pos = 1ULL << i;
1367-
switch (possible_fmt & pos) {
1368-
/*
1369-
* for format
1370-
*/
1371-
case SND_SOC_POSSIBLE_DAIFMT_I2S:
1372-
case SND_SOC_POSSIBLE_DAIFMT_RIGHT_J:
1373-
case SND_SOC_POSSIBLE_DAIFMT_LEFT_J:
1374-
case SND_SOC_POSSIBLE_DAIFMT_DSP_A:
1375-
case SND_SOC_POSSIBLE_DAIFMT_DSP_B:
1376-
case SND_SOC_POSSIBLE_DAIFMT_AC97:
1377-
case SND_SOC_POSSIBLE_DAIFMT_PDM:
1378-
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | i;
1379-
break;
1380-
/*
1381-
* for clock
1382-
*/
1383-
case SND_SOC_POSSIBLE_DAIFMT_CONT:
1384-
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_CONT;
1385-
break;
1386-
case SND_SOC_POSSIBLE_DAIFMT_GATED:
1387-
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_GATED;
1388-
break;
1389-
/*
1390-
* for clock invert
1391-
*/
1392-
case SND_SOC_POSSIBLE_DAIFMT_NB_NF:
1393-
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_NF;
1394-
break;
1395-
case SND_SOC_POSSIBLE_DAIFMT_NB_IF:
1396-
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_IF;
1397-
break;
1398-
case SND_SOC_POSSIBLE_DAIFMT_IB_NF:
1399-
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_NF;
1400-
break;
1401-
case SND_SOC_POSSIBLE_DAIFMT_IB_IF:
1402-
dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_IF;
1403-
break;
1404-
}
1405-
}
1406-
1407-
/*
1408-
* Some driver might have very complex limitation.
1409-
* In such case, user want to auto-select non-limitation part,
1410-
* and want to manually specify complex part.
1411-
*
1412-
* Or for example, if both CPU and Codec can be clock provider,
1413-
* but because of its quality, user want to specify it manually.
1414-
*
1415-
* Use manually specified settings if sound card did.
1416-
*/
1417-
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK))
1418-
mask |= SND_SOC_DAIFMT_FORMAT_MASK;
1419-
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_MASK))
1420-
mask |= SND_SOC_DAIFMT_CLOCK_MASK;
1421-
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_INV_MASK))
1422-
mask |= SND_SOC_DAIFMT_INV_MASK;
1423-
if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK))
1424-
mask |= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
1425-
1426-
dai_link->dai_fmt |= (dai_fmt & mask);
1427-
}
1428-
14291287
/**
14301288
* snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime
14311289
* @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,
15041362
if (ret < 0)
15051363
return ret;
15061364

1507-
snd_soc_runtime_get_dai_fmt(rtd);
1508-
ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
1365+
ret = snd_soc_runtime_set_dai_fmt(rtd, snd_soc_dai_auto_select_format(rtd));
15091366
if (ret)
15101367
goto err;
15111368

0 commit comments

Comments
 (0)