Skip to content

Commit 9e2921c

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 9e2921c

2 files changed

Lines changed: 97 additions & 15 deletions

File tree

sound/soc/sof/ipc4-topology.c

Lines changed: 88 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,25 @@ 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+
return SOF_IPC4_TYPE_LSB_INTEGER;
1518+
default:
1519+
dev_err(sdev->dev, "invalid pcm sample type %d\n", params_format(params));
1520+
return -EINVAL;
1521+
}
1522+
}
1523+
14831524
static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14841525
struct snd_sof_widget *swidget,
14851526
struct sof_ipc4_base_module_cfg *base_config,
@@ -1491,8 +1532,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14911532
u32 valid_bits;
14921533
u32 channels;
14931534
u32 rate;
1535+
u32 type;
14941536
bool single_format;
14951537
int sample_valid_bits;
1538+
int sample_type;
14961539
int i = 0;
14971540

14981541
if (!pin_fmts_size) {
@@ -1508,6 +1551,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
15081551
if (sample_valid_bits < 0)
15091552
return sample_valid_bits;
15101553

1554+
sample_type = sof_ipc4_get_sample_type(sdev, params);
1555+
if (sample_type < 0)
1556+
return sample_type;
1557+
15111558
/*
15121559
* Search supported input audio formats with pin index 0 to match rate, channels and
15131560
* sample_valid_bits from reference params
@@ -1521,8 +1568,9 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
15211568
rate = fmt->sampling_frequency;
15221569
channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
15231570
valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1571+
type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg);
15241572
if (params_rate(params) == rate && params_channels(params) == channels &&
1525-
sample_valid_bits == valid_bits)
1573+
sample_valid_bits == valid_bits && sample_type == type)
15261574
break;
15271575
}
15281576

@@ -1943,7 +1991,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
19431991
int *ipc_config_size;
19441992
u32 **data;
19451993
int ipc_size, ret, out_ref_valid_bits;
1946-
u32 out_ref_rate, out_ref_channels;
1994+
u32 out_ref_rate, out_ref_channels, out_ref_type;
19471995
u32 deep_buffer_dma_ms = 0;
19481996
bool single_output_bitdepth;
19491997
int i;
@@ -1984,10 +2032,20 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
19842032
host_dma_id = platform_params->stream_tag - 1;
19852033
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id);
19862034

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

2038+
/* Set SCS bit for 8 and 16 bit formats */
2039+
switch (params_format(fe_params)) {
2040+
case SNDRV_PCM_FORMAT_S16_LE:
2041+
case SNDRV_PCM_FORMAT_U8:
2042+
case SNDRV_PCM_FORMAT_A_LAW:
2043+
case SNDRV_PCM_FORMAT_MU_LAW:
2044+
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK;
2045+
default:
2046+
break;
2047+
}
2048+
19912049
/*
19922050
* Despite its name the bitfield 'fifo_size' is used to define DMA buffer
19932051
* size. The expression calculates 2ms buffer size.
@@ -2112,6 +2170,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
21122170
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
21132171
out_ref_rate = in_fmt->sampling_frequency;
21142172
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2173+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
21152174

21162175
if (!single_output_bitdepth)
21172176
out_ref_valid_bits =
@@ -2122,6 +2181,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
21222181
case snd_soc_dapm_dai_in:
21232182
out_ref_rate = params_rate(fe_params);
21242183
out_ref_channels = params_channels(fe_params);
2184+
out_ref_type = sof_ipc4_get_sample_type(sdev, fe_params);
2185+
if (out_ref_type < 0)
2186+
return out_ref_type;
2187+
21252188
if (!single_output_bitdepth) {
21262189
out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params);
21272190
if (out_ref_valid_bits < 0)
@@ -2146,12 +2209,14 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
21462209
out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt;
21472210
out_ref_valid_bits =
21482211
SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
2212+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(out_fmt->fmt_cfg);
21492213
}
21502214

21512215
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
21522216
&copier_data->base_config,
21532217
available_fmt, out_ref_rate,
2154-
out_ref_channels, out_ref_valid_bits);
2218+
out_ref_channels, out_ref_valid_bits,
2219+
out_ref_type);
21552220
if (output_fmt_index < 0)
21562221
return output_fmt_index;
21572222

@@ -2380,7 +2445,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
23802445
struct sof_ipc4_gain *gain = swidget->private;
23812446
struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt;
23822447
struct sof_ipc4_audio_format *in_fmt;
2383-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2448+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
23842449
int input_fmt_index, output_fmt_index;
23852450

23862451
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2394,13 +2459,15 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
23942459
out_ref_rate = in_fmt->sampling_frequency;
23952460
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
23962461
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2462+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
23972463

23982464
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
23992465
&gain->data.base_config,
24002466
available_fmt,
24012467
out_ref_rate,
24022468
out_ref_channels,
2403-
out_ref_valid_bits);
2469+
out_ref_valid_bits,
2470+
out_ref_type);
24042471
if (output_fmt_index < 0)
24052472
return output_fmt_index;
24062473

@@ -2423,7 +2490,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
24232490
struct sof_ipc4_mixer *mixer = swidget->private;
24242491
struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt;
24252492
struct sof_ipc4_audio_format *in_fmt;
2426-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2493+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
24272494
int input_fmt_index, output_fmt_index;
24282495

24292496
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2437,13 +2504,15 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
24372504
out_ref_rate = in_fmt->sampling_frequency;
24382505
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
24392506
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2507+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
24402508

24412509
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
24422510
&mixer->base_config,
24432511
available_fmt,
24442512
out_ref_rate,
24452513
out_ref_channels,
2446-
out_ref_valid_bits);
2514+
out_ref_valid_bits,
2515+
out_ref_type);
24472516
if (output_fmt_index < 0)
24482517
return output_fmt_index;
24492518

@@ -2467,7 +2536,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
24672536
struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt;
24682537
struct sof_ipc4_audio_format *out_audio_fmt;
24692538
struct sof_ipc4_audio_format *in_audio_fmt;
2470-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2539+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
24712540
int output_fmt_index, input_fmt_index;
24722541

24732542
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2494,6 +2563,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
24942563
in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
24952564
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg);
24962565
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg);
2566+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_audio_fmt->fmt_cfg);
24972567

24982568
/*
24992569
* For capture, the SRC module should convert the rate to match the rate requested by the
@@ -2507,7 +2577,8 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
25072577
available_fmt,
25082578
out_ref_rate,
25092579
out_ref_channels,
2510-
out_ref_valid_bits);
2580+
out_ref_valid_bits,
2581+
out_ref_type);
25112582
if (output_fmt_index < 0)
25122583
return output_fmt_index;
25132584

@@ -2631,20 +2702,22 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
26312702
struct sof_ipc4_audio_format *in_fmt;
26322703
struct sof_ipc4_pin_format *pin_fmt;
26332704
u32 out_ref_rate, out_ref_channels;
2634-
int out_ref_valid_bits;
2705+
int out_ref_valid_bits, out_ref_type;
26352706

26362707
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
26372708

26382709
out_ref_rate = in_fmt->sampling_frequency;
26392710
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
26402711
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2712+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
26412713

26422714
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
26432715
&process->base_config,
26442716
available_fmt,
26452717
out_ref_rate,
26462718
out_ref_channels,
2647-
out_ref_valid_bits);
2719+
out_ref_valid_bits,
2720+
out_ref_type);
26482721
if (output_fmt_index < 0)
26492722
return output_fmt_index;
26502723

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)