Set of chnages to ALSA Ravenna driver to fix the playback with memory mapped access mode on ARM platform.
Issue is in the mr_alsa_audio_pcm_playback_copy_internal() function of audio_driver.c that transfers the PCM samples from the ALSA buffer to the Ravenna buffer using the get_user() function. In case of memory access mode the ALSA buffer can be directly accessed by the kernel and the samples must be copied. mr_alsa_audio_pcm_playback_copy_internal() has been modified can to handle the transfer of the ALSA buffer from user space (used with read/write access mode) and from kernel space (used by memory access mode). The issue is common to all the platform but impacting ARM only. Additional changes: - changed type for dma_playback_offset and dma_capture_offset variables to uint32_t instead of atomic_t since the pointer callback mr_alsa_audio_pcm_pointer() is now atomic - added variables to the mr_alsa_audio_chip scructure to decrease the number of calls to snd_pcm_lib_xxx() functions. These get assigned in the prepare callback mr_alsa_audio_pcm_prepare() - changed mr_alsa_audio_get_playback_buffer_size_in_frames() to return configured size of Ravenna playback buffer (same as mr_alsa_audio_get_capture_buffer_size_in_frames()) - some rework of the existing patches This fixes issue #20wq
This commit is contained in:
		
							parent
							
								
									2a2d536284
								
							
						
					
					
						commit
						7c42e52dca
					
				| @ -37,28 +37,6 @@ index 5a160e4..a5c84e4 100644 | |||||||
|   |   | ||||||
|  		i64DeltaSAC =  ui64UsedSAC - ui64GlobalSAC; |  		i64DeltaSAC =  ui64UsedSAC - ui64GlobalSAC; | ||||||
|  		//MTAL_DP("i64DeltaSAC %I64u playout delay %u, frame size: %u\n", i64DeltaSAC, pRTP_stream_info->m_ui32PlayOutDelay, pManager->get_frame_size(pManager->user)); |  		//MTAL_DP("i64DeltaSAC %I64u playout delay %u, frame size: %u\n", i64DeltaSAC, pRTP_stream_info->m_ui32PlayOutDelay, pManager->get_frame_size(pManager->user)); | ||||||
| diff --git a/driver/audio_driver.c b/driver/audio_driver.c
 |  | ||||||
| index a04ec21..cb8b056 100644
 |  | ||||||
| --- a/driver/audio_driver.c
 |  | ||||||
| +++ b/driver/audio_driver.c
 |  | ||||||
| @@ -1205,8 +1205,8 @@ static int mr_alsa_audio_pcm_capture_copy_internal(  struct snd_pcm_substream *s
 |  | ||||||
|      { |  | ||||||
|          int ret_pu; |  | ||||||
|          char val = 0xf1; |  | ||||||
| -        __put_user_x(1, val, (unsigned long __user *)src, ret_pu);
 |  | ||||||
| -        ret_pu = put_user(val, (unsigned long __user *)src);
 |  | ||||||
| +        //__put_user_x(1, val, (unsigned long __user *)src, ret_pu);
 |  | ||||||
| +        ret_pu = put_user(val, (unsigned char __user *)src);
 |  | ||||||
|          //put_user(val, (unsigned long __user *)src); |  | ||||||
|          switch(nb_logical_bits) |  | ||||||
|          { |  | ||||||
| @@ -2758,4 +2758,4 @@ void mr_alsa_audio_card_exit(void)
 |  | ||||||
|      g_ravenna_peer = NULL; |  | ||||||
|      g_mr_alsa_audio_ops = NULL; |  | ||||||
|      printk(KERN_INFO "leaving mr_alsa_audio_card_exit..\n"); |  | ||||||
| -}
 |  | ||||||
| \ No newline at end of file |  | ||||||
| +}
 |  | ||||||
| diff --git a/driver/manager.c b/driver/manager.c
 | diff --git a/driver/manager.c b/driver/manager.c
 | ||||||
| index 5a90eca..8023708 100644
 | index 5a90eca..8023708 100644
 | ||||||
| --- a/driver/manager.c
 | --- a/driver/manager.c
 | ||||||
|  | |||||||
| @ -1,71 +1,143 @@ | |||||||
| diff --git a/driver/audio_driver.c b/driver/audio_driver.c
 | diff --git a/driver/audio_driver.c b/driver/audio_driver.c
 | ||||||
| index 3d9debd..910ed5b 100644
 | index 3d9debd..3c3183e 100644
 | ||||||
| --- a/driver/audio_driver.c
 | --- a/driver/audio_driver.c
 | ||||||
| +++ b/driver/audio_driver.c
 | +++ b/driver/audio_driver.c
 | ||||||
| @@ -43,7 +43,7 @@
 | @@ -43,7 +43,6 @@
 | ||||||
|  #include <sound/control.h> |  #include <sound/control.h> | ||||||
|  #include <sound/tlv.h> |  #include <sound/tlv.h> | ||||||
|  #include <sound/pcm.h> |  #include <sound/pcm.h> | ||||||
| -#include <sound/pcm-indirect.h> // for mmap
 | -#include <sound/pcm-indirect.h> // for mmap
 | ||||||
| +//#include <sound/pcm-indirect.h> // for mmap
 |  | ||||||
|  #include <sound/pcm_params.h> |  #include <sound/pcm_params.h> | ||||||
|  #include <sound/initval.h> |  #include <sound/initval.h> | ||||||
|   |   | ||||||
| @@ -121,9 +121,6 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 | @@ -77,11 +76,6 @@ static int index = SNDRV_DEFAULT_IDX1; /* Index 0-max */
 | ||||||
|  |  static char *id = SNDRV_DEFAULT_STR1; /* Id for card */ | ||||||
|  |  static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ | ||||||
|  |  static int pcm_devs = 1; | ||||||
|  | -//static int pcm_substreams = 8; // todo
 | ||||||
|  | -//#define MUTE_CHECK
 | ||||||
|  | -#ifdef MUTE_CHECK
 | ||||||
|  | -static bool playback_mute_detected = false;
 | ||||||
|  | -#endif
 | ||||||
|  |   | ||||||
|  |  module_param(index, int, 0444); | ||||||
|  |  MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); | ||||||
|  | @@ -112,7 +106,8 @@ static int mr_alsa_audio_pcm_capture_copy(  struct snd_pcm_substream *substream,
 | ||||||
|  |  static int mr_alsa_audio_pcm_capture_copy_internal( struct snd_pcm_substream *substream, | ||||||
|                                              int channel, uint32_t pos, |                                              int channel, uint32_t pos, | ||||||
|                                              void __user *src, |                                              void __user *src, | ||||||
|                                              snd_pcm_uframes_t count); | -                                            snd_pcm_uframes_t count, bool to_user_space);
 | ||||||
|  | +                                            snd_pcm_uframes_t count,
 | ||||||
|  | +                                            bool to_user_space);
 | ||||||
|  |  static int mr_alsa_audio_pcm_playback_copy( struct snd_pcm_substream *substream, | ||||||
|  |                                              int channel, snd_pcm_uframes_t pos, | ||||||
|  |                                              void __user *src, | ||||||
|  | @@ -120,10 +115,8 @@ static int mr_alsa_audio_pcm_playback_copy( struct snd_pcm_substream *substream,
 | ||||||
|  |  static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *substream, | ||||||
|  |                                              int channel, uint32_t pos, | ||||||
|  |                                              void __user *src, | ||||||
|  | -                                            snd_pcm_uframes_t count);
 | ||||||
| -static int mr_alsa_audio_pcm_playback_silence(  struct snd_pcm_substream *substream,
 | -static int mr_alsa_audio_pcm_playback_silence(  struct snd_pcm_substream *substream,
 | ||||||
| -                                            int channel, snd_pcm_uframes_t pos,
 | -                                            int channel, snd_pcm_uframes_t pos,
 | ||||||
| -                                            snd_pcm_uframes_t count);
 | -                                            snd_pcm_uframes_t count);
 | ||||||
|  | +                                            snd_pcm_uframes_t count,
 | ||||||
|  | +                                            bool from_user_space);
 | ||||||
|   |   | ||||||
|  /// "chip" : the main private structure |  /// "chip" : the main private structure | ||||||
|  struct mr_alsa_audio_chip |  struct mr_alsa_audio_chip | ||||||
| @@ -177,9 +174,7 @@ struct mr_alsa_audio_chip
 | @@ -177,10 +170,14 @@ struct mr_alsa_audio_chip
 | ||||||
|      struct snd_card *card;  /* one card */ |      struct snd_card *card;  /* one card */ | ||||||
|      struct snd_pcm *pcm;    /* has one pcm */ |      struct snd_pcm *pcm;    /* has one pcm */ | ||||||
|       |       | ||||||
| -    struct snd_pcm_indirect pcm_playback_indirect;
 | -    struct snd_pcm_indirect pcm_playback_indirect;
 | ||||||
