Skip to content

Commit 1ae4f3f

Browse files
committed
ASoC: SOF: ipc4-topology: Add support for 8-bit formats
This patch enables use of 8-bit unsigned, A-law, and mu-law sample formats with IPC4 SOF. The ipc4-topology.h is updated with IPC4 sample types. The purpose is to to convert ALSA types to IPC4 types. The functions of_ipc4_update_hw_params(), sof_ipc4_get_valid_bits(), and new function sof_ipc4_get_sample_type() are updated to handle the sample type conversions. The function sof_ipc4_prepare_copier_module() is updated to set the DMA SCS bit for all non 32 bits sample types. The change to function sof_ipc4_get_valid_bits() returns 8 bits for these ALSA formats. The change to function sof_ipc4_prepare_copier_module() is needed to handle properly all non 32-bit formats with SCS bit set. To support playback with new 8 bits types, the sof_ipc4_init_input_audio_fmt() function is updated to get the sample type and use it in search for copier input pin format. To support capture, the sof_ipc4_init_output_audio_fmt() is updated similarly. Since the function uses separate out_ref_type argument, instead of single parameters struct, the out_ref_type needs to be added to every user of the function. Therefore functions sof_ipc4_prepare_copier_module(), sof_ipc4_prepare_gain_module(), sof_ipc4_prepare_mixer_module(), sof_ipc4_prepare_src_module(), and sof_ipc4_prepare_process_module() are updated to set the out_ref_type. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 3fc50b3 commit 1ae4f3f

2 files changed

Lines changed: 91 additions & 15 deletions

File tree

sound/soc/sof/ipc4-topology.c

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,10 +1342,27 @@ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw
13421342

13431343
if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) {
13441344
int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1345+
int type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg);
13451346
snd_pcm_format_t snd_fmt;
13461347
struct snd_mask *m;
13471348

13481349
switch (valid_bits) {
1350+
case 8:
1351+
switch (type) {
1352+
case SOF_IPC4_TYPE_A_LAW:
1353+
snd_fmt = SNDRV_PCM_FORMAT_A_LAW;
1354+
break;
1355+
case SOF_IPC4_TYPE_MU_LAW:
1356+
snd_fmt = SNDRV_PCM_FORMAT_MU_LAW;
1357+
break;
1358+
case SOF_IPC4_TYPE_UNSIGNED_INTEGER:
1359+
snd_fmt = SNDRV_PCM_FORMAT_U8;
1360+
break;
1361+
default:
1362+
dev_err(sdev->dev, "Unsupported PCM 8-bit IPC4 type %d\n", type);
1363+
return -EINVAL;
1364+
}
1365+
break;
13491366
case 16:
13501367
snd_fmt = SNDRV_PCM_FORMAT_S16_LE;
13511368
break;
@@ -1417,7 +1434,7 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
14171434
struct sof_ipc4_base_module_cfg *base_config,
14181435
struct sof_ipc4_available_audio_format *available_fmt,
14191436
u32 out_ref_rate, u32 out_ref_channels,
1420-
u32 out_ref_valid_bits)
1437+
u32 out_ref_valid_bits, u32 out_ref_type)
14211438
{
14221439
struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts;
14231440
u32 pin_fmts_size = available_fmt->num_output_formats;
@@ -1443,14 +1460,15 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
14431460
for (i = 0; i < pin_fmts_size; i++) {
14441461
struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt;
14451462

1446-
u32 _out_rate, _out_channels, _out_valid_bits;
1463+
u32 _out_rate, _out_channels, _out_valid_bits, _out_type;
14471464

14481465
_out_rate = fmt->sampling_frequency;
14491466
_out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
14501467
_out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1468+
_out_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg);
14511469

14521470
if (_out_rate == out_ref_rate && _out_channels == out_ref_channels &&
1453-
_out_valid_bits == out_ref_valid_bits)
1471+
_out_valid_bits == out_ref_valid_bits && _out_type == out_ref_type)
14541472
goto out_fmt;
14551473
}
14561474

@@ -1468,6 +1486,10 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
14681486
static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params)
14691487
{
14701488
switch (params_format(params)) {
1489+
case SNDRV_PCM_FORMAT_U8:
1490+
case SNDRV_PCM_FORMAT_MU_LAW:
1491+
case SNDRV_PCM_FORMAT_A_LAW:
1492+
return 8;
14711493
case SNDRV_PCM_FORMAT_S16_LE:
14721494
return 16;
14731495
case SNDRV_PCM_FORMAT_S24_LE:
@@ -1480,6 +1502,26 @@ static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_p
14801502
}
14811503
}
14821504

