[PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus

Christophe Leroy posted 4 patches 1 month, 3 weeks ago
There is a newer version of this series
[PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus
Posted by Christophe Leroy 1 month, 3 weeks ago
To reduce complexity of interrupt handling in following patch, ensure
audio channels are configured in the same order as timeslots on the
TDM bus. If we need a given ordering of audio sources in the audio
frame, it is possible to re-order codecs on the TDM bus, no need to
mix up timeslots in channels.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: New
---
 sound/soc/fsl/fsl_qmc_audio.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
index 5614a8b909edf..0be29ccc1ff7b 100644
--- a/sound/soc/fsl/fsl_qmc_audio.c
+++ b/sound/soc/fsl/fsl_qmc_audio.c
@@ -791,12 +791,17 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
 			       struct qmc_dai *qmc_dai,
 			       struct snd_soc_dai_driver *qmc_soc_dai_driver)
 {
+	struct qmc_chan_ts_info ts_info;
 	struct qmc_chan_info info;
 	unsigned long rx_fs_rate;
 	unsigned long tx_fs_rate;
+	int prev_last_rx_ts = 0;
+	int prev_last_tx_ts = 0;
 	unsigned int nb_tx_ts;
 	unsigned int nb_rx_ts;
 	unsigned int i;
+	int last_rx_ts;
+	int last_tx_ts;
 	int count;
 	u32 val;
 	int ret;
@@ -879,6 +884,30 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
 				return -EINVAL;
 			}
 		}
+
+		ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
+		if (ret) {
+			dev_err(qmc_audio->dev, "dai %d get QMC %d channel TS info failed %d\n",
+				qmc_dai->id, i, ret);
+			return ret;
+		}
+
+		last_rx_ts = fls64(ts_info.rx_ts_mask);
+		last_tx_ts = fls64(ts_info.rx_ts_mask);
+
+		if (prev_last_rx_ts > last_rx_ts) {
+			dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (RX timeslot %lu before %lu)\n",
+				qmc_dai->id, i, prev_last_rx_ts, last_rx_ts);
+			return -EINVAL;
+		}
+		if (prev_last_tx_ts > last_tx_ts) {
+			dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (TX timeslot %lu before %lu)\n",
+				qmc_dai->id, i, prev_last_tx_ts, last_tx_ts);
+			return -EINVAL;
+		}
+
+		prev_last_rx_ts = last_rx_ts;
+		prev_last_tx_ts = last_tx_ts;
 	}
 
 	qmc_dai->nb_chans_avail = count;
-- 
2.49.0
Re: [PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus
Posted by Herve Codina 1 month, 3 weeks ago
On Tue, 12 Aug 2025 12:50:56 +0200
Christophe Leroy <christophe.leroy@csgroup.eu> wrote:

> To reduce complexity of interrupt handling in following patch, ensure
> audio channels are configured in the same order as timeslots on the
> TDM bus. If we need a given ordering of audio sources in the audio
> frame, it is possible to re-order codecs on the TDM bus, no need to
> mix up timeslots in channels.
> 
> Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
> ---
> v2: New
> ---
>  sound/soc/fsl/fsl_qmc_audio.c | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
> 
> diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
> index 5614a8b909edf..0be29ccc1ff7b 100644
> --- a/sound/soc/fsl/fsl_qmc_audio.c
> +++ b/sound/soc/fsl/fsl_qmc_audio.c
> @@ -791,12 +791,17 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
>  			       struct qmc_dai *qmc_dai,
>  			       struct snd_soc_dai_driver *qmc_soc_dai_driver)
>  {
> +	struct qmc_chan_ts_info ts_info;
>  	struct qmc_chan_info info;
>  	unsigned long rx_fs_rate;
>  	unsigned long tx_fs_rate;
> +	int prev_last_rx_ts = 0;
> +	int prev_last_tx_ts = 0;
>  	unsigned int nb_tx_ts;
>  	unsigned int nb_rx_ts;
>  	unsigned int i;
> +	int last_rx_ts;
> +	int last_tx_ts;
>  	int count;
>  	u32 val;
>  	int ret;
> @@ -879,6 +884,30 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
>  				return -EINVAL;
>  			}
>  		}
> +
> +		ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);

qmc_chan_get_ts_info() need a struct qmc_chan as first parameter

qmc_dai->qmc_chans[i].qmc_chan instead of qmc_dai->qmc_chans[i].

The use of qmc_dai->qmc_chans[i] without .qmc_chan have to be done on patch 4 (cleanup patch).