|      atomic_t dma_playback_offset; // to be used with atomic_read, atomic_set | -    atomic_t dma_playback_offset; // to be used with atomic_read, atomic_set
 | ||||||
| -    struct snd_pcm_indirect pcm_capture_indirect;
 | -    struct snd_pcm_indirect pcm_capture_indirect;
 | ||||||
|      atomic_t dma_capture_offset; // to be used with atomic_read, atomic_set  | -    atomic_t dma_capture_offset; // to be used with atomic_read, atomic_set 
 | ||||||
|  | +    uint32_t dma_playback_offset;
 | ||||||
|  | +    uint32_t dma_capture_offset;
 | ||||||
|  | +
 | ||||||
|  | +    unsigned int pcm_playback_buffer_size;
 | ||||||
|  | +    unsigned int pcm_capture_buffer_size;
 | ||||||
|  | +
 | ||||||
|  | +    uint8_t *dma_playback_buffer;
 | ||||||
|  | +    uint8_t *dma_capture_buffer;
 | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
| @@ -594,7 +589,7 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 |   | ||||||
|  | @@ -507,13 +504,28 @@ static void* mr_alsa_audio_get_playback_buffer(void *rawchip)
 | ||||||
|  |  } | ||||||
|  |  static uint32_t mr_alsa_audio_get_playback_buffer_size_in_frames(void *rawchip) | ||||||
|  |  { | ||||||
|  | -    if(rawchip)
 | ||||||
|  | +    uint32_t res = 0;
 | ||||||
|  | +    if (rawchip)
 | ||||||
|  |      { | ||||||
|  | -        struct mr_alsa_audio_chip *chip = (struct mr_alsa_audio_chip*)rawchip;
 | ||||||
|  | -        if(chip->playback_buffer)
 | ||||||
|  | -            return MR_ALSA_RINGBUFFER_NB_FRAMES;
 | ||||||
|  | +        struct mr_alsa_audio_chip* chip = (struct mr_alsa_audio_chip*)rawchip;
 | ||||||
|  | +        //spin_lock_irq(&chip->lock);
 | ||||||
|  | +        {
 | ||||||
|  | +            struct snd_pcm_runtime* runtime = chip->playback_substream ? chip->playback_substream->runtime : NULL;
 | ||||||
|  | +            if (chip->playback_buffer)
 | ||||||
|  | +            {
 | ||||||
|  | +                if (runtime && runtime->period_size != 0 && runtime->periods != 0)
 | ||||||
|  | +                {
 | ||||||
|  | +                    res = chip->current_dsd ? MR_ALSA_RINGBUFFER_NB_FRAMES : runtime->period_size * runtime->periods;
 | ||||||
|  | +                }
 | ||||||
|  | +                else
 | ||||||
|  | +                {
 | ||||||
|  | +                    res = MR_ALSA_RINGBUFFER_NB_FRAMES;
 | ||||||
|  | +                }
 | ||||||
|  | +            }
 | ||||||
|  | +        }
 | ||||||
|  | +        //spin_unlock_irq(&chip->lock);
 | ||||||
|  |      } | ||||||
|  | -    return 0;
 | ||||||
|  | +    return res;
 | ||||||
|  |   | ||||||
|  |  } | ||||||
|  |  static void* mr_alsa_audio_get_capture_buffer(void *rawchip) | ||||||
|  | @@ -594,7 +606,8 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | ||||||
|          uint32_t ring_buffer_size = MR_ALSA_RINGBUFFER_NB_FRAMES; // init to the max size possible |          uint32_t ring_buffer_size = MR_ALSA_RINGBUFFER_NB_FRAMES; // init to the max size possible | ||||||
|          uint32_t ptp_frame_size; |          uint32_t ptp_frame_size; | ||||||
|          struct mr_alsa_audio_chip *chip = (struct mr_alsa_audio_chip*)rawchip; |          struct mr_alsa_audio_chip *chip = (struct mr_alsa_audio_chip*)rawchip; | ||||||
| -        spin_lock_irq(&chip->lock);
 | -        spin_lock_irq(&chip->lock);
 | ||||||
|  | +
 | ||||||
| +        spin_lock(&chip->lock);
 | +        spin_lock(&chip->lock);
 | ||||||
|          chip->mr_alsa_audio_ops->get_interrupts_frame_size(chip->ravenna_peer, &ptp_frame_size); |          chip->mr_alsa_audio_ops->get_interrupts_frame_size(chip->ravenna_peer, &ptp_frame_size); | ||||||
|          if(direction == 1 && chip->capture_substream != NULL) |          if(direction == 1 && chip->capture_substream != NULL) | ||||||
|          { |          { | ||||||
| @@ -614,21 +609,30 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | @@ -611,24 +624,22 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | ||||||
|                  unsigned long bytes_to_frame_factor = runtime->channels * snd_pcm_format_physical_width(runtime->format) >> 3; |                  runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ||  | ||||||
|                  unsigned int pcm_buffer_size = snd_pcm_lib_buffer_bytes(chip->capture_substream); |                  runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) | ||||||
|                  unsigned int pos; |              { | ||||||
|  | -                unsigned long bytes_to_frame_factor = runtime->channels * snd_pcm_format_physical_width(runtime->format) >> 3;
 | ||||||
|  | -                unsigned int pcm_buffer_size = snd_pcm_lib_buffer_bytes(chip->capture_substream);
 | ||||||
|  | -                unsigned int pos;
 | ||||||
| -                uint32_t offset = 0;
 | -                uint32_t offset = 0;
 | ||||||
| +                //uint32_t offset = 0;
 | -                // char jitter_buffer_byte_len = 3;
 | ||||||
|                  // char jitter_buffer_byte_len = 3; | -                // chip->mr_alsa_audio_ops->get_jitter_buffer_sample_bytelength(chip->ravenna_peer, &jitter_buffer_byte_len);
 | ||||||
|                  // chip->mr_alsa_audio_ops->get_jitter_buffer_sample_bytelength(chip->ravenna_peer, &jitter_buffer_byte_len); |  | ||||||
| -                
 | -                
 | ||||||
|                  pos = atomic_read(&chip->dma_capture_offset); | -                pos = atomic_read(&chip->dma_capture_offset);
 | ||||||
| +
 | -                pos += ptp_frame_size * bytes_to_frame_factor;
 | ||||||
|                  pos += ptp_frame_size * bytes_to_frame_factor; | -                if (pos >= pcm_buffer_size)
 | ||||||
|                  if (pos >= pcm_buffer_size) | +                unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_capture_stride;
 | ||||||
|                  { |  | ||||||
|                      pos -= pcm_buffer_size; |  | ||||||
|                  } |  | ||||||
|                  atomic_set(&chip->dma_capture_offset, pos); |  | ||||||
| +
 | +
 | ||||||
| +                //printk(KERN_DEBUG "capture copy pos=%u, dma_pos=%u, count=%u, channels=%d pcm_size=%u\n", chip->capture_buffer_pos, pos, ptp_frame_size, runtime->channels, pcm_buffer_size);
 | +                //printk(KERN_DEBUG "capture copy pos=%u, dma_pos=%u, count=%u, channels=%d pcm_size=%u\n", chip->capture_buffer_pos, pos, ptp_frame_size, runtime->channels, pcm_buffer_size);
 | ||||||
| +                mr_alsa_audio_pcm_capture_copy_internal(chip->capture_substream,
 | +                mr_alsa_audio_pcm_capture_copy_internal(chip->capture_substream, runtime->channels/*channel*/,
 | ||||||
| +                    runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ? -1 : runtime->channels/*channel*/,
 | +                    chip->capture_buffer_pos, chip->dma_capture_buffer + chip->dma_capture_offset/**src*/, ptp_frame_size, false);
 | ||||||
| +                    chip->capture_buffer_pos, runtime->dma_area + pos/**src*/, ptp_frame_size, false);
 | +
 | ||||||
|                   | +                chip->dma_capture_offset += ptp_frame_size * bytes_to_frame_factor;
 | ||||||
|  | +                if (chip->dma_capture_offset >= chip->pcm_capture_buffer_size)
 | ||||||
|  |                  { | ||||||
|  | -                    pos -= pcm_buffer_size;
 | ||||||
|  | +                    chip->dma_capture_offset -= chip->pcm_capture_buffer_size;
 | ||||||
|  |                  } | ||||||
|  | -                atomic_set(&chip->dma_capture_offset, pos);
 | ||||||
|  | -                
 | ||||||
| -                chip->mr_alsa_audio_ops->get_input_jitter_buffer_offset(chip->ravenna_peer, &offset);
 | -                chip->mr_alsa_audio_ops->get_input_jitter_buffer_offset(chip->ravenna_peer, &offset);
 | ||||||
| +                //chip->mr_alsa_audio_ops->get_input_jitter_buffer_offset(chip->ravenna_peer, &offset);
 | -                //printk(KERN_DEBUG "Interrupt Capture pos = %u \n", offset);
 | ||||||
|                  //printk(KERN_DEBUG "Interrupt Capture pos = %u \n", offset); |  | ||||||
|              } |              } | ||||||
| +
 | +
 | ||||||