1505+
static int sof_ipc4_get_sample_type(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params)
1506+
{
1507+
switch (params_format(params)) {
1508+
case SNDRV_PCM_FORMAT_A_LAW:
1509+
return SOF_IPC4_TYPE_A_LAW;
1510+
case SNDRV_PCM_FORMAT_MU_LAW:
1511+
return SOF_IPC4_TYPE_MU_LAW;
1512+
case SNDRV_PCM_FORMAT_U8:
1513+
return SOF_IPC4_TYPE_UNSIGNED_INTEGER;
1514+
case SNDRV_PCM_FORMAT_S16_LE:
1515+
case SNDRV_PCM_FORMAT_S24_LE:
1516+
case SNDRV_PCM_FORMAT_S32_LE:
1517+
case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
1518+
return SOF_IPC4_TYPE_LSB_INTEGER;
1519+
default:
1520+
dev_err(sdev->dev, "invalid pcm sample type %d\n", params_format(params));
1521+
return -EINVAL;
1522+
}
1523+
}
1524+
14831525
static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14841526
struct snd_sof_widget *swidget,
14851527
struct sof_ipc4_base_module_cfg *base_config,
@@ -1491,8 +1533,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14911533
u32 valid_bits;
14921534
u32 channels;
14931535
u32 rate;
1536+
u32 type;
14941537
bool single_format;
14951538
int sample_valid_bits;
1539+
int sample_type;
14961540
int i = 0;
14971541

14981542
if (!pin_fmts_size) {
@@ -1508,6 +1552,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
15081552
if (sample_valid_bits < 0)
15091553
return sample_valid_bits;
15101554

1555+
sample_type = sof_ipc4_get_sample_type(sdev, params);
1556+
if (sample_type < 0)
1557+
return sample_type;
1558+
15111559
/*
15121560
* Search supported input audio formats with pin index 0 to match rate, channels and
15131561
* sample_valid_bits from reference params
@@ -1521,8 +1569,9 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
15211569
rate = fmt->sampling_frequency;
15221570
channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
15231571
valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1572+
type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg);
15241573
if (params_rate(params) == rate && params_channels(params) == channels &&
1525-
sample_valid_bits == valid_bits)
1574+
sample_valid_bits == valid_bits && sample_type == type)
15261575
break;
15271576
}
15281577

@@ -1943,7 +1992,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
19431992
int *ipc_config_size;
19441993
u32 **data;
19451994
int ipc_size, ret, out_ref_valid_bits;
1946-
u32 out_ref_rate, out_ref_channels;
1995+
u32 out_ref_rate, out_ref_channels, out_ref_type;
19471996
u32 deep_buffer_dma_ms = 0;
19481997
bool single_output_bitdepth;
19491998
int i;
@@ -1984,10 +2033,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
19842033
host_dma_id = platform_params->stream_tag - 1;
19852034
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id);
19862035

1987-
/* Set SCS bit for S16_LE format only */
19882036
if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE)
19892037
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK;
19902038