Best regards,
Hervé
Re: [PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus
Posted by Christophe Leroy 1 month, 2 weeks ago

Le 14/08/2025 à 09:45, Herve Codina a écrit :
> On Tue, 12 Aug 2025 12:50:56 +0200
> Christophe Leroy <christophe.leroy@csgroup.eu> wrote:
> 
>> To reduce complexity of interrupt handling in following patch, ensure
>> audio channels are configured in the same order as timeslots on the
>> TDM bus. If we need a given ordering of audio sources in the audio
>> frame, it is possible to re-order codecs on the TDM bus, no need to
>> mix up timeslots in channels.
>>
>> Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
>> ---
>> v2: New
>> ---
>>   sound/soc/fsl/fsl_qmc_audio.c | 29 +++++++++++++++++++++++++++++
>>   1 file changed, 29 insertions(+)
>>
>> diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
>> index 5614a8b909edf..0be29ccc1ff7b 100644
>> --- a/sound/soc/fsl/fsl_qmc_audio.c
>> +++ b/sound/soc/fsl/fsl_qmc_audio.c
>> @@ -791,12 +791,17 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
>>   			       struct qmc_dai *qmc_dai,
>>   			       struct snd_soc_dai_driver *qmc_soc_dai_driver)
>>   {
>> +	struct qmc_chan_ts_info ts_info;
>>   	struct qmc_chan_info info;
>>   	unsigned long rx_fs_rate;
>>   	unsigned long tx_fs_rate;
>> +	int prev_last_rx_ts = 0;
>> +	int prev_last_tx_ts = 0;
>>   	unsigned int nb_tx_ts;
>>   	unsigned int nb_rx_ts;
>>   	unsigned int i;
>> +	int last_rx_ts;
>> +	int last_tx_ts;
>>   	int count;
>>   	u32 val;
>>   	int ret;
>> @@ -879,6 +884,30 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
>>   				return -EINVAL;
>>   			}
>>   		}
>> +
>> +		ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
> 
> qmc_chan_get_ts_info() need a struct qmc_chan as first parameter
> 
> qmc_dai->qmc_chans[i].qmc_chan instead of qmc_dai->qmc_chans[i].
> 
> The use of qmc_dai->qmc_chans[i] without .qmc_chan have to be done on patch 4 (cleanup patch).

Fixed in v3

Thanks
Christophe
Re: [PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus
Posted by kernel test robot 1 month, 3 weeks ago
Hi Christophe,

kernel test robot noticed the following build warnings:

[auto build test WARNING on broonie-sound/for-next]
[also build test WARNING on linus/master v6.17-rc1 next-20250813]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Christophe-Leroy/soc-fsl-qmc-Only-set-completion-interrupt-when-needed/20250812-193812
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
patch link:    https://lore.kernel.org/r/8d01cf4599664188c92a515922d68c9834263384.1754993232.git.christophe.leroy%40csgroup.eu
patch subject: [PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus
config: powerpc64-randconfig-r073-20250813 (https://download.01.org/0day-ci/archive/20250814/202508140002.NBrWOZJL-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 3769ce013be2879bf0b329c14a16f5cb766f26ce)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250814/202508140002.NBrWOZJL-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508140002.NBrWOZJL-lkp@intel.com/

All warnings (new ones prefixed by >>):

   sound/soc/fsl/fsl_qmc_audio.c:888:39: error: no member named 'qmc_chans' in 'struct qmc_dai'
     888 |                 ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
         |                                            ~~~~~~~  ^
>> sound/soc/fsl/fsl_qmc_audio.c:900:21: warning: format specifies type 'unsigned long' but the argument has type 'int' [-Wformat]
     899 |                         dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (RX timeslot %lu before %lu)\n",
         |                                                                                                     ~~~
         |                                                                                                     %d
     900 |                                 qmc_dai->id, i, prev_last_rx_ts, last_rx_ts);
         |                                                 ^~~~~~~~~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   sound/soc/fsl/fsl_qmc_audio.c:900:38: warning: format specifies type 'unsigned long' but the argument has type 'int' [-Wformat]
     899 |                         dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (RX timeslot %lu before %lu)\n",
         |                                                                                                                ~~~
         |                                                                                                                %d
     900 |                                 qmc_dai->id, i, prev_last_rx_ts, last_rx_ts);
         |                                                                  ^~~~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   sound/soc/fsl/fsl_qmc_audio.c:905:21: warning: format specifies type 'unsigned long' but the argument has type 'int' [-Wformat]
     904 |                         dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (TX timeslot %lu before %lu)\n",
         |                                                                                                     ~~~
         |                                                                                                     %d
     905 |                                 qmc_dai->id, i, prev_last_tx_ts, last_tx_ts);
         |                                                 ^~~~~~~~~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   sound/soc/fsl/fsl_qmc_audio.c:905:38: warning: format specifies type 'unsigned long' but the argument has type 'int' [-Wformat]
     904 |                         dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (TX timeslot %lu before %lu)\n",
         |                                                                                                                ~~~
         |                                                                                                                %d
     905 |                                 qmc_dai->id, i, prev_last_tx_ts, last_tx_ts);
         |                                                                  ^~~~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   4 warnings and 1 error generated.