| +            chip->capture_buffer_pos += ptp_frame_size;
 | +            chip->capture_buffer_pos += ptp_frame_size;
 | ||||||
| @ -74,7 +146,7 @@ index 3d9debd..910ed5b 100644 | |||||||
|               |               | ||||||
|              /// Ravenna DSD always uses a rate of 352k with eventual zero padding to maintain a 32 bit alignment |              /// Ravenna DSD always uses a rate of 352k with eventual zero padding to maintain a 32 bit alignment | ||||||
|              /// while DSD in ALSA uses a continuous 8, 16 or 32 bit aligned stream with at 352k, 176k or 88k |              /// while DSD in ALSA uses a continuous 8, 16 or 32 bit aligned stream with at 352k, 176k or 88k | ||||||
| @@ -636,7 +640,9 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | @@ -636,7 +647,9 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | ||||||
|              if(++chip->current_capture_interrupt_idx >= chip->nb_capture_interrupts_per_period) |              if(++chip->current_capture_interrupt_idx >= chip->nb_capture_interrupts_per_period) | ||||||
|              { |              { | ||||||
|                  chip->current_capture_interrupt_idx = 0; |                  chip->current_capture_interrupt_idx = 0; | ||||||
| @ -84,20 +156,47 @@ index 3d9debd..910ed5b 100644 | |||||||
|              } |              } | ||||||
|          } |          } | ||||||
|          else if(direction == 0 && chip->playback_substream != NULL) |          else if(direction == 0 && chip->playback_substream != NULL) | ||||||
| @@ -659,6 +665,12 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | @@ -648,27 +661,27 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | ||||||
|                  unsigned int pos; |                  printk(KERN_ERR "mr_alsa_audio_pcm_interrupt playback period_size*periods > MR_ALSA_RINGBUFFER_NB_FRAMES\n"); | ||||||
|                   |                  return -2; | ||||||
|                  pos = atomic_read(&chip->dma_playback_offset); |              } | ||||||
|  | -            
 | ||||||
|  | +
 | ||||||