2039+
/* Set SCS bit for 8 and 16 bit formats */
2040+
if (params_physical_width(fe_params) <= 16)
2041+
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK;
2042+
19912043
/*
19922044
* Despite its name the bitfield 'fifo_size' is used to define DMA buffer
19932045
* size. The expression calculates 2ms buffer size.
@@ -2112,6 +2164,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
21122164
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
21132165
out_ref_rate = in_fmt->sampling_frequency;
21142166
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2167+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
21152168

21162169
if (!single_output_bitdepth)
21172170
out_ref_valid_bits =
@@ -2122,6 +2175,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
21222175
case snd_soc_dapm_dai_in:
21232176
out_ref_rate = params_rate(fe_params);
21242177
out_ref_channels = params_channels(fe_params);
2178+
out_ref_type = sof_ipc4_get_sample_type(sdev, fe_params);
2179+
if (out_ref_type < 0)
2180+
return out_ref_type;
2181+
21252182
if (!single_output_bitdepth) {
21262183
out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params);
21272184
if (out_ref_valid_bits < 0)
@@ -2146,12 +2203,14 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
21462203
out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt;
21472204
out_ref_valid_bits =
21482205
SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
2206+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(out_fmt->fmt_cfg);
21492207
}
21502208

21512209
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
21522210
&copier_data->base_config,
21532211
available_fmt, out_ref_rate,
2154-
out_ref_channels, out_ref_valid_bits);
2212+
out_ref_channels, out_ref_valid_bits,
2213+
out_ref_type);
21552214
if (output_fmt_index < 0)
21562215
return output_fmt_index;
21572216

@@ -2380,7 +2439,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
23802439
struct sof_ipc4_gain *gain = swidget->private;
23812440
struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt;
23822441
struct sof_ipc4_audio_format *in_fmt;
2383-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2442+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
23842443
int input_fmt_index, output_fmt_index;
23852444

23862445
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2394,13 +2453,15 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
23942453
out_ref_rate = in_fmt->sampling_frequency;
23952454
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
23962455
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2456+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
23972457

23982458
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
23992459
&gain->data.base_config,
24002460
available_fmt,
24012461
out_ref_rate,
24022462
out_ref_channels,
2403-
out_ref_valid_bits);
2463+
out_ref_valid_bits,
2464+
out_ref_type);
24042465
if (output_fmt_index < 0)
24052466
return output_fmt_index;
24062467

@@ -2423,7 +2484,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
24232484
struct sof_ipc4_mixer *mixer = swidget->private;
24242485
struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt;
24252486
struct sof_ipc4_audio_format *in_fmt;
2426-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2487+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
24272488
int input_fmt_index, output_fmt_index;
24282489

24292490
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2437,13 +2498,15 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
24372498
out_ref_rate = in_fmt->sampling_frequency;
24382499
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
24392500
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2501+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
24402502

24412503
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
24422504
&mixer->base_config,
24432505
available_fmt,
24442506
out_ref_rate,
24452507
out_ref_channels,
2446-
out_ref_valid_bits);
2508+
out_ref_valid_bits,
2509+
out_ref_type);
24472510
if (output_fmt_index < 0)
24482511
return output_fmt_index;
24492512

@@ -2467,7 +2530,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
24672530
struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt;
24682531
struct sof_ipc4_audio_format *out_audio_fmt;
24692532
struct sof_ipc4_audio_format *in_audio_fmt;
2470-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2533+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
24712534
int output_fmt_index, input_fmt_index;
24722535

24732536
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2494,6 +2557,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
24942557
in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
24952558
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg);
24962559
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg);
2560+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_audio_fmt->fmt_cfg);
24972561

24982562
/*
24992563
* For capture, the SRC module should convert the rate to match the rate requested by the
@@ -2507,7 +2571,8 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
25072571
available_fmt,
25082572
out_ref_rate,
25092573
out_ref_channels,
2510-
out_ref_valid_bits);
2574+
out_ref_valid_bits,
2575+
out_ref_type);
25112576
if (output_fmt_index < 0)
25122577
return output_fmt_index;
25132578

@@ -2631,20 +2696,22 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
26312696
struct sof_ipc4_audio_format *in_fmt;
26322697
struct sof_ipc4_pin_format *pin_fmt;
26332698
u32 out_ref_rate, out_ref_channels;
2634-
int out_ref_valid_bits;
2699+
int out_ref_valid_bits, out_ref_type;
26352700

26362701
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
26372702

26382703
out_ref_rate = in_fmt->sampling_frequency;
26392704
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
26402705
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2706+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
26412707

26422708
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
26432709
&process->base_config,
26442710
available_fmt,
26452711
out_ref_rate,
26462712
out_ref_channels,
2647-
out_ref_valid_bits);
2713+
out_ref_valid_bits,
2714+
out_ref_type);
26482715
if (output_fmt_index < 0)
26492716
return output_fmt_index;
26502717

sound/soc/sof/ipc4-topology.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@
4141
#define SOF_IPC4_FW_MAX_PAGE_COUNT 20
4242
#define SOF_IPC4_FW_MAX_QUEUE_COUNT 8
4343

44+
/* IPC4 sample types */
45+
#define SOF_IPC4_TYPE_MSB_INTEGER 0
46+
#define SOF_IPC4_TYPE_LSB_INTEGER 1
47+
#define SOF_IPC4_TYPE_SIGNED_INTEGER 2
48+
#define SOF_IPC4_TYPE_UNSIGNED_INTEGER 3
49+
#define SOF_IPC4_TYPE_FLOAT 4
50+
#define SOF_IPC4_TYPE_A_LAW 5
51+
#define SOF_IPC4_TYPE_MU_LAW 6
52+
4453
/* Node index and mask applicable for host copier and ALH/HDA type DAI copiers */
4554
#define SOF_IPC4_NODE_INDEX_MASK 0xFF
4655
#define SOF_IPC4_NODE_INDEX(x) ((x) & SOF_IPC4_NODE_INDEX_MASK)

0 commit comments

Comments
 (0)