Uh oh!
There was an error while loading. Please reload this page.
forked from torvalds/linux
- Notifications
You must be signed in to change notification settings - Fork 150
ASoC: SOF: ipc-topology: Add float and 8-bit formats#5401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
bardliao
merged 2 commits into
thesofproject:topic/sof-dev
from
singalsu:add_8bit_supportJun 23, 2025
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1342,18 +1342,45 @@ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw | ||
| if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) { | ||
| int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); | ||
| int type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg); | ||
| snd_pcm_format_t snd_fmt; | ||
| struct snd_mask *m; | ||
| switch (valid_bits) { | ||
| case 8: | ||
| switch (type) { | ||
| case SOF_IPC4_TYPE_A_LAW: | ||
| snd_fmt = SNDRV_PCM_FORMAT_A_LAW; | ||
| break; | ||
| case SOF_IPC4_TYPE_MU_LAW: | ||
| snd_fmt = SNDRV_PCM_FORMAT_MU_LAW; | ||
| break; | ||
| case SOF_IPC4_TYPE_UNSIGNED_INTEGER: | ||
| snd_fmt = SNDRV_PCM_FORMAT_U8; | ||
| break; | ||
| default: | ||
| dev_err(sdev->dev, "Unsupported PCM 8-bit IPC4 type %d\n", type); | ||
| return -EINVAL; | ||
| } | ||
| break; | ||
| case 16: | ||
| snd_fmt = SNDRV_PCM_FORMAT_S16_LE; | ||
| break; | ||
| case 24: | ||
| snd_fmt = SNDRV_PCM_FORMAT_S24_LE; | ||
| break; | ||
| case 32: | ||
| snd_fmt = SNDRV_PCM_FORMAT_S32_LE; | ||
| switch (type) { | ||
| case SOF_IPC4_TYPE_LSB_INTEGER: | ||
| snd_fmt = SNDRV_PCM_FORMAT_S32_LE; | ||
| break; | ||
| case SOF_IPC4_TYPE_FLOAT: | ||
| snd_fmt = SNDRV_PCM_FORMAT_FLOAT_LE; | ||
| break; | ||
| default: | ||
| dev_err(sdev->dev, "Unsupported PCM 32-bit IPC4 type %d\n", type); | ||
| return -EINVAL; | ||
| } | ||
| break; | ||
| default: | ||
| dev_err(sdev->dev, "invalid PCM valid_bits %d\n", valid_bits); | ||
| @@ -1417,7 +1444,7 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, | ||
| struct sof_ipc4_base_module_cfg *base_config, | ||
| struct sof_ipc4_available_audio_format *available_fmt, | ||
| u32 out_ref_rate, u32 out_ref_channels, | ||
| u32 out_ref_valid_bits) | ||
| u32 out_ref_valid_bits, u32 out_ref_type) | ||
| { | ||
| struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts; | ||
| u32 pin_fmts_size = available_fmt->num_output_formats; | ||
| @@ -1443,14 +1470,15 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, | ||
| for (i = 0; i < pin_fmts_size; i++) { | ||
| struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; | ||
| u32 _out_rate, _out_channels, _out_valid_bits; | ||
| u32 _out_rate, _out_channels, _out_valid_bits, _out_type; | ||
| _out_rate = fmt->sampling_frequency; | ||
| _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); | ||
| _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); | ||
| _out_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg); | ||
| if (_out_rate == out_ref_rate && _out_channels == out_ref_channels && | ||
| _out_valid_bits == out_ref_valid_bits) | ||
| _out_valid_bits == out_ref_valid_bits && _out_type == out_ref_type) | ||
| goto out_fmt; | ||
| } | ||
| @@ -1468,18 +1496,46 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, | ||
| static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params) | ||
| { | ||
| switch (params_format(params)) { | ||
| case SNDRV_PCM_FORMAT_U8: | ||
| case SNDRV_PCM_FORMAT_MU_LAW: | ||
| case SNDRV_PCM_FORMAT_A_LAW: | ||
| return 8; | ||
| case SNDRV_PCM_FORMAT_S16_LE: | ||
| return 16; | ||
| case SNDRV_PCM_FORMAT_S24_LE: | ||
| return 24; | ||
| case SNDRV_PCM_FORMAT_S32_LE: | ||
| return 32; | ||
| case SNDRV_PCM_FORMAT_FLOAT_LE: | ||
| return 32; | ||
| default: | ||
| dev_err(sdev->dev, "invalid pcm frame format %d\n", params_format(params)); | ||
| return -EINVAL; | ||
| } | ||
| } | ||
| static int sof_ipc4_get_sample_type(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params) | ||
| { | ||
| switch (params_format(params)) { | ||
| case SNDRV_PCM_FORMAT_A_LAW: | ||
| return SOF_IPC4_TYPE_A_LAW; | ||
| case SNDRV_PCM_FORMAT_MU_LAW: | ||
| return SOF_IPC4_TYPE_MU_LAW; | ||
| case SNDRV_PCM_FORMAT_U8: | ||
| return SOF_IPC4_TYPE_UNSIGNED_INTEGER; | ||
| case SNDRV_PCM_FORMAT_S16_LE: | ||
| case SNDRV_PCM_FORMAT_S24_LE: | ||
| case SNDRV_PCM_FORMAT_S32_LE: | ||
| case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: | ||
| return SOF_IPC4_TYPE_LSB_INTEGER; | ||
| case SNDRV_PCM_FORMAT_FLOAT_LE: | ||
| return SOF_IPC4_TYPE_FLOAT; | ||
| default: | ||
| dev_err(sdev->dev, "invalid pcm sample type %d\n", params_format(params)); | ||
| return -EINVAL; | ||
ujfalusi marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| } | ||
| static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, | ||
| struct snd_sof_widget *swidget, | ||
| struct sof_ipc4_base_module_cfg *base_config, | ||
| @@ -1491,8 +1547,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, | ||
| u32 valid_bits; | ||
| u32 channels; | ||
| u32 rate; | ||
| u32 type; | ||
| bool single_format; | ||
| int sample_valid_bits; | ||
| int sample_type; | ||
| int i = 0; | ||
| if (!pin_fmts_size) { | ||
| @@ -1508,6 +1566,10 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, | ||
| if (sample_valid_bits < 0) | ||
| return sample_valid_bits; | ||
| sample_type = sof_ipc4_get_sample_type(sdev, params); | ||
| if (sample_type < 0) | ||
| return sample_type; | ||
| /* | ||
| * Search supported input audio formats with pin index 0 to match rate, channels and | ||
| * sample_valid_bits from reference params | ||
| @@ -1521,8 +1583,9 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, | ||
| rate = fmt->sampling_frequency; | ||
| channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); | ||
| valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); | ||
| type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt->fmt_cfg); | ||
| if (params_rate(params) == rate && params_channels(params) == channels && | ||
| sample_valid_bits == valid_bits) | ||
| sample_valid_bits == valid_bits && sample_type == type) | ||
singalsu marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| break; | ||
| } | ||
| @@ -1943,7 +2006,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, | ||
| int *ipc_config_size; | ||
| u32 **data; | ||
| int ipc_size, ret, out_ref_valid_bits; | ||
| u32 out_ref_rate, out_ref_channels; | ||
| u32 out_ref_rate, out_ref_channels, out_ref_type; | ||
| u32 deep_buffer_dma_ms = 0; | ||
| bool single_output_bitdepth; | ||
| int i; | ||
| @@ -1984,10 +2047,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, | ||
| host_dma_id = platform_params->stream_tag - 1; | ||
| pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id); | ||
| /* Set SCS bit for S16_LE format only */ | ||
| if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE) | ||
| pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; | ||
| /* Set SCS bit for 8 and 16 bit formats */ | ||
| if (params_physical_width(fe_params) <= 16) | ||
| pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; | ||
| /* | ||
| * Despite its name the bitfield 'fifo_size' is used to define DMA buffer | ||
| * size. The expression calculates 2ms buffer size. | ||
| @@ -2112,6 +2178,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, | ||
| in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; | ||
| out_ref_rate = in_fmt->sampling_frequency; | ||
| out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); | ||
| out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg); | ||
| if (!single_output_bitdepth) | ||
| out_ref_valid_bits = | ||
| @@ -2122,6 +2189,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, | ||
| case snd_soc_dapm_dai_in: | ||
| out_ref_rate = params_rate(fe_params); | ||
| out_ref_channels = params_channels(fe_params); | ||
| out_ref_type = sof_ipc4_get_sample_type(sdev, fe_params); | ||
| if (out_ref_type < 0) | ||
| return out_ref_type; | ||
| if (!single_output_bitdepth) { | ||
| out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params); | ||
| if (out_ref_valid_bits < 0) | ||
| @@ -2146,12 +2217,14 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, | ||
| out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt; | ||
| out_ref_valid_bits = | ||
| SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); | ||
| out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(out_fmt->fmt_cfg); | ||
| } | ||
| output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, | ||
| &copier_data->base_config, | ||
| available_fmt, out_ref_rate, | ||
| out_ref_channels, out_ref_valid_bits); | ||
| out_ref_channels, out_ref_valid_bits, | ||
| out_ref_type); | ||
| if (output_fmt_index < 0) | ||
| return output_fmt_index; | ||
| @@ -2380,7 +2453,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, | ||
| struct sof_ipc4_gain *gain = swidget->private; | ||
| struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; | ||
| struct sof_ipc4_audio_format *in_fmt; | ||
| u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; | ||
| u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; | ||
| int input_fmt_index, output_fmt_index; | ||
| input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, | ||
| @@ -2394,13 +2467,15 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, | ||
| out_ref_rate = in_fmt->sampling_frequency; | ||
| out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); | ||
| out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); | ||
| out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg); | ||
| output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, | ||
| &gain->data.base_config, | ||
| available_fmt, | ||
| out_ref_rate, | ||
| out_ref_channels, | ||
| out_ref_valid_bits); | ||
| out_ref_valid_bits, | ||
| out_ref_type); | ||
| if (output_fmt_index < 0) | ||
| return output_fmt_index; | ||
| @@ -2423,7 +2498,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, | ||
| struct sof_ipc4_mixer *mixer = swidget->private; | ||
| struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; | ||
| struct sof_ipc4_audio_format *in_fmt; | ||
| u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; | ||
| u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; | ||
| int input_fmt_index, output_fmt_index; | ||
| input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, | ||
| @@ -2437,13 +2512,15 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, | ||
| out_ref_rate = in_fmt->sampling_frequency; | ||
| out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); | ||
| out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); | ||
| out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg); | ||
| output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, | ||
| &mixer->base_config, | ||
| available_fmt, | ||
| out_ref_rate, | ||
| out_ref_channels, | ||
| out_ref_valid_bits); | ||
| out_ref_valid_bits, | ||
| out_ref_type); | ||
| if (output_fmt_index < 0) | ||
| return output_fmt_index; | ||
| @@ -2467,7 +2544,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, | ||
| struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt; | ||
| struct sof_ipc4_audio_format *out_audio_fmt; | ||
| struct sof_ipc4_audio_format *in_audio_fmt; | ||
| u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; | ||
| u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; | ||
| int output_fmt_index, input_fmt_index; | ||
| input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, | ||
| @@ -2494,6 +2571,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, | ||
| in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; | ||
| out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg); | ||
| out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg); | ||
| out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_audio_fmt->fmt_cfg); | ||
| /* | ||
| * For capture, the SRC module should convert the rate to match the rate requested by the | ||
| @@ -2507,7 +2585,8 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, | ||
| available_fmt, | ||
| out_ref_rate, | ||
| out_ref_channels, | ||
| out_ref_valid_bits); | ||
| out_ref_valid_bits, | ||
| out_ref_type); | ||
| if (output_fmt_index < 0) | ||
| return output_fmt_index; | ||
| @@ -2631,20 +2710,22 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, | ||
| struct sof_ipc4_audio_format *in_fmt; | ||
| struct sof_ipc4_pin_format *pin_fmt; | ||
| u32 out_ref_rate, out_ref_channels; | ||
| int out_ref_valid_bits; | ||
| int out_ref_valid_bits, out_ref_type; | ||
| in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; | ||
| out_ref_rate = in_fmt->sampling_frequency; | ||
| out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); | ||
| out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); | ||
| out_ref_type = SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(in_fmt->fmt_cfg); | ||
| output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, | ||
| &process->base_config, | ||
| available_fmt, | ||
| out_ref_rate, | ||
| out_ref_channels, | ||
| out_ref_valid_bits); | ||
| out_ref_valid_bits, | ||
| out_ref_type); | ||
| if (output_fmt_index < 0) | ||
| return output_fmt_index; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.