@@ -20,6 +20,11 @@ struct stream_cfg {
2020 nrfx_i2s_config_t nrfx_cfg ;
2121};
2222
23+ struct i2s_buf {
24+ void * mem_block ;
25+ size_t size ;
26+ };
27+
2328struct i2s_nrfx_drv_data {
2429 struct onoff_manager * clk_mgr ;
2530 struct onoff_client clk_cli ;
@@ -189,9 +194,14 @@ static void find_suitable_clock(const struct i2s_nrfx_drv_cfg *drv_cfg,
189194static bool get_next_tx_buffer (struct i2s_nrfx_drv_data * drv_data ,
190195 nrfx_i2s_buffers_t * buffers )
191196{
197+ struct i2s_buf buf ;
192198 int ret = k_msgq_get (& drv_data -> tx_queue ,
193- & buffers -> p_tx_buffer ,
199+ & buf ,
194200 K_NO_WAIT );
201+ if (ret == 0 ) {
202+ buffers -> p_tx_buffer = buf .mem_block ;
203+ buffers -> buffer_size = buf .size / sizeof (uint32_t );
204+ }
195205 return (ret == 0 );
196206}
197207
@@ -226,21 +236,22 @@ static void free_rx_buffer(struct i2s_nrfx_drv_data *drv_data, void *buffer)
226236static bool supply_next_buffers (struct i2s_nrfx_drv_data * drv_data ,
227237 nrfx_i2s_buffers_t * next )
228238{
229- uint32_t block_size = (drv_data -> active_dir == I2S_DIR_TX )
230- ? drv_data -> tx .cfg .block_size
231- : drv_data -> rx .cfg .block_size ;
232-
233- drv_data -> last_tx_buffer = next -> p_tx_buffer ;
234-
235239 if (drv_data -> active_dir != I2S_DIR_TX ) { /* -> RX active */
236240 if (!get_next_rx_buffer (drv_data , next )) {
237241 drv_data -> state = I2S_STATE_ERROR ;
238242 nrfx_i2s_stop (drv_data -> p_i2s );
239243 return false;
240244 }
245+ /* Set buffer size if there is no TX buffer (which effectively
246+ * controls how many bytes will be received).
247+ */
248+ if (drv_data -> active_dir == I2S_DIR_RX ) {
249+ next -> buffer_size =
250+ drv_data -> rx .cfg .block_size / sizeof (uint32_t );
251+ }
241252 }
242253
243- next -> buffer_size = block_size / sizeof ( uint32_t ) ;
254+ drv_data -> last_tx_buffer = next -> p_tx_buffer ;
244255
245256 LOG_DBG ("Next buffers: %p/%p" , next -> p_tx_buffer , next -> p_rx_buffer );
246257 nrfx_i2s_next_buffers_set (drv_data -> p_i2s , next );
@@ -300,8 +311,12 @@ static void data_handler(const struct device *dev,
300311 if (drv_data -> discard_rx ) {
301312 free_rx_buffer (drv_data , released -> p_rx_buffer );
302313 } else {
314+ struct i2s_buf buf = {
315+ .mem_block = released -> p_rx_buffer ,
316+ .size = released -> buffer_size * sizeof (uint32_t )
317+ };
303318 int ret = k_msgq_put (& drv_data -> rx_queue ,
304- & released -> p_rx_buffer ,
319+ & buf ,
305320 K_NO_WAIT );
306321 if (ret < 0 ) {
307322 LOG_ERR ("No room in RX queue" );
@@ -351,6 +366,7 @@ static void data_handler(const struct device *dev,
351366 * before this buffer would be started again).
352367 */
353368 next .p_tx_buffer = drv_data -> last_tx_buffer ;
369+ next .buffer_size = 1 ;
354370 } else if (get_next_tx_buffer (drv_data , & next )) {
355371 /* Next TX buffer successfully retrieved from
356372 * the queue, nothing more to do here.
@@ -367,6 +383,7 @@ static void data_handler(const struct device *dev,
367383 * will be stopped earlier.
368384 */
369385 next .p_tx_buffer = drv_data -> last_tx_buffer ;
386+ next .buffer_size = 1 ;
370387 } else {
371388 /* Next TX buffer cannot be supplied now.
372389 * Defer it to when the user writes more data.
@@ -383,21 +400,21 @@ static void data_handler(const struct device *dev,
383400static void purge_queue (const struct device * dev , enum i2s_dir dir )
384401{
385402 struct i2s_nrfx_drv_data * drv_data = dev -> data ;
386- void * mem_block ;
403+ struct i2s_buf buf ;
387404
388405 if (dir == I2S_DIR_TX || dir == I2S_DIR_BOTH ) {
389406 while (k_msgq_get (& drv_data -> tx_queue ,
390- & mem_block ,
407+ & buf ,
391408 K_NO_WAIT ) == 0 ) {
392- free_tx_buffer (drv_data , mem_block );
409+ free_tx_buffer (drv_data , buf . mem_block );
393410 }
394411 }
395412
396413 if (dir == I2S_DIR_RX || dir == I2S_DIR_BOTH ) {
397414 while (k_msgq_get (& drv_data -> rx_queue ,
398- & mem_block ,
415+ & buf ,
399416 K_NO_WAIT ) == 0 ) {
400- free_rx_buffer (drv_data , mem_block );
417+ free_rx_buffer (drv_data , buf . mem_block );
401418 }
402419 }
403420}
@@ -560,6 +577,7 @@ static int i2s_nrfx_read(const struct device *dev,
560577 void * * mem_block , size_t * size )
561578{
562579 struct i2s_nrfx_drv_data * drv_data = dev -> data ;
580+ struct i2s_buf buf ;
563581 int ret ;
564582
565583 if (!drv_data -> rx_configured ) {
@@ -568,18 +586,19 @@ static int i2s_nrfx_read(const struct device *dev,
568586 }
569587
570588 ret = k_msgq_get (& drv_data -> rx_queue ,
571- mem_block ,
589+ & buf ,
572590 (drv_data -> state == I2S_STATE_ERROR )
573591 ? K_NO_WAIT
574592 : SYS_TIMEOUT_MS (drv_data -> rx .cfg .timeout ));
575593 if (ret == - ENOMSG ) {
576594 return - EIO ;
577595 }
578596
579- LOG_DBG ("Released RX %p" , * mem_block );
597+ LOG_DBG ("Released RX %p" , buf . mem_block );
580598
581599 if (ret == 0 ) {
582- * size = drv_data -> rx .cfg .block_size ;
600+ * mem_block = buf .mem_block ;
601+ * size = buf .size ;
583602 }
584603
585604 return ret ;
@@ -589,6 +608,7 @@ static int i2s_nrfx_write(const struct device *dev,
589608 void * mem_block , size_t size )
590609{
591610 struct i2s_nrfx_drv_data * drv_data = dev -> data ;
611+ struct i2s_buf buf = { .mem_block = mem_block , .size = size };
592612 int ret ;
593613
594614 if (!drv_data -> tx_configured ) {
@@ -602,14 +622,14 @@ static int i2s_nrfx_write(const struct device *dev,
602622 return - EIO ;
603623 }
604624
605- if (size != drv_data -> tx .cfg .block_size ) {
606- LOG_ERR ("This device can only write blocks of %u bytes" ,
625+ if (size > drv_data -> tx .cfg .block_size || size < sizeof ( uint32_t ) ) {
626+ LOG_ERR ("This device can only write blocks up to %u bytes" ,
607627 drv_data -> tx .cfg .block_size );
608628 return - EIO ;
609629 }
610630
611631 ret = k_msgq_put (& drv_data -> tx_queue ,
612- & mem_block ,
632+ & buf ,
613633 SYS_TIMEOUT_MS (drv_data -> tx .cfg .timeout ));
614634 if (ret < 0 ) {
615635 return ret ;
@@ -662,12 +682,17 @@ static int start_transfer(struct i2s_nrfx_drv_data *drv_data)
662682 /* Failed to allocate next RX buffer */
663683 ret = - ENOMEM ;
664684 } else {
665- uint32_t block_size = (drv_data -> active_dir == I2S_DIR_TX )
666- ? drv_data -> tx .cfg .block_size
667- : drv_data -> rx .cfg .block_size ;
668685 nrfx_err_t err ;
669686
670- initial_buffers .buffer_size = block_size / sizeof (uint32_t );
687+ /* It is necessary to set buffer size here only for I2S_DIR_RX,
688+ * because only then the get_next_tx_buffer() call in the if
689+ * condition above gets short-circuited.
690+ */
691+ if (drv_data -> active_dir == I2S_DIR_RX ) {
692+ initial_buffers .buffer_size =
693+ drv_data -> rx .cfg .block_size / sizeof (uint32_t );
694+ }
695+
671696 drv_data -> last_tx_buffer = initial_buffers .p_tx_buffer ;
672697
673698 err = nrfx_i2s_start (drv_data -> p_i2s , & initial_buffers , 0 );
@@ -904,8 +929,8 @@ static const struct i2s_driver_api i2s_nrf_drv_api = {
904929#define I2S_CLK_SRC (idx ) DT_STRING_TOKEN(I2S(idx), clock_source)
905930
906931#define I2S_NRFX_DEVICE (idx ) \
907- static void * tx_msgs##idx[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \
908- static void * rx_msgs##idx[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \
932+ static struct i2s_buf tx_msgs##idx[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \
933+ static struct i2s_buf rx_msgs##idx[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \
909934 static void data_handler##idx(nrfx_i2s_buffers_t const *p_released, \
910935 uint32_t status) \
911936 { \
@@ -941,10 +966,10 @@ static const struct i2s_driver_api i2s_nrf_drv_api = {
941966 return err; \
942967 } \
943968 k_msgq_init(&i2s_nrfx_data##idx.tx_queue, \
944- (char *)tx_msgs##idx, sizeof(void *), \
969+ (char *)tx_msgs##idx, sizeof(struct i2s_buf), \
945970 ARRAY_SIZE(tx_msgs##idx)); \
946971 k_msgq_init(&i2s_nrfx_data##idx.rx_queue, \
947- (char *)rx_msgs##idx, sizeof(void *), \
972+ (char *)rx_msgs##idx, sizeof(struct i2s_buf), \
948973 ARRAY_SIZE(rx_msgs##idx)); \
949974 init_clock_manager(dev); \
950975 return 0; \
0 commit comments