Skip to content

Commit a742f2c

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. They are updated 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. Change to function sof_ipc4_get_valid_bits() returns 8 bits for these ALSA formats. 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 12a9259 commit a742f2c

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
@@ -1300,10 +1300,27 @@ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw
13001300

13011301
if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) {
13021302
int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1303+
int type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg);
13031304
snd_pcm_format_t snd_fmt;
13041305
struct snd_mask *m;
13051306

13061307
switch (valid_bits) {
1308+
case 8:
1309+
switch (type) {
1310+
case SOF_IPC4_TYPE_A_LAW:
1311+
snd_fmt = SNDRV_PCM_FORMAT_A_LAW;
1312+
break;
1313+
case SOF_IPC4_TYPE_MU_LAW:
1314+
snd_fmt = SNDRV_PCM_FORMAT_MU_LAW;
1315+
break;
1316+
case SOF_IPC4_TYPE_UNSIGNED_INTEGER:
1317+
snd_fmt = SNDRV_PCM_FORMAT_U8;
1318+
break;
1319+
default:
1320+
dev_err(sdev->dev, "Unsupported PCM 8-bit IPC4 type %d\n", type);
1321+
return -EINVAL;
1322+
}
1323+
break;
13071324
case 16:
13081325
snd_fmt = SNDRV_PCM_FORMAT_S16_LE;
13091326
break;
@@ -1375,7 +1392,7 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
13751392
struct sof_ipc4_base_module_cfg *base_config,
13761393
struct sof_ipc4_available_audio_format *available_fmt,
13771394
u32 out_ref_rate, u32 out_ref_channels,
1378-
u32 out_ref_valid_bits)
1395+
u32 out_ref_valid_bits, u32 out_ref_type)
13791396
{
13801397
struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts;
13811398
u32 pin_fmts_size = available_fmt->num_output_formats;
@@ -1401,14 +1418,15 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
14011418
for (i = 0; i < pin_fmts_size; i++) {
14021419
struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt;
14031420

1404-
u32 _out_rate, _out_channels, _out_valid_bits;
1421+
u32 _out_rate, _out_channels, _out_valid_bits, _out_type;
14051422

14061423
_out_rate = fmt->sampling_frequency;
14071424
_out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
14081425
_out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1426+
_out_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg);
14091427

14101428
if (_out_rate == out_ref_rate && _out_channels == out_ref_channels &&
1411-
_out_valid_bits == out_ref_valid_bits)
1429+
_out_valid_bits == out_ref_valid_bits && _out_type == out_ref_type)
14121430
goto out_fmt;
14131431
}
14141432

@@ -1426,6 +1444,10 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
14261444
static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params)
14271445
{
14281446
switch (params_format(params)) {
1447+
case SNDRV_PCM_FORMAT_U8:
1448+
case SNDRV_PCM_FORMAT_MU_LAW:
1449+
case SNDRV_PCM_FORMAT_A_LAW:
1450+
return 8;
14291451
case SNDRV_PCM_FORMAT_S16_LE:
14301452
return 16;
14311453
case SNDRV_PCM_FORMAT_S24_LE:
@@ -1438,6 +1460,25 @@ static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_p
14381460
}
14391461
}
14401462

1463+
static int sof_ipc4_get_sample_type(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params)
1464+
{
1465+
switch (params_format(params)) {
1466+
case SNDRV_PCM_FORMAT_A_LAW:
1467+
return SOF_IPC4_TYPE_A_LAW;
1468+
case SNDRV_PCM_FORMAT_MU_LAW:
1469+
return SOF_IPC4_TYPE_MU_LAW;
1470+
case SNDRV_PCM_FORMAT_U8:
1471+
return SOF_IPC4_TYPE_UNSIGNED_INTEGER;
1472+
case SNDRV_PCM_FORMAT_S16_LE:
1473+
case SNDRV_PCM_FORMAT_S24_LE:
1474+
case SNDRV_PCM_FORMAT_S32_LE:
1475+
return SOF_IPC4_TYPE_LSB_INTEGER;
1476+
default:
1477+
dev_err(sdev->dev, "invalid pcm sample type %d\n", params_format(params));
1478+
return -EINVAL;
1479+
}
1480+
}
1481+
14411482
static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14421483
struct snd_sof_widget *swidget,
14431484
struct sof_ipc4_base_module_cfg *base_config,
@@ -1449,8 +1490,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14491490
u32 valid_bits;
14501491
u32 channels;
14511492
u32 rate;
1493+
u32 type;
14521494
bool single_format;
14531495
int sample_valid_bits;
1496+
int sample_type;
14541497
int i = 0;
14551498

14561499
if (!pin_fmts_size) {
@@ -1466,6 +1509,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14661509
if (sample_valid_bits < 0)
14671510
return sample_valid_bits;
14681511

1512+
sample_type = sof_ipc4_get_sample_type(sdev, params);
1513+
if (sample_type < 0)
1514+
return sample_type;
1515+
14691516
/*
14701517
* Search supported input audio formats with pin index 0 to match rate, channels and
14711518
* sample_valid_bits from reference params
@@ -1479,8 +1526,9 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
14791526
rate = fmt->sampling_frequency;
14801527
channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
14811528
valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1529+
type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg);
14821530
if (params_rate(params) == rate && params_channels(params) == channels &&
1483-
sample_valid_bits == valid_bits)
1531+
sample_valid_bits == valid_bits && sample_type == type)
14841532
break;
14851533
}
14861534

@@ -1901,7 +1949,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
19011949
int *ipc_config_size;
19021950
u32 **data;
19031951
int ipc_size, ret, out_ref_valid_bits;
1904-
u32 out_ref_rate, out_ref_channels;
1952+
u32 out_ref_rate, out_ref_channels, out_ref_type;
19051953
u32 deep_buffer_dma_ms = 0;
19061954
bool single_output_bitdepth;
19071955
int i;
@@ -1942,10 +1990,20 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
19421990
host_dma_id = platform_params->stream_tag - 1;
19431991
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id);
19441992

1945-
/* Set SCS bit for S16_LE format only */
19461993
if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE)
19471994
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK;
19481995

