@@ -195,9 +195,10 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo
195195 for (i = 0 ; i < num_formats ; i ++ ) {
196196 struct sof_ipc4_audio_format * fmt = & pin_fmt [i ].audio_fmt ;
197197 dev_dbg (dev ,
198- "Pin index #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n" ,
199- pin_fmt [i ].pin_index , fmt -> sampling_frequency , fmt -> bit_depth , fmt -> ch_map ,
200- fmt -> ch_cfg , fmt -> interleaving_style , fmt -> fmt_cfg ,
198+ "Pin index #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n" ,
199+ pin_fmt [i ].pin_index , fmt -> sampling_frequency , fmt -> bit_depth ,
200+ SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT (fmt -> fmt_cfg ),
201+ fmt -> ch_map , fmt -> ch_cfg , fmt -> interleaving_style , fmt -> fmt_cfg ,
201202 pin_fmt [i ].buffer_size );
202203 }
203204}
@@ -1430,7 +1431,7 @@ static int snd_sof_get_hw_config_params(struct snd_sof_dev *sdev, struct snd_sof
14301431
14311432static int
14321433snd_sof_get_nhlt_endpoint_data (struct snd_sof_dev * sdev , struct snd_sof_dai * dai ,
1433- bool single_format ,
1434+ bool single_bitdepth ,
14341435 struct snd_pcm_hw_params * params , u32 dai_index ,
14351436 u32 linktype , u8 dir , u32 * * dst , u32 * len )
14361437{
@@ -1453,7 +1454,7 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
14531454 * Look for 32-bit blob first instead of 16-bit if copier
14541455 * supports multiple formats
14551456 */
1456- if (bit_depth == 16 && !single_format ) {
1457+ if (bit_depth == 16 && !single_bitdepth ) {
14571458 dev_dbg (sdev -> dev , "Looking for 32-bit blob first for DMIC\n" );
14581459 format_change = true;
14591460 bit_depth = 32 ;
@@ -1491,14 +1492,29 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
14911492 dir , dev_type );
14921493
14931494 if (!cfg ) {
1495+ bool get_new_blob = false;
1496+
14941497 if (format_change ) {
14951498 /*
14961499 * The 32-bit blob was not found in NHLT table, try to
14971500 * look for one based on the params
14981501 */
14991502 bit_depth = params_width (params );
15001503 format_change = false;
1504+ get_new_blob = true;
1505+ } else if (linktype == SOF_DAI_INTEL_DMIC && !single_bitdepth ) {
1506+ /*
1507+ * The requested 32-bit blob (no format change for the
1508+ * blob request) was not found in NHLT table, try to
1509+ * look for 16-bit blob if the copier supports multiple
1510+ * formats
1511+ */
1512+ bit_depth = 16 ;
1513+ format_change = true;
1514+ get_new_blob = true;
1515+ }
15011516
1517+ if (get_new_blob ) {
15021518 cfg = intel_nhlt_get_endpoint_blob (sdev -> dev , ipc4_data -> nhlt ,
15031519 dai_index , nhlt_type ,
15041520 bit_depth , bit_depth ,
@@ -1521,34 +1537,38 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
15211537
15221538 if (format_change ) {
15231539 /*
1524- * Update the params to reflect that we have loaded 32-bit blob
1525- * instead of the 16-bit .
1540+ * Update the params to reflect that different blob was loaded
1541+ * instead of the requested bit depth (16 -> 32 or 32 -> 16) .
15261542 * This information is going to be used by the caller to find
15271543 * matching copier format on the dai side.
15281544 */
15291545 struct snd_mask * m ;
15301546
15311547 m = hw_param_mask (params , SNDRV_PCM_HW_PARAM_FORMAT );
15321548 snd_mask_none (m );
1533- snd_mask_set_format (m , SNDRV_PCM_FORMAT_S32_LE );
1549+ if (bit_depth == 16 )
1550+ snd_mask_set_format (m , SNDRV_PCM_FORMAT_S16_LE );
1551+ else
1552+ snd_mask_set_format (m , SNDRV_PCM_FORMAT_S32_LE );
1553+
15341554 }
15351555
15361556 return 0 ;
15371557}
15381558#else
15391559static int
15401560snd_sof_get_nhlt_endpoint_data (struct snd_sof_dev * sdev , struct snd_sof_dai * dai ,
1541- bool single_format ,
1561+ bool single_bitdepth ,
15421562 struct snd_pcm_hw_params * params , u32 dai_index ,
15431563 u32 linktype , u8 dir , u32 * * dst , u32 * len )
15441564{
15451565 return 0 ;
15461566}
15471567#endif
15481568
1549- bool sof_ipc4_copier_is_single_format (struct snd_sof_dev * sdev ,
1550- struct sof_ipc4_pin_format * pin_fmts ,
1551- u32 pin_fmts_size )
1569+ bool sof_ipc4_copier_is_single_bitdepth (struct snd_sof_dev * sdev ,
1570+ struct sof_ipc4_pin_format * pin_fmts ,
1571+ u32 pin_fmts_size )
15521572{
15531573 struct sof_ipc4_audio_format * fmt ;
15541574 u32 valid_bits ;
@@ -1571,56 +1591,93 @@ bool sof_ipc4_copier_is_single_format(struct snd_sof_dev *sdev,
15711591 return true;
15721592}
15731593
1594+ static int
1595+ sof_ipc4_adjust_params_to_dai_format (struct snd_sof_dev * sdev ,
1596+ struct snd_pcm_hw_params * params ,
1597+ struct sof_ipc4_pin_format * pin_fmts ,
1598+ u32 pin_fmts_size )
1599+ {
1600+ u32 params_mask = BIT (SNDRV_PCM_HW_PARAM_RATE ) |
1601+ BIT (SNDRV_PCM_HW_PARAM_CHANNELS ) |
1602+ BIT (SNDRV_PCM_HW_PARAM_FORMAT );
1603+ struct sof_ipc4_audio_format * fmt ;
1604+ u32 rate , channels , valid_bits ;
1605+ int i ;
1606+
1607+ fmt = & pin_fmts [0 ].audio_fmt ;
1608+ rate = fmt -> sampling_frequency ;
1609+ channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT (fmt -> fmt_cfg );
1610+ valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH (fmt -> fmt_cfg );
1611+
1612+ /* check if parameters in topology defined formats are the same */
1613+ for (i = 1 ; i < pin_fmts_size ; i ++ ) {
1614+ u32 val ;
1615+
1616+ fmt = & pin_fmts [i ].audio_fmt ;
1617+
1618+ if (params_mask & BIT (SNDRV_PCM_HW_PARAM_RATE )) {
1619+ val = fmt -> sampling_frequency ;
1620+ if (val != rate )
1621+ params_mask &= ~BIT (SNDRV_PCM_HW_PARAM_RATE );
1622+ }
1623+ if (params_mask & BIT (SNDRV_PCM_HW_PARAM_CHANNELS )) {
1624+ val = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT (fmt -> fmt_cfg );
1625+ if (val != channels )
1626+ params_mask &= ~BIT (SNDRV_PCM_HW_PARAM_CHANNELS );
1627+ }
1628+ if (params_mask & BIT (SNDRV_PCM_HW_PARAM_FORMAT )) {
1629+ val = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH (fmt -> fmt_cfg );
1630+ if (val != valid_bits )
1631+ params_mask &= ~BIT (SNDRV_PCM_HW_PARAM_FORMAT );
1632+ }
1633+ }
1634+
1635+ if (params_mask )
1636+ return sof_ipc4_update_hw_params (sdev , params ,
1637+ & pin_fmts [0 ].audio_fmt ,
1638+ params_mask );
1639+
1640+ return 0 ;
1641+ }
1642+
15741643static int
15751644sof_ipc4_prepare_dai_copier (struct snd_sof_dev * sdev , struct snd_sof_dai * dai ,
15761645 struct snd_pcm_hw_params * params , int dir )
15771646{
15781647 struct sof_ipc4_available_audio_format * available_fmt ;
15791648 struct snd_pcm_hw_params dai_params = * params ;
15801649 struct sof_ipc4_copier_data * copier_data ;
1650+ struct sof_ipc4_pin_format * pin_fmts ;
15811651 struct sof_ipc4_copier * ipc4_copier ;
1582- bool single_format ;
1652+ bool single_bitdepth ;
1653+ u32 num_pin_fmts ;
15831654 int ret ;
15841655
15851656 ipc4_copier = dai -> private ;
15861657 copier_data = & ipc4_copier -> data ;
15871658 available_fmt = & ipc4_copier -> available_fmt ;
15881659
15891660 /*
1590- * If the copier on the DAI side supports only single bit depth then
1591- * this depth (format) should be used to look for the NHLT blob (if
1592- * needed) and in case of capture this should be used for the input
1593- * format lookup
1661+ * Fixup the params based on the format parameters of the DAI. If any
1662+ * of the RATE, CHANNELS, bit depth is static among the formats then
1663+ * narrow the params to only allow that specific parameter value.
15941664 */
15951665 if (dir == SNDRV_PCM_STREAM_PLAYBACK ) {
1596- single_format = sof_ipc4_copier_is_single_format (sdev ,
1597- available_fmt -> output_pin_fmts ,
1598- available_fmt -> num_output_formats );
1599-
1600- /* Update the dai_params with the only supported format */
1601- if (single_format ) {
1602- ret = sof_ipc4_update_hw_params (sdev , & dai_params ,
1603- & available_fmt -> output_pin_fmts [0 ].audio_fmt ,
1604- BIT (SNDRV_PCM_HW_PARAM_FORMAT ));
1605- if (ret )
1606- return ret ;
1607- }
1666+ pin_fmts = available_fmt -> output_pin_fmts ;
1667+ num_pin_fmts = available_fmt -> num_output_formats ;
16081668 } else {
1609- single_format = sof_ipc4_copier_is_single_format (sdev ,
1610- available_fmt -> input_pin_fmts ,
1611- available_fmt -> num_input_formats );
1612-
1613- /* Update the dai_params with the only supported format */
1614- if (single_format ) {
1615- ret = sof_ipc4_update_hw_params (sdev , & dai_params ,
1616- & available_fmt -> input_pin_fmts [0 ].audio_fmt ,
1617- BIT (SNDRV_PCM_HW_PARAM_FORMAT ));
1618- if (ret )
1619- return ret ;
1620- }
1669+ pin_fmts = available_fmt -> input_pin_fmts ;
1670+ num_pin_fmts = available_fmt -> num_input_formats ;
16211671 }
16221672
1623- ret = snd_sof_get_nhlt_endpoint_data (sdev , dai , single_format ,
1673+ ret = sof_ipc4_adjust_params_to_dai_format (sdev , & dai_params , pin_fmts ,
1674+ num_pin_fmts );
1675+ if (ret )
1676+ return ret ;
1677+
1678+ single_bitdepth = sof_ipc4_copier_is_single_bitdepth (sdev , pin_fmts ,
1679+ num_pin_fmts );
1680+ ret = snd_sof_get_nhlt_endpoint_data (sdev , dai , single_bitdepth ,
16241681 & dai_params ,
16251682 ipc4_copier -> dai_index ,
16261683 ipc4_copier -> dai_type , dir ,
@@ -1655,7 +1712,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
16551712 u32 out_ref_rate , out_ref_channels ;
16561713 u32 deep_buffer_dma_ms = 0 ;
16571714 int output_fmt_index ;
1658- bool single_output_format ;
1715+ bool single_output_bitdepth ;
16591716 int i ;
16601717
16611718 dev_dbg (sdev -> dev , "copier %s, type %d" , swidget -> widget -> name , swidget -> id );
@@ -1792,9 +1849,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
17921849 return ret ;
17931850
17941851 /* set the reference params for output format selection */
1795- single_output_format = sof_ipc4_copier_is_single_format (sdev ,
1796- available_fmt -> output_pin_fmts ,
1797- available_fmt -> num_output_formats );
1852+ single_output_bitdepth = sof_ipc4_copier_is_single_bitdepth (sdev ,
1853+ available_fmt -> output_pin_fmts ,
1854+ available_fmt -> num_output_formats );
17981855 switch (swidget -> id ) {
17991856 case snd_soc_dapm_aif_in :
18001857 case snd_soc_dapm_dai_out :
@@ -1806,7 +1863,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
18061863 out_ref_rate = in_fmt -> sampling_frequency ;
18071864 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT (in_fmt -> fmt_cfg );
18081865
1809- if (!single_output_format )
1866+ if (!single_output_bitdepth )
18101867 out_ref_valid_bits =
18111868 SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH (in_fmt -> fmt_cfg );
18121869 break ;
@@ -1815,7 +1872,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
18151872 case snd_soc_dapm_dai_in :
18161873 out_ref_rate = params_rate (fe_params );
18171874 out_ref_channels = params_channels (fe_params );
1818- if (!single_output_format ) {
1875+ if (!single_output_bitdepth ) {
18191876 out_ref_valid_bits = sof_ipc4_get_valid_bits (sdev , fe_params );
18201877 if (out_ref_valid_bits < 0 )
18211878 return out_ref_valid_bits ;
@@ -1833,7 +1890,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
18331890 * if the output format is the same across all available output formats, choose
18341891 * that as the reference.
18351892 */
1836- if (single_output_format ) {
1893+ if (single_output_bitdepth ) {
18371894 struct sof_ipc4_audio_format * out_fmt ;
18381895
18391896 out_fmt = & available_fmt -> output_pin_fmts [0 ].audio_fmt ;
0 commit comments