vim +900 sound/soc/fsl/fsl_qmc_audio.c

   789	
   790	static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np,
   791				       struct qmc_dai *qmc_dai,
   792				       struct snd_soc_dai_driver *qmc_soc_dai_driver)
   793	{
   794		struct qmc_chan_ts_info ts_info;
   795		struct qmc_chan_info info;
   796		unsigned long rx_fs_rate;
   797		unsigned long tx_fs_rate;
   798		int prev_last_rx_ts = 0;
   799		int prev_last_tx_ts = 0;
   800		unsigned int nb_tx_ts;
   801		unsigned int nb_rx_ts;
   802		unsigned int i;
   803		int last_rx_ts;
   804		int last_tx_ts;
   805		int count;
   806		u32 val;
   807		int ret;
   808	
   809		qmc_dai->dev = qmc_audio->dev;
   810	
   811		ret = of_property_read_u32(np, "reg", &val);
   812		if (ret) {
   813			dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np);
   814			return ret;
   815		}
   816		qmc_dai->id = val;
   817	
   818		qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d",
   819					       np->parent->name, qmc_dai->id);
   820		if (!qmc_dai->name)
   821			return -ENOMEM;
   822	
   823		count = qmc_chan_count_phandles(np, "fsl,qmc-chan");
   824		if (count < 0)
   825			return dev_err_probe(qmc_audio->dev, count,
   826					     "dai %d get number of QMC channel failed\n", qmc_dai->id);
   827		if (!count)
   828			return dev_err_probe(qmc_audio->dev, -EINVAL,
   829					     "dai %d no QMC channel defined\n", qmc_dai->id);
   830	
   831		qmc_dai->chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->chans), GFP_KERNEL);
   832		if (!qmc_dai->chans)
   833			return -ENOMEM;
   834	
   835		for (i = 0; i < count; i++) {
   836			qmc_dai->chans[i].qmc_chan = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np,
   837											"fsl,qmc-chan", i);
   838			if (IS_ERR(qmc_dai->chans[i].qmc_chan)) {
   839				return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->chans[i].qmc_chan),
   840						     "dai %d get QMC channel %d failed\n", qmc_dai->id, i);
   841			}
   842	
   843			ret = qmc_chan_get_info(qmc_dai->chans[i].qmc_chan, &info);
   844			if (ret) {
   845				dev_err(qmc_audio->dev, "dai %d get QMC %d channel info failed %d\n",
   846					qmc_dai->id, i, ret);
   847				return ret;
   848			}
   849	
   850			if (info.mode != QMC_TRANSPARENT) {
   851				dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n",
   852					qmc_dai->id, i, info.mode);
   853				return -EINVAL;
   854			}
   855	
   856			/*
   857			 * All channels must have the same number of Tx slots and the
   858			 * same numbers of Rx slots.
   859			 */
   860			if (i == 0) {
   861				nb_tx_ts = info.nb_tx_ts;
   862				nb_rx_ts = info.nb_rx_ts;
   863				tx_fs_rate = info.tx_fs_rate;
   864				rx_fs_rate = info.rx_fs_rate;
   865			} else {
   866				if (nb_tx_ts != info.nb_tx_ts) {
   867					dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Tx timeslots (%u instead of %u)\n",
   868						qmc_dai->id, i, info.nb_tx_ts, nb_tx_ts);
   869					return -EINVAL;
   870				}
   871				if (nb_rx_ts != info.nb_rx_ts) {
   872					dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Rx timeslots (%u instead of %u)\n",
   873						qmc_dai->id, i, info.nb_rx_ts, nb_rx_ts);
   874					return -EINVAL;
   875				}
   876				if (tx_fs_rate != info.tx_fs_rate) {
   877					dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Tx frame sample rate (%lu instead of %lu)\n",
   878						qmc_dai->id, i, info.tx_fs_rate, tx_fs_rate);
   879					return -EINVAL;
   880				}
   881				if (rx_fs_rate != info.rx_fs_rate) {
   882					dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Rx frame sample rate (%lu instead of %lu)\n",
   883						qmc_dai->id, i, info.rx_fs_rate, rx_fs_rate);
   884					return -EINVAL;
   885				}
   886			}
   887	
 > 888			ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
   889			if (ret) {
   890				dev_err(qmc_audio->dev, "dai %d get QMC %d channel TS info failed %d\n",
   891					qmc_dai->id, i, ret);
   892				return ret;
   893			}
   894	
   895			last_rx_ts = fls64(ts_info.rx_ts_mask);
   896			last_tx_ts = fls64(ts_info.rx_ts_mask);
   897	
   898			if (prev_last_rx_ts > last_rx_ts) {
   899				dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (RX timeslot %lu before %lu)\n",
 > 900					qmc_dai->id, i, prev_last_rx_ts, last_rx_ts);
   901				return -EINVAL;
   902			}
   903			if (prev_last_tx_ts > last_tx_ts) {
   904				dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (TX timeslot %lu before %lu)\n",
   905					qmc_dai->id, i, prev_last_tx_ts, last_tx_ts);
   906				return -EINVAL;
   907			}
   908	
   909			prev_last_rx_ts = last_rx_ts;
   910			prev_last_tx_ts = last_tx_ts;
   911		}
   912	
   913		qmc_dai->nb_chans_avail = count;
   914		qmc_dai->nb_tx_ts = nb_tx_ts * count;
   915		qmc_dai->nb_rx_ts = nb_rx_ts * count;
   916	
   917		qmc_soc_dai_driver->id = qmc_dai->id;
   918		qmc_soc_dai_driver->name = qmc_dai->name;
   919	
   920		qmc_soc_dai_driver->playback.channels_min = 0;
   921		qmc_soc_dai_driver->playback.channels_max = 0;
   922		if (nb_tx_ts) {
   923			qmc_soc_dai_driver->playback.channels_min = 1;
   924			qmc_soc_dai_driver->playback.channels_max = count > 1 ? count : nb_tx_ts;
   925		}
   926		qmc_soc_dai_driver->playback.formats = qmc_audio_formats(nb_tx_ts,
   927									 count > 1);
   928	
   929		qmc_soc_dai_driver->capture.channels_min = 0;
   930		qmc_soc_dai_driver->capture.channels_max = 0;
   931		if (nb_rx_ts) {
   932			qmc_soc_dai_driver->capture.channels_min = 1;
   933			qmc_soc_dai_driver->capture.channels_max = count > 1 ? count : nb_rx_ts;
   934		}
   935		qmc_soc_dai_driver->capture.formats = qmc_audio_formats(nb_rx_ts,
   936									count > 1);
   937	
   938		qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(tx_fs_rate);
   939		qmc_soc_dai_driver->playback.rate_min = tx_fs_rate;
   940		qmc_soc_dai_driver->playback.rate_max = tx_fs_rate;
   941		qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(rx_fs_rate);
   942		qmc_soc_dai_driver->capture.rate_min = rx_fs_rate;
   943		qmc_soc_dai_driver->capture.rate_max = rx_fs_rate;
   944	
   945		qmc_soc_dai_driver->ops = &qmc_dai_ops;
   946	
   947		return 0;
   948	}
   949	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus
Posted by Herve Codina 1 month, 3 weeks ago
Hi Christophe,

On Tue, 12 Aug 2025 12:50:56 +0200
Christophe Leroy <christophe.leroy@csgroup.eu> wrote:

...

> @@ -879,6 +884,30 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
>  				return -EINVAL;
>  			}
>  		}
> +
> +		ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
> +		if (ret) {
> +			dev_err(qmc_audio->dev, "dai %d get QMC %d channel TS info failed %d\n",
> +				qmc_dai->id, i, ret);
> +			return ret;
> +		}
> +
> +		last_rx_ts = fls64(ts_info.rx_ts_mask);
> +		last_tx_ts = fls64(ts_info.rx_ts_mask);
                                              
tx_ts_mask instead of rx_ts_mask for last_tx_ts.

Best regards,
Hervé
Re: [PATCH v2 2/4] ASoc: fsl: fsl_qmc_audio: Ensure audio channels are ordered in TDM bus
Posted by Christophe Leroy 1 month, 2 weeks ago

Le 13/08/2025 à 12:06, Herve Codina a écrit :
> Hi Christophe,
> 
> On Tue, 12 Aug 2025 12:50:56 +0200
> Christophe Leroy <christophe.leroy@csgroup.eu> wrote:
> 
> ...
> 
>> @@ -879,6 +884,30 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
>>   				return -EINVAL;
>>   			}
>>   		}
>> +
>> +		ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
>> +		if (ret) {
>> +			dev_err(qmc_audio->dev, "dai %d get QMC %d channel TS info failed %d\n",
>> +				qmc_dai->id, i, ret);
>> +			return ret;
>> +		}
>> +
>> +		last_rx_ts = fls64(ts_info.rx_ts_mask);
>> +		last_tx_ts = fls64(ts_info.rx_ts_mask);
>                                                
> tx_ts_mask instead of rx_ts_mask for last_tx_ts.
> 

Fixed in v3

Thanks
Christophe