1996+
/* Set SCS bit for 8 and 16 bit formats */
1997+
switch (params_format(fe_params)) {
1998+
case SNDRV_PCM_FORMAT_S16_LE:
1999+
case SNDRV_PCM_FORMAT_U8:
2000+
case SNDRV_PCM_FORMAT_A_LAW:
2001+
case SNDRV_PCM_FORMAT_MU_LAW:
2002+
pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK;
2003+
default:
2004+
break;
2005+
}
2006+
19492007
/*
19502008
* Despite its name the bitfield 'fifo_size' is used to define DMA buffer
19512009
* size. The expression calculates 2ms buffer size.
@@ -2070,6 +2128,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
20702128
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
20712129
out_ref_rate = in_fmt->sampling_frequency;
20722130
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2131+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
20732132

20742133
if (!single_output_bitdepth)
20752134
out_ref_valid_bits =
@@ -2080,6 +2139,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
20802139
case snd_soc_dapm_dai_in:
20812140
out_ref_rate = params_rate(fe_params);
20822141
out_ref_channels = params_channels(fe_params);
2142+
out_ref_type = sof_ipc4_get_sample_type(sdev, fe_params);
2143+
if (out_ref_type < 0)
2144+
return out_ref_type;
2145+
20832146
if (!single_output_bitdepth) {
20842147
out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params);
20852148
if (out_ref_valid_bits < 0)
@@ -2104,12 +2167,14 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
21042167
out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt;
21052168
out_ref_valid_bits =
21062169
SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
2170+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(out_fmt->fmt_cfg);
21072171
}
21082172

21092173
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
21102174
&copier_data->base_config,
21112175
available_fmt, out_ref_rate,
2112-
out_ref_channels, out_ref_valid_bits);
2176+
out_ref_channels, out_ref_valid_bits,
2177+
out_ref_type);
21132178
if (output_fmt_index < 0)
21142179
return output_fmt_index;
21152180

@@ -2338,7 +2403,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
23382403
struct sof_ipc4_gain *gain = swidget->private;
23392404
struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt;
23402405
struct sof_ipc4_audio_format *in_fmt;
2341-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2406+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
23422407
int input_fmt_index, output_fmt_index;
23432408

23442409
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2352,13 +2417,15 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
23522417
out_ref_rate = in_fmt->sampling_frequency;
23532418
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
23542419
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2420+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
23552421

23562422
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
23572423
&gain->data.base_config,
23582424
available_fmt,
23592425
out_ref_rate,
23602426
out_ref_channels,
2361-
out_ref_valid_bits);
2427+
out_ref_valid_bits,
2428+
out_ref_type);
23622429
if (output_fmt_index < 0)
23632430
return output_fmt_index;
23642431

@@ -2381,7 +2448,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
23812448
struct sof_ipc4_mixer *mixer = swidget->private;
23822449
struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt;
23832450
struct sof_ipc4_audio_format *in_fmt;
2384-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2451+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
23852452
int input_fmt_index, output_fmt_index;
23862453

23872454
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2395,13 +2462,15 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
23952462
out_ref_rate = in_fmt->sampling_frequency;
23962463
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
23972464
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2465+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
23982466

23992467
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
24002468
&mixer->base_config,
24012469
available_fmt,
24022470
out_ref_rate,
24032471
out_ref_channels,
2404-
out_ref_valid_bits);
2472+
out_ref_valid_bits,
2473+
out_ref_type);
24052474
if (output_fmt_index < 0)
24062475
return output_fmt_index;
24072476

@@ -2425,7 +2494,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
24252494
struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt;
24262495
struct sof_ipc4_audio_format *out_audio_fmt;
24272496
struct sof_ipc4_audio_format *in_audio_fmt;
2428-
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
2497+
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
24292498
int output_fmt_index, input_fmt_index;
24302499

24312500
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
@@ -2452,6 +2521,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
24522521
in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
24532522
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg);
24542523
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg);
2524+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_audio_fmt->fmt_cfg);
24552525

24562526
/*
24572527
* For capture, the SRC module should convert the rate to match the rate requested by the
@@ -2465,7 +2535,8 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
24652535
available_fmt,
24662536
out_ref_rate,
24672537
out_ref_channels,
2468-
out_ref_valid_bits);
2538+
out_ref_valid_bits,
2539+
out_ref_type);
24692540
if (output_fmt_index < 0)
24702541
return output_fmt_index;
24712542

@@ -2589,20 +2660,22 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
25892660
struct sof_ipc4_audio_format *in_fmt;
25902661
struct sof_ipc4_pin_format *pin_fmt;
25912662
u32 out_ref_rate, out_ref_channels;
2592-
int out_ref_valid_bits;
2663+
int out_ref_valid_bits, out_ref_type;
25932664

25942665
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
25952666

25962667
out_ref_rate = in_fmt->sampling_frequency;
25972668
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
25982669
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2670+
out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg);
25992671

26002672
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
26012673
&process->base_config,
26022674
available_fmt,
26032675
out_ref_rate,
26042676
out_ref_channels,
2605-
out_ref_valid_bits);
2677+
out_ref_valid_bits,
2678+
out_ref_type);
26062679
if (output_fmt_index < 0)
26072680
return output_fmt_index;
26082681

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)