|  |              /// DMA case | ||||||
|  |              if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ||  | ||||||
|  |                  runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ||  | ||||||
|  |                  runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) | ||||||
|  |              { | ||||||
|  | -                unsigned long bytes_to_frame_factor = runtime->channels * snd_pcm_format_physical_width(runtime->format) >> 3;
 | ||||||
|  | -                unsigned int pcm_buffer_size = snd_pcm_lib_buffer_bytes(chip->playback_substream);
 | ||||||
|  | -                unsigned int pos;
 | ||||||
|  | -                
 | ||||||
|  | -                pos = atomic_read(&chip->dma_playback_offset);
 | ||||||
|  | -                pos += ptp_frame_size * bytes_to_frame_factor;
 | ||||||
|  | -                if (pos >= pcm_buffer_size)
 | ||||||
|  | +                unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_playback_stride;
 | ||||||
| +
 | +
 | ||||||
| +                //printk(KERN_DEBUG "playback copy pos=%u, dma_pos=%u, count=%u, channels=%d pcm_size=%u\n", chip->playback_buffer_pos, pos, ptp_frame_size, runtime->channels, pcm_buffer_size);
 | +                //printk(KERN_DEBUG "playback copy pos=%u, dma_pos=%u, count=%u, channels=%d pcm_size=%u\n", chip->playback_buffer_pos, pos, ptp_frame_size, runtime->channels, pcm_buffer_size);
 | ||||||
| +                mr_alsa_audio_pcm_playback_copy_internal(chip->playback_substream,
 | +                mr_alsa_audio_pcm_playback_copy_internal(chip->playback_substream, runtime->channels/*channel*/,
 | ||||||
| +                    runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ? -1 : runtime->channels/*channel*/,
 | +                    chip->playback_buffer_pos/*pos*/, chip->dma_playback_buffer + chip->dma_playback_offset/*src*/, ptp_frame_size/*count*/, false);
 | ||||||
| +                    chip->playback_buffer_pos/*pos*/, runtime->dma_area + pos/*src*/, ptp_frame_size/*count*/);
 |  | ||||||
| +
 | +
 | ||||||
|                  pos += ptp_frame_size * bytes_to_frame_factor; | +                chip->dma_playback_offset += ptp_frame_size * bytes_to_frame_factor;
 | ||||||
|                  if (pos >= pcm_buffer_size) | +                if (chip->dma_playback_offset >= chip->pcm_playback_buffer_size)
 | ||||||
|                  { |                  { | ||||||
| @@ -678,10 +690,12 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | -                    pos -= pcm_buffer_size;
 | ||||||
|  | +                    chip->dma_playback_offset -= chip->pcm_playback_buffer_size;
 | ||||||
|  |                  } | ||||||
|  | -                atomic_set(&chip->dma_playback_offset, pos);
 | ||||||
|  |              } | ||||||
|  | -            
 | ||||||
|  | +
 | ||||||
|  |              chip->playback_buffer_pos += ptp_frame_size; | ||||||
|  | -            if(chip->playback_buffer_pos >= ring_buffer_size)
 | ||||||
|  | +            if (chip->playback_buffer_pos >= ring_buffer_size)
 | ||||||
|  |                  chip->playback_buffer_pos -= ring_buffer_size; | ||||||
|  |   | ||||||
|  |              /// Ravenna DSD always uses a rate of 352k with eventual zero padding to maintain a 32 bit alignment | ||||||
|  | @@ -678,10 +691,12 @@ static int mr_alsa_audio_pcm_interrupt(void *rawchip, int direction)
 | ||||||
|              { |              { | ||||||
|                  chip->playback_buffer_rav_sac += ptp_frame_size; |                  chip->playback_buffer_rav_sac += ptp_frame_size; | ||||||
|                  chip->current_playback_interrupt_idx = 0; |                  chip->current_playback_interrupt_idx = 0; | ||||||
| @ -111,12 +210,18 @@ index 3d9debd..910ed5b 100644 | |||||||
|          return 0; |          return 0; | ||||||
|      } |      } | ||||||
|      return -1; |      return -1; | ||||||
| @@ -917,15 +931,12 @@ static int mr_alsa_audio_pcm_prepare(struct snd_pcm_substream *substream)
 | @@ -914,18 +929,15 @@ static int mr_alsa_audio_pcm_prepare(struct snd_pcm_substream *substream)
 | ||||||
|              // TODO: snd_pcm_format_set_silence(SNDRV_PCM_FORMAT_S24_3LE, chip->mr_alsa_audio_ops->, ) |              /// Fill the additional delay between the packet output and the sound eared | ||||||
|  |              chip->mr_alsa_audio_ops->get_playout_delay(chip->ravenna_peer, &runtime->delay); | ||||||
|   |   | ||||||
|              atomic_set(&chip->dma_playback_offset, 0); | -            // TODO: snd_pcm_format_set_silence(SNDRV_PCM_FORMAT_S24_3LE, chip->mr_alsa_audio_ops->, )
 | ||||||
|  | -
 | ||||||
|  | -            atomic_set(&chip->dma_playback_offset, 0);
 | ||||||
| -            memset(&chip->pcm_playback_indirect, 0, sizeof(chip->pcm_playback_indirect));
 | -            memset(&chip->pcm_playback_indirect, 0, sizeof(chip->pcm_playback_indirect));
 | ||||||
| -            chip->pcm_playback_indirect.hw_buffer_size = chip->pcm_playback_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
 | -            chip->pcm_playback_indirect.hw_buffer_size = chip->pcm_playback_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
 | ||||||
|  | +            chip->dma_playback_offset = 0;
 | ||||||
|  | +            chip->dma_playback_buffer = runtime->dma_area;
 | ||||||
|  | +            chip->pcm_playback_buffer_size = snd_pcm_lib_buffer_bytes(chip->playback_substream);
 | ||||||
|          } |          } | ||||||
|          else if(substream->stream == SNDRV_PCM_STREAM_CAPTURE) |          else if(substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||||||
|          { |          { | ||||||
| @ -127,17 +232,23 @@ index 3d9debd..910ed5b 100644 | |||||||
|              printk(KERN_DEBUG "mr_alsa_audio_pcm_prepare for capture stream\n"); |              printk(KERN_DEBUG "mr_alsa_audio_pcm_prepare for capture stream\n"); | ||||||
|              if(chip->ravenna_peer) |              if(chip->ravenna_peer) | ||||||
|              { |              { | ||||||
| @@ -946,9 +957,6 @@ static int mr_alsa_audio_pcm_prepare(struct snd_pcm_substream *substream)
 | @@ -943,12 +955,10 @@ static int mr_alsa_audio_pcm_prepare(struct snd_pcm_substream *substream)
 | ||||||
|              // TODO: snd_pcm_format_set_silence |              chip->capture_buffer_pos = offset; | ||||||
|  |              chip->current_capture_interrupt_idx = 0; | ||||||
|  |              chip->nb_capture_interrupts_per_period = ((runtime_dsd_mode != 0)? (MR_ALSA_PTP_FRAME_RATE_FOR_DSD / runtime->rate) : 1); | ||||||
|  | -            // TODO: snd_pcm_format_set_silence
 | ||||||
|               |               | ||||||
|              atomic_set(&chip->dma_capture_offset, 0); | -            atomic_set(&chip->dma_capture_offset, 0);
 | ||||||
| -            memset(&chip->pcm_capture_indirect, 0, sizeof(chip->pcm_capture_indirect));
 | -            memset(&chip->pcm_capture_indirect, 0, sizeof(chip->pcm_capture_indirect));
 | ||||||
| -            chip->pcm_capture_indirect.hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
 | -            chip->pcm_capture_indirect.hw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
 | ||||||
| -            chip->pcm_capture_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
 | -            chip->pcm_capture_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
 | ||||||
|  | +            chip->dma_capture_offset = 0;
 | ||||||
|  | +            chip->dma_capture_buffer = runtime->dma_area;
 | ||||||
|  | +            chip->pcm_capture_buffer_size = snd_pcm_lib_buffer_bytes(chip->capture_substream);
 | ||||||
|          } |          } | ||||||
|      } |      } | ||||||
|      else |      else | ||||||
| @@ -970,6 +978,7 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | @@ -970,6 +980,7 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | ||||||
|      uint32_t offset = 0; |      uint32_t offset = 0; | ||||||
|      //printk("entering mr_alsa_audio_pcm_pointer (substream name=%s #%d) ...\n", alsa_sub->name, alsa_sub->number); |      //printk("entering mr_alsa_audio_pcm_pointer (substream name=%s #%d) ...\n", alsa_sub->name, alsa_sub->number); | ||||||
|   |   | ||||||
| @ -145,29 +256,29 @@ index 3d9debd..910ed5b 100644 | |||||||
|      if(alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) |      if(alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||||||
|      { |      { | ||||||
|          /// DMA case |          /// DMA case | ||||||
| @@ -977,7 +986,9 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | @@ -977,7 +988,9 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | ||||||
|              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ||  |              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ||  | ||||||
|              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) |              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) | ||||||
|          { |          { | ||||||
| -            offset = snd_pcm_indirect_playback_pointer(alsa_sub, &chip->pcm_playback_indirect, atomic_read(&chip->dma_playback_offset));
 | -            offset = snd_pcm_indirect_playback_pointer(alsa_sub, &chip->pcm_playback_indirect, atomic_read(&chip->dma_playback_offset));
 | ||||||
| +            struct snd_pcm_runtime *runtime = alsa_sub->runtime;
 | +            struct snd_pcm_runtime *runtime = alsa_sub->runtime;
 | ||||||
| +            unsigned long bytes_to_frame_factor = runtime->channels * snd_pcm_format_physical_width(runtime->format) >> 3;
 | +            unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_playback_stride;
 | ||||||
| +            offset = atomic_read(&chip->dma_playback_offset) / bytes_to_frame_factor;
 | +            offset = chip->dma_playback_offset / bytes_to_frame_factor;
 | ||||||
|          } |          } | ||||||
|          else |          else | ||||||
|          { |          { | ||||||
| @@ -1010,7 +1021,9 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | @@ -1010,7 +1023,9 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | ||||||
|              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ||  |              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ||  | ||||||
|              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) |              alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) | ||||||
|          { |          { | ||||||
| -            offset = snd_pcm_indirect_capture_pointer(alsa_sub, &chip->pcm_capture_indirect, atomic_read(&chip->dma_capture_offset));
 | -            offset = snd_pcm_indirect_capture_pointer(alsa_sub, &chip->pcm_capture_indirect, atomic_read(&chip->dma_capture_offset));
 | ||||||
| +            struct snd_pcm_runtime *runtime = alsa_sub->runtime;
 | +            struct snd_pcm_runtime *runtime = alsa_sub->runtime;
 | ||||||
| +            unsigned long bytes_to_frame_factor = runtime->channels * snd_pcm_format_physical_width(runtime->format) >> 3;
 | +            unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_capture_stride;
 | ||||||
| +            offset = atomic_read(&chip->dma_capture_offset) / bytes_to_frame_factor;
 | +            offset = chip->dma_capture_offset / bytes_to_frame_factor;
 | ||||||
|          } |          } | ||||||
|          else |          else | ||||||
|          { |          { | ||||||
| @@ -1036,6 +1049,7 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | @@ -1036,6 +1051,7 @@ static snd_pcm_uframes_t mr_alsa_audio_pcm_pointer(struct snd_pcm_substream *als
 | ||||||
|          } |          } | ||||||
|          //printk("mr_alsa_audio_pcm_pointer capture offset = %u\n", offset); |          //printk("mr_alsa_audio_pcm_pointer capture offset = %u\n", offset); | ||||||
|      } |      } | ||||||
| @ -175,11 +286,438 @@ index 3d9debd..910ed5b 100644 | |||||||
|      return offset; |      return offset; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -1555,230 +1607,6 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 | @@ -1152,9 +1168,10 @@ static int mr_alsa_audio_pcm_capture_copy_user(  struct snd_pcm_substream *subst
 | ||||||
|  |                                              void __user *src, | ||||||
|  |                                              unsigned long count) | ||||||
|  |   { | ||||||
|  | +    struct mr_alsa_audio_chip* chip = snd_pcm_substream_chip(substream);
 | ||||||
|  |      struct snd_pcm_runtime *runtime = substream->runtime; | ||||||
|  |      bool interleaved = runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ? 1 : 0; | ||||||
|  | -    unsigned long bytes_to_frame_factor = runtime->channels * snd_pcm_format_physical_width(runtime->format) >> 3;
 | ||||||
|  | +    unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_capture_stride;
 | ||||||
|  |      return mr_alsa_audio_pcm_capture_copy(substream, interleaved ? -1 : channel, pos / bytes_to_frame_factor, src, count / bytes_to_frame_factor); | ||||||
|  |  } | ||||||
|  |  #endif | ||||||
|  | @@ -1173,13 +1190,14 @@ static int mr_alsa_audio_pcm_capture_copy(  struct snd_pcm_substream *substream,
 | ||||||
|  |  static int mr_alsa_audio_pcm_capture_copy_internal(  struct snd_pcm_substream *substream, | ||||||
|  |                                              int channel, uint32_t pos, | ||||||
|  |                                              void __user *src, | ||||||
|  | -                                            snd_pcm_uframes_t count, bool to_user_space)
 | ||||||
|  | +                                            snd_pcm_uframes_t count,
 | ||||||
|  | +                                            bool to_user_space)
 | ||||||
|  |  { | ||||||
|  |      struct mr_alsa_audio_chip *chip = snd_pcm_substream_chip(substream); | ||||||
|  |      struct snd_pcm_runtime *runtime = substream->runtime; | ||||||
|  | -    int interleaved = ((channel == -1 && runtime->channels > 1)? 1 : 0);
 | ||||||
|  | +    bool interleaved = (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
 | ||||||
|  |      unsigned int nb_logical_bits = snd_pcm_format_width(runtime->format); | ||||||
|  | -    unsigned int strideIn = snd_pcm_format_physical_width(runtime->format) >> 3;
 | ||||||
|  | +    unsigned int strideIn = chip->current_alsa_capture_stride;
 | ||||||
|  |      uint32_t ravenna_buffer_pos = pos; | ||||||
|  |   | ||||||
|  |      // todo DSD capture | ||||||
|  | @@ -1204,12 +1222,7 @@ static int mr_alsa_audio_pcm_capture_copy_internal(  struct snd_pcm_substream *s
 | ||||||
|  |   | ||||||
|  |   | ||||||
|  |      if(interleaved) | ||||||
|  | -    {
 | ||||||
|  | -        int ret_pu;
 | ||||||
|  | -        char val = 0xf1;
 | ||||||
|  | -        __put_user_x(1, val, (unsigned long __user *)src, ret_pu);
 | ||||||
|  | -        ret_pu = put_user(val, (unsigned long __user *)src);
 | ||||||
|  | -        //put_user(val, (unsigned long __user *)src);
 | ||||||
|  | +    {
 | ||||||
|  |          switch(nb_logical_bits) | ||||||
|  |          { | ||||||
|  |              case 16: | ||||||
|  | @@ -1244,8 +1257,8 @@ static int mr_alsa_audio_pcm_capture_copy_internal(  struct snd_pcm_substream *s
 | ||||||
|  |          return -EINVAL; | ||||||
|  |      } | ||||||
|  |      return count; | ||||||
|  | -
 | ||||||
|  |  } | ||||||
|  | +
 | ||||||
|  |  /// This callback is called whenever the alsa application wants to write data | ||||||
|  |  /// We use it here to do all the de-interleaving, format conversion and DSD re-packing | ||||||
|  |  /// The intermediate buffer is actually the alsa (dma) buffer, allocated in hw_params() | ||||||
|  | @@ -1256,10 +1269,10 @@ static int mr_alsa_audio_pcm_playback_copy_user(  struct snd_pcm_substream *subs
 | ||||||
|  |                                              void __user *src, | ||||||
|  |                                              unsigned long count) | ||||||
|  |  { | ||||||
|  | +    struct mr_alsa_audio_chip* chip = snd_pcm_substream_chip(substream);
 | ||||||
|  |      struct snd_pcm_runtime *runtime = substream->runtime; | ||||||
|  | -    bool interleaved = runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ? 1 : 0;
 | ||||||
|  | -    unsigned long bytes_to_frame_factor = runtime->channels * snd_pcm_format_physical_width(runtime->format) >> 3;
 | ||||||
|  | -    return mr_alsa_audio_pcm_playback_copy(substream, interleaved ? -1 : channel, pos / bytes_to_frame_factor, src, count / bytes_to_frame_factor);
 | ||||||
|  | +    unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_playback_stride;
 | ||||||
|  | +    return mr_alsa_audio_pcm_playback_copy(substream, channel, pos / bytes_to_frame_factor, src, count / bytes_to_frame_factor);
 | ||||||
|  |  } | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | @@ -1278,126 +1291,68 @@ static int mr_alsa_audio_pcm_playback_copy( struct snd_pcm_substream *substream,
 | ||||||
|  |      /// so respective ring buffers might have different scale and size | ||||||
|  |      uint32_t ravenna_buffer_pos = pos * chip->nb_playback_interrupts_per_period; | ||||||
|  |       | ||||||
|  | -    if(snd_BUG_ON(ravenna_buffer_pos >= MR_ALSA_RINGBUFFER_NB_FRAMES))
 | ||||||
|  | -        ravenna_buffer_pos -= MR_ALSA_RINGBUFFER_NB_FRAMES;
 | ||||||
|  | -    
 | ||||||
|  | -    return mr_alsa_audio_pcm_playback_copy_internal(substream, channel, ravenna_buffer_pos, src, count);
 | ||||||
|  | +    return mr_alsa_audio_pcm_playback_copy_internal(substream, channel, ravenna_buffer_pos, src, count, true);
 | ||||||
|  |  } | ||||||
|  | -///
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *substream, | ||||||
|  |                                              int channel, uint32_t pos, | ||||||
|  |                                              void __user *src, | ||||||
|  | -                                            snd_pcm_uframes_t count)
 | ||||||
|  | +                                            snd_pcm_uframes_t count,
 | ||||||
|  | +                                            bool from_user_space)
 | ||||||
|  |  { | ||||||
|  |      struct mr_alsa_audio_chip *chip = snd_pcm_substream_chip(substream); | ||||||
|  |      struct snd_pcm_runtime *runtime = substream->runtime; | ||||||
|  |      int chn = 0; | ||||||
|  | -    //int interleaved = ((channel == -1 && runtime->channels > 1)? 1 : 0);
 | ||||||
|  | -    int interleaved = runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ? 1 : 0;
 | ||||||
|  | +    bool interleaved = (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
 | ||||||
|  |      unsigned int nb_logical_bits = snd_pcm_format_width(runtime->format); | ||||||
|  | -    unsigned int strideIn = snd_pcm_format_physical_width(runtime->format) >> 3;
 | ||||||
|  | +    unsigned int strideIn = chip->current_alsa_playback_stride;
 | ||||||
|  |      unsigned int strideOut = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE) >> 3; | ||||||
|  |      uint32_t dsdrate = mr_alsa_audio_get_dsd_sample_rate(runtime->format, runtime->rate); | ||||||
|  |      uint32_t dsdmode = (dsdrate > 0? mr_alsa_audio_get_dsd_mode(dsdrate) : 0); | ||||||
|  |      uint32_t ravenna_buffer_pos = pos; | ||||||
|  | -    //uint32_t alsa_ring_buffer_nb_frames = MR_ALSA_RINGBUFFER_NB_FRAMES / chip->nb_playback_interrupts_per_period;
 | ||||||
|  | -
 | ||||||
|  | -    #ifdef MUTE_CHECK
 | ||||||
|  | -        // mute check
 | ||||||
|  | -        unsigned char *buffer_to_check = chip->playback_buffer + ravenna_buffer_pos * strideOut; // output buffer channel 0
 | ||||||
|  | -        bool mute_detected = false;
 | ||||||
|  | -        char testblock [256];
 | ||||||
|  | -        memset(testblock, 0, sizeof(testblock));
 | ||||||
|  | -    #endif
 | ||||||
|  | -    
 | ||||||
|  | -    if (channel > 0 && channel >= runtime->channels)
 | ||||||
|  | -    {
 | ||||||
|  | -        printk(KERN_WARNING "Channel %d copy ignored because it does not fit the available runtime channels (%d)", channel, runtime->channels);
 | ||||||
|  | -       return 0;
 | ||||||
|  | -    }
 | ||||||
|  | -
 | ||||||
|  | -    //printk(KERN_DEBUG "entering mr_alsa_audio_pcm_playback_copy (substream name=%s #%d) (runtime channels %d) access %d...\n", substream->name, substream->number, runtime->channels, runtime->access));
 | ||||||
|  | -
 | ||||||
|  | -    /*if(snd_BUG_ON(chip->playback_buffer_rav_sac > chip->playback_buffer_alsa_sac))
 | ||||||
|  | -    {
 | ||||||
|  | -        printk(KERN_WARNING "mr_alsa_audio_pcm_playback_copy: Playback stall. Missing playback data from the player application.");
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | -    }
 | ||||||
|  | -
 | ||||||
|  | -    //printk("playback_copy: initial count = %u, alsa_ring_buffer_nb_frames = %u \n", count, alsa_ring_buffer_nb_frames);
 | ||||||
|  | -    if(alsa_ring_buffer_nb_frames < chip->playback_buffer_alsa_sac - chip->playback_buffer_rav_sac)
 | ||||||
|  | -    {
 | ||||||
|  | -        count = 0; /// no room for more playback at the moment
 | ||||||
|  | -        printk(KERN_WARNING "playback_copy: no room at the moment (count =%lu) \n", count);
 | ||||||
|  | -    }
 | ||||||
|  | -
 | ||||||
|  | -    if(count > alsa_ring_buffer_nb_frames - (chip->playback_buffer_alsa_sac - chip->playback_buffer_rav_sac))
 | ||||||
|  | -    {
 | ||||||
|  | -        snd_pcm_uframes_t new_count = (snd_pcm_uframes_t)(alsa_ring_buffer_nb_frames - (chip->playback_buffer_alsa_sac - chip->playback_buffer_rav_sac));
 | ||||||
|  | -        printk(KERN_WARNING "playback_copy count overflow 1: change count from %lu to %lu\n", count, new_count);
 | ||||||
|  | -        count = new_count;
 | ||||||
|  | -    }
 | ||||||
|  | -    if(count * chip->nb_playback_interrupts_per_period + ravenna_buffer_pos > MR_ALSA_RINGBUFFER_NB_FRAMES)
 | ||||||
|  | -    {
 | ||||||
|  | -        snd_pcm_uframes_t new_count = (MR_ALSA_RINGBUFFER_NB_FRAMES - ravenna_buffer_pos) / chip->nb_playback_interrupts_per_period;
 | ||||||
|  | -        printk(KERN_WARNING "playback_copy count overflow 2: change count from %lu to %lu\n", count, new_count);
 | ||||||
|  | -        count = new_count;
 | ||||||
|  | -    }*/
 | ||||||
|  |   | ||||||
|  |      //printk("playback_copy: rate = %u, dsdmode = %u, #IRQ per period = %u, count = %u, pos = %lu, ravenna_buffer_pos = %u, alsa_pb_sac = %llu, ravenna_pb_sac = %llu\n", (dsdrate > 0? dsdrate : runtime->rate), dsdmode, chip->nb_playback_interrupts_per_period, count, pos, ravenna_buffer_pos, chip->playback_buffer_alsa_sac, chip->playback_buffer_rav_sac); | ||||||
|  | -    if(count == 0)
 | ||||||
|  | -        return 0;
 | ||||||
|  |       | ||||||
|  |      if(interleaved) | ||||||
|  |      { | ||||||
|  | +        /// de-interleaving
 | ||||||
|  | +        unsigned char *in, *out;
 | ||||||
|  | +        unsigned int stepIn = runtime->channels * strideIn;
 | ||||||
|  | +        unsigned int stepOut = strideOut * chip->nb_playback_interrupts_per_period;
 | ||||||
|  | +        uint32_t ring_buffer_size = MR_ALSA_RINGBUFFER_NB_FRAMES * strideOut;
 | ||||||
|  | +        //printk("playback_copy: de-interleaving %u frames, pos = %llu, ravenna_buffer_pos = %u, with strideIn = %u, strideOut = %u, stepIn = %u, stepOut = %u, ravBuffer_csize = %u \n", count, pos, ravenna_buffer_pos, strideIn, strideOut, stepIn, stepOut, (unsigned int)ravBuffer_csize);
 | ||||||
|  | +
 | ||||||
|  | +        if (from_user_space)
 | ||||||
|  |          { | ||||||
|  | -            /// de-interleaving
 | ||||||
|  | -            unsigned char *in, *out;
 | ||||||
|  | -            unsigned int stepIn = runtime->channels * strideIn;
 | ||||||
|  | -            unsigned int stepOut = strideOut * chip->nb_playback_interrupts_per_period;
 | ||||||
|  | -            size_t ravBuffer_csize = MR_ALSA_RINGBUFFER_NB_FRAMES * strideOut;
 | ||||||
|  | -            //printk("playback_copy: de-interleaving %u frames, pos = %llu, ravenna_buffer_pos = %u, with strideIn = %u, strideOut = %u, stepIn = %u, stepOut = %u, ravBuffer_csize = %u \n", count, pos, ravenna_buffer_pos, strideIn, strideOut, stepIn, stepOut, (unsigned int)ravBuffer_csize);
 | ||||||
|  | -            for(chn = 0; chn < runtime->channels; ++chn)
 | ||||||
|  | +            for (chn = 0; chn < runtime->channels; ++chn)
 | ||||||
|  |              { | ||||||
|  |                  uint32_t currentOutPos = ravenna_buffer_pos * strideOut; | ||||||
|  |                  snd_pcm_uframes_t frmCnt = 0; | ||||||
|  |                  in = (unsigned char*)src + chn * strideIn; | ||||||
|  | -                out = chip->playback_buffer + chn * ravBuffer_csize + currentOutPos;
 | ||||||
|  | -
 | ||||||
|  | +                out = chip->playback_buffer + chn * ring_buffer_size + currentOutPos;
 | ||||||
|  | +                //
 | ||||||
|  |                  ///Conversion to Signed integer 32 bit LE | ||||||
|  | -                for(frmCnt = 0; frmCnt < count; ++frmCnt)
 | ||||||
|  | +                for (frmCnt = 0; frmCnt < count; ++frmCnt)
 | ||||||
|  |                  { | ||||||
|  |                      /// assumes Little Endian | ||||||
|  |                      int32_t val = 0; | ||||||
|  | -                    if(dsdmode == 0)
 | ||||||
|  | +                    if (dsdmode == 0)
 | ||||||
|  |                      { | ||||||
|  | -                        switch(nb_logical_bits)
 | ||||||
|  | +                        switch (nb_logical_bits)
 | ||||||
|  |                          { | ||||||
|  | -                            case 16:
 | ||||||
|  | -                                //val = (((int32_t)(in[1]) << 8) | ((int32_t)(in[0]))) << 16;
 | ||||||
|  | -                                // OR
 | ||||||
|  | -                                //((unsigned char*)&val)[3] = in[1];
 | ||||||
|  | -                                //((unsigned char*)&val)[2] = in[0];
 | ||||||
|  | -                                // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[3], &in[1]);
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[2], &in[0]);
 | ||||||
|  | -                                break;
 | ||||||
|  | -                            case 24:
 | ||||||
|  | -                                //val = (((int32_t)(in[2]) << 16) | ((int32_t)(in[1]) << 8) | ((int32_t)(in[0]))) << 8;
 | ||||||
|  | -                                // OR
 | ||||||
|  | -                                // ((unsigned char*)&val)[3] = in[2];
 | ||||||
|  | -                                // ((unsigned char*)&val)[2] = in[1];
 | ||||||
|  | -                                // ((unsigned char*)&val)[1] = in[0];
 | ||||||
|  | -                                // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[3], &in[2]);
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[2], &in[1]);
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[1], &in[0]);
 | ||||||
|  | -                                break;
 | ||||||
|  | -                            case 32:
 | ||||||
|  | -                                //val = *(int32_t*)(in);
 | ||||||
|  | -                                // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                __get_user(val, (int32_t*)in);
 | ||||||
|  | -                                break;
 | ||||||
|  | +                        case 16:
 | ||||||
|  | +                            __get_user(((unsigned char*)&val)[3], &in[1]);
 | ||||||
|  | +                            __get_user(((unsigned char*)&val)[2], &in[0]);
 | ||||||
|  | +                            break;
 | ||||||
|  | +                        case 24:
 | ||||||
|  | +                            __get_user(((unsigned char*)&val)[3], &in[2]);
 | ||||||
|  | +                            __get_user(((unsigned char*)&val)[2], &in[1]);
 | ||||||
|  | +                            __get_user(((unsigned char*)&val)[1], &in[0]);
 | ||||||
|  | +                            break;
 | ||||||
|  | +                        case 32:
 | ||||||
|  | +                            __get_user(val, (int32_t*)in);
 | ||||||
|  | +                            break;
 | ||||||
|  |                          } | ||||||
|  |                          *((int32_t*)out) = val; | ||||||
|  |                      } | ||||||
|  | @@ -1405,34 +1360,30 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 | ||||||
|  |                      { | ||||||
|  |                          /// interleaved DSD stream to non interleaved 32 bit aligned blocks with 1/2/4 DSD bytes per 32 bit | ||||||
|  |                          uint32_t out_cnt; | ||||||
|  | -                        for(out_cnt = 0; out_cnt < chip->nb_playback_interrupts_per_period; ++out_cnt)
 | ||||||
|  | +                        for (out_cnt = 0; out_cnt < chip->nb_playback_interrupts_per_period; ++out_cnt)
 | ||||||
|  |                          { | ||||||
|  | -                            switch(dsdmode)
 | ||||||
|  | +                            switch (dsdmode)
 | ||||||
|  |                              { | ||||||
|  | -                                case 1: ///DSD64
 | ||||||
|  | -                                    //val = *(int32_t*)(in + out_cnt) & 0xFF;
 | ||||||
|  | -                                    __get_user(((unsigned char*)&val)[0], &in[out_cnt]);
 | ||||||
|  | -                                    break;
 | ||||||
|  | -                                case 2: ///DSD128
 | ||||||
|  | -                                    //val = (((int32_t)(in[2 * out_cnt + 1]) << 8) | ((int32_t)(in[2 * out_cnt]))) & 0xFFFF;
 | ||||||
|  | -                                    __get_user(((unsigned char*)&val)[1], &in[2 * out_cnt + 1]);
 | ||||||
|  | -                                    __get_user(((unsigned char*)&val)[0], &in[2 * out_cnt]);
 | ||||||
|  | -                                    break;
 | ||||||
|  | -                                case 4: ///DSD256
 | ||||||
|  | -                                    //val = *(int32_t*)(in);
 | ||||||
|  | -                                    // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                    __get_user(val, (int32_t*)in);
 | ||||||
|  | -                                    break;
 | ||||||
|  | +                            case 1: ///DSD64
 | ||||||
|  | +                                __get_user(((unsigned char*)&val)[0], &in[out_cnt]);
 | ||||||
|  | +                                break;
 | ||||||
|  | +                            case 2: ///DSD128
 | ||||||
|  | +                                __get_user(((unsigned char*)&val)[1], &in[2 * out_cnt + 1]);
 | ||||||
|  | +                                __get_user(((unsigned char*)&val)[0], &in[2 * out_cnt]);
 | ||||||
|  | +                                break;
 | ||||||
|  | +                            case 4: ///DSD256
 | ||||||
|  | +                                __get_user(val, (int32_t*)in);
 | ||||||
|  | +                                break;
 | ||||||
|  |                              } | ||||||
|  |                              ((int32_t*)out)[out_cnt] = val; | ||||||
|  |                          } | ||||||
|  |                      } | ||||||
|  |   | ||||||
|  |                      in += stepIn; | ||||||
|  | -                    if(currentOutPos + stepOut >= ravBuffer_csize)
 | ||||||
|  | +                    if (currentOutPos + stepOut >= ring_buffer_size)
 | ||||||
|  |                      { | ||||||
|  |                          currentOutPos = 0; | ||||||
|  | -                        out = chip->playback_buffer + chn * ravBuffer_csize;
 | ||||||
|  | +                        out = chip->playback_buffer + chn * ring_buffer_size;
 | ||||||
|  |                      } | ||||||
|  |                      else | ||||||
|  |                      { | ||||||
|  | @@ -1442,56 +1393,37 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 | ||||||
|  |                  } | ||||||
|  |              } | ||||||
|  |          } | ||||||
|  | -    }
 | ||||||
|  | -    else
 | ||||||
|  | -    {
 | ||||||
|  | +        else
 | ||||||
|  |          { | ||||||
|  | -            //printk("mr_alsa_audio_pcm_playback_copy: no de-interleaving, converting %u frames with strideIn = %u\n", count, strideIn);
 | ||||||
|  | -            /// do the format conversion to the Ravenna Ring buffer
 | ||||||
|  | +            for (chn = 0; chn < runtime->channels; ++chn)
 | ||||||
|  |              { | ||||||
|  | -                unsigned char *in, *out;
 | ||||||
|  | -                unsigned int stepIn = strideIn;
 | ||||||
|  | -                unsigned int stepOut = strideOut * chip->nb_playback_interrupts_per_period;
 | ||||||
|  | -                size_t ravBuffer_csize = MR_ALSA_RINGBUFFER_NB_FRAMES * strideOut;
 | ||||||
|  |                  uint32_t currentOutPos = ravenna_buffer_pos * strideOut; | ||||||
|  |                  snd_pcm_uframes_t frmCnt = 0; | ||||||
|  | -
 | ||||||
|  | -                in = (unsigned char*)src;
 | ||||||
|  | -                out = chip->playback_buffer + channel * ravBuffer_csize + currentOutPos;
 | ||||||
|  | -                for(frmCnt = 0; frmCnt < count; ++frmCnt)
 | ||||||
|  | +                in = (unsigned char*)src + chn * strideIn;
 | ||||||
|  | +                out = chip->playback_buffer + chn * ring_buffer_size + currentOutPos;
 | ||||||
|  | +                //
 | ||||||
|  | +                ///Conversion to Signed integer 32 bit LE
 | ||||||
|  | +                for (frmCnt = 0; frmCnt < count; ++frmCnt)
 | ||||||
|  |                  { | ||||||
|  | -                    /// conversion to signed 32 bit integer LE
 | ||||||
|  |                      /// assumes Little Endian | ||||||
|  | -                     int32_t val = 0;
 | ||||||
|  | -                    if(dsdmode == 0)
 | ||||||
|  | +                    int32_t val = 0;
 | ||||||
|  | +                    if (dsdmode == 0)
 | ||||||
|  |                      { | ||||||
|  | -                        switch(nb_logical_bits)
 | ||||||
|  | +                        switch (nb_logical_bits)
 | ||||||
|  |                          { | ||||||
|  | -                            case 16:
 | ||||||
|  | -                                //val = (((int32_t)(in[1]) << 8) | ((int32_t)(in[0]))) << 16;
 | ||||||
|  | -                                // OR
 | ||||||
|  | -                                //((unsigned char*)&val)[3] = in[1];
 | ||||||
|  | -                                //((unsigned char*)&val)[2] = in[0];
 | ||||||
|  | -                                // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[3], &in[1]);
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[2], &in[0]);
 | ||||||
|  | -                                break;
 | ||||||
|  | -                            case 24:
 | ||||||
|  | -                                //val = (((int32_t)(in[2]) << 16) | ((int32_t)(in[1]) << 8) | ((int32_t)(in[0]))) << 8;
 | ||||||
|  | -                                // OR
 | ||||||
|  | -                                // ((unsigned char*)&val)[3] = in[2];
 | ||||||
|  | -                                // ((unsigned char*)&val)[2] = in[1];
 | ||||||
|  | -                                // ((unsigned char*)&val)[1] = in[0];
 | ||||||
|  | -                                // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[3], &in[2]);
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[2], &in[1]);
 | ||||||
|  | -                                __get_user(((unsigned char*)&val)[1], &in[0]);
 | ||||||
|  | -                                break;
 | ||||||
|  | -                            case 32:
 | ||||||
|  | -                                //val = *(int32_t*)(in);
 | ||||||
|  | -                                // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                __get_user(val, (int32_t*)in);
 | ||||||
|  | -                                break;
 | ||||||
|  | +                        case 16:
 | ||||||
|  | +
 | ||||||
|  | +                            ((unsigned char*)&val)[3] = in[1];
 | ||||||
|  | +                            ((unsigned char*)&val)[2] = in[0];
 | ||||||
|  | +                            break;
 | ||||||
|  | +                        case 24:
 | ||||||
|  | +                            ((unsigned char*)&val)[3] = in[2];
 | ||||||
|  | +                            ((unsigned char*)&val)[2] = in[1];
 | ||||||
|  | +                            ((unsigned char*)&val)[1] = in[0];
 | ||||||
|  | +                            break;
 | ||||||
|  | +                        case 32:
 | ||||||
|  | +                            val = *(int32_t*)(in);
 | ||||||
|  | +                            break;
 | ||||||
|  |                          } | ||||||
|  |                          *((int32_t*)out) = val; | ||||||
|  |                      } | ||||||
|  | @@ -1499,33 +1431,29 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 | ||||||
|  |                      { | ||||||
|  |                          /// interleaved DSD stream to non interleaved 32 bit aligned blocks with 1/2/4 DSD bytes per 32 bit | ||||||
|  |                          uint32_t out_cnt; | ||||||
|  | -                        for(out_cnt = 0; out_cnt < chip->nb_playback_interrupts_per_period; ++out_cnt)
 | ||||||
|  | +                        for (out_cnt = 0; out_cnt < chip->nb_playback_interrupts_per_period; ++out_cnt)
 | ||||||
|  |                          { | ||||||
|  | -                            switch(dsdmode)
 | ||||||
|  | +                            switch (dsdmode)
 | ||||||
|  |                              { | ||||||
|  | -                                case 1: ///DSD64
 | ||||||
|  | -                                    //val = *(int32_t*)(in + out_cnt) & 0xFF;
 | ||||||
|  | -                                    __get_user(((unsigned char*)&val)[0], &in[out_cnt]);
 | ||||||
|  | -                                    break;
 | ||||||
|  | -                                case 2: ///DSD128
 | ||||||
|  | -                                    //val = (((int32_t)(in[2 * out_cnt + 1]) << 8) | ((int32_t)(in[2 * out_cnt]))) & 0xFFFF;
 | ||||||
|  | -                                    __get_user(((unsigned char*)&val)[1], &in[2 * out_cnt + 1]);
 | ||||||
|  | -                                    __get_user(((unsigned char*)&val)[0], &in[2 * out_cnt]);
 | ||||||
|  | -                                    break;
 | ||||||
|  | -                                case 4: ///DSD256
 | ||||||
|  | -                                    //val = *(int32_t*)(in);
 | ||||||
|  | -                                    // OR without intermediate copy_from_user buffer
 | ||||||
|  | -                                    __get_user(val, (int32_t*)in);
 | ||||||
|  | -                                    break;
 | ||||||
|  | +                            case 1: ///DSD64
 | ||||||
|  | +                                val = *(int32_t*)(in + out_cnt) & 0xFF;
 | ||||||
|  | +                                break;
 | ||||||
|  | +                            case 2: ///DSD128
 | ||||||
|  | +                                val = (((int32_t)(in[2 * out_cnt + 1]) << 8) | ((int32_t)(in[2 * out_cnt]))) & 0xFFFF;
 | ||||||
|  | +                                break;
 | ||||||
|  | +                            case 4: ///DSD256
 | ||||||
|  | +                                val = *(int32_t*)(in);
 | ||||||
|  | +                                break;
 | ||||||
|  |                              } | ||||||
|  |                              ((int32_t*)out)[out_cnt] = val; | ||||||
|  |                          } | ||||||
|  |                      } | ||||||
|  | +
 | ||||||
|  |                      in += stepIn; | ||||||
|  | -                    if(currentOutPos + stepOut >= ravBuffer_csize)
 | ||||||
|  | +                    if (currentOutPos + stepOut >= ring_buffer_size)
 | ||||||
|  |                      { | ||||||
|  |                          currentOutPos = 0; | ||||||
|  | -                        out = chip->playback_buffer + channel * ravBuffer_csize;
 | ||||||
|  | +                        out = chip->playback_buffer + chn * ring_buffer_size;
 | ||||||
|  |                      } | ||||||
|  |                      else | ||||||
|  |                      { | ||||||
|  | @@ -1536,248 +1464,17 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 | ||||||
|  |              } | ||||||
|  |          } | ||||||
|  |      } | ||||||
|  | -    
 | ||||||
|  | -    
 | ||||||
|  | -    #ifdef MUTE_CHECK
 | ||||||
|  | -    // First channel check
 | ||||||
|  | -    mute_detected = !memcmp(testblock, buffer_to_check, min((ssize_t )256, frames_to_bytes(runtime, count)));
 | ||||||
|  | -    if (mute_detected != playback_mute_detected)
 | ||||||
|  | +    else
 | ||||||
|  |      { | ||||||
|  | -        if (mute_detected)
 | ||||||
|  | -            printk(">>>>Playback buffer mute detected\n");
 | ||||||
|  | -        else
 | ||||||
|  | -            printk(">>>>Playback buffer signal detected\n");
 | ||||||
|  | -        playback_mute_detected = mute_detected;
 | ||||||
|  | +        printk(KERN_WARNING "Uninterleaved Playback is not supported\n");
 | ||||||
|  | +        return -EINVAL;
 | ||||||
|  |      } | ||||||
|  | -    #endif
 | ||||||
|  |       | ||||||
|  |      chip->playback_buffer_alsa_sac += count; | ||||||
|      return count; |      return count; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| -
 |   | ||||||
| -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
 | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
 | ||||||
| -static int mr_alsa_audio_pcm_playback_fill_silence(  struct snd_pcm_substream *substream,
 | -static int mr_alsa_audio_pcm_playback_fill_silence(  struct snd_pcm_substream *substream,
 | ||||||
| -                                            int channel, unsigned long pos,
 | -                                            int channel, unsigned long pos,
 | ||||||
| @ -402,34 +940,43 @@ index 3d9debd..910ed5b 100644 | |||||||
| -    }
 | -    }
 | ||||||
| -    return 0;
 | -    return 0;
 | ||||||
| -}
 | -}
 | ||||||
| -
 |   | ||||||
|  /// hw_params callback |  /// hw_params callback | ||||||
|  /// This is called when the hardware parameter (hw_params) is set up by the application, that is, once when |  /// This is called when the hardware parameter (hw_params) is set up by the application, that is, once when | ||||||
|  /// the buffer size, the period size, the format, etc. are defined for the pcm substream. | @@ -2339,14 +2032,10 @@ static struct snd_pcm_ops mr_alsa_audio_pcm_playback_ops = {
 | ||||||
| @@ -2340,13 +2168,13 @@ static struct snd_pcm_ops mr_alsa_audio_pcm_playback_ops = {
 |      .pointer =  mr_alsa_audio_pcm_pointer, | ||||||
|  #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) |  #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) | ||||||
|      .copy_user = mr_alsa_audio_pcm_playback_copy_user, |      .copy_user = mr_alsa_audio_pcm_playback_copy_user, | ||||||
|      //.copy_kernel = mr_alsa_audio_pcm_playback_copy, | -    //.copy_kernel = mr_alsa_audio_pcm_playback_copy,
 | ||||||
| -    .fill_silence = mr_alsa_audio_pcm_playback_fill_silence,
 | -    .fill_silence = mr_alsa_audio_pcm_playback_fill_silence,
 | ||||||
| +    //.fill_silence = mr_alsa_audio_pcm_playback_fill_silence,
 |  | ||||||
|  #else |  #else | ||||||
|      .copy =     mr_alsa_audio_pcm_playback_copy, |      .copy =     mr_alsa_audio_pcm_playback_copy, | ||||||
| -    .silence =  mr_alsa_audio_pcm_playback_silence,
 | -    .silence =  mr_alsa_audio_pcm_playback_silence,
 | ||||||
| +    //.silence =  mr_alsa_audio_pcm_playback_silence,
 |  | ||||||
|  #endif |  #endif | ||||||
|      .page =     snd_pcm_lib_get_vmalloc_page, |      .page =     snd_pcm_lib_get_vmalloc_page, | ||||||
| -    .ack =      mr_alsa_audio_pcm_ack,
 | -    .ack =      mr_alsa_audio_pcm_ack,
 | ||||||
| +    //.ack =      mr_alsa_audio_pcm_ack,
 |  | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
|  ///////////////////////////////////////////////////////////////////////////////////// |  ///////////////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -2368,7 +2196,7 @@ static struct snd_pcm_ops mr_alsa_audio_pcm_capture_ops = {
 | @@ -2361,14 +2050,12 @@ static struct snd_pcm_ops mr_alsa_audio_pcm_capture_ops = {
 | ||||||
|  |      .pointer =  mr_alsa_audio_pcm_pointer, | ||||||
|  |  #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) | ||||||
|  |      .copy_user = mr_alsa_audio_pcm_capture_copy_user, | ||||||
|  | -    //.copy_kernel = mr_alsa_audio_pcm_capture_copy,
 | ||||||
|  |      .fill_silence = NULL, | ||||||
|  |  #else | ||||||
|  |      .copy =     mr_alsa_audio_pcm_capture_copy, | ||||||
|      .silence =  NULL, //mr_alsa_audio_pcm_silence, |      .silence =  NULL, //mr_alsa_audio_pcm_silence, | ||||||
|  #endif |  #endif | ||||||
|      .page =     snd_pcm_lib_get_vmalloc_page, |      .page =     snd_pcm_lib_get_vmalloc_page, | ||||||
| -    .ack =      mr_alsa_audio_pcm_ack,
 | -    .ack =      mr_alsa_audio_pcm_ack,
 | ||||||
| +    //.ack =      mr_alsa_audio_pcm_ack,
 |  | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
|   |   | ||||||
| 
 | @@ -2786,4 +2473,4 @@ void mr_alsa_audio_card_exit(void)
 | ||||||
|  |      g_ravenna_peer = NULL; | ||||||
|  |      g_mr_alsa_audio_ops = NULL; | ||||||
|  |      printk(KERN_INFO "leaving mr_alsa_audio_card_exit..\n"); | ||||||
|  | -}
 | ||||||
|  | \ No newline at end of file | ||||||
|  | +}
 | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								3rdparty/patches/ravenna-alsa-lkm-fixes.patch
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								3rdparty/patches/ravenna-alsa-lkm-fixes.patch
									
									
									
									
										vendored
									
									
								
							| @ -80,26 +80,3 @@ index ac65bbb..a65994f 100644 | |||||||
|  #else |  #else | ||||||
|      #include <string.h> |      #include <string.h> | ||||||
|  #endif |  #endif | ||||||
| diff --git a/driver/audio_driver.c b/driver/audio_driver.c
 |  | ||||||
| index 3d9debd..0ff2dfc 100644
 |  | ||||||
| --- a/driver/audio_driver.c
 |  | ||||||
| +++ b/driver/audio_driver.c
 |  | ||||||
| @@ -1292,8 +1292,7 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 |  | ||||||
|      struct mr_alsa_audio_chip *chip = snd_pcm_substream_chip(substream); |  | ||||||
|      struct snd_pcm_runtime *runtime = substream->runtime; |  | ||||||
|      int chn = 0; |  | ||||||
| -    //int interleaved = ((channel == -1 && runtime->channels > 1)? 1 : 0);
 |  | ||||||
| -    int interleaved = runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ? 1 : 0;
 |  | ||||||
| +    int interleaved = ((channel == -1 && runtime->channels > 1)? 1 : 0);
 |  | ||||||
|      unsigned int nb_logical_bits = snd_pcm_format_width(runtime->format); |  | ||||||
|      unsigned int strideIn = snd_pcm_format_physical_width(runtime->format) >> 3; |  | ||||||
|      unsigned int strideOut = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE) >> 3; |  | ||||||
| @@ -1310,7 +1309,7 @@ static int mr_alsa_audio_pcm_playback_copy_internal( struct snd_pcm_substream *s
 |  | ||||||
|          memset(testblock, 0, sizeof(testblock)); |  | ||||||
|      #endif |  | ||||||
|       |  | ||||||
| -    if (channel > 0 && channel >= runtime->channels)
 |  | ||||||
| +    if (!interleaved && channel >= runtime->channels)
 |  | ||||||
|      { |  | ||||||
|          printk(KERN_WARNING "Channel %d copy ignored because it does not fit the available runtime channels (%d)", channel, runtime->channels); |  | ||||||
|         return 0; |  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user