diff --git a/driver/audio_driver.c b/driver/audio_driver.c --- a/driver/audio_driver.c +++ b/driver/audio_driver.c @@ -99,24 +99,14 @@ static struct alsa_ops *g_mr_alsa_audio_ops; -static int mr_alsa_audio_pcm_capture_copy( struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count); 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); -static int mr_alsa_audio_pcm_playback_copy( struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - void __user *src, snd_pcm_uframes_t count); 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, - bool from_user_space); + snd_pcm_uframes_t count); /// "chip" : the main private structure struct mr_alsa_audio_chip @@ -611,6 +601,7 @@ chip->mr_alsa_audio_ops->get_interrupts_frame_size(chip->ravenna_peer, &ptp_frame_size); if(direction == 1 && chip->capture_substream != NULL) { + unsigned long bytes_to_frame_factor; struct snd_pcm_runtime *runtime = chip->capture_substream->runtime; ring_buffer_size = chip->current_dsd ? MR_ALSA_RINGBUFFER_NB_FRAMES : runtime->period_size * runtime->periods; if (ring_buffer_size > MR_ALSA_RINGBUFFER_NB_FRAMES) @@ -620,22 +611,15 @@ } /// 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 * chip->current_alsa_capture_stride; - - //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, runtime->channels/*channel*/, - chip->capture_buffer_pos, chip->dma_capture_buffer + chip->dma_capture_offset/**src*/, ptp_frame_size, false); + bytes_to_frame_factor = runtime->channels * chip->current_alsa_capture_stride; - chip->dma_capture_offset += ptp_frame_size * bytes_to_frame_factor; - if (chip->dma_capture_offset >= chip->pcm_capture_buffer_size) - { - chip->dma_capture_offset -= chip->pcm_capture_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, runtime->channels/*channel*/, + chip->capture_buffer_pos, chip->dma_capture_buffer + chip->dma_capture_offset/**src*/, ptp_frame_size); + + chip->dma_capture_offset += ptp_frame_size * bytes_to_frame_factor; + if (chip->dma_capture_offset >= chip->pcm_capture_buffer_size) + chip->dma_capture_offset -= chip->pcm_capture_buffer_size; chip->capture_buffer_pos += ptp_frame_size; if(chip->capture_buffer_pos >= ring_buffer_size) @@ -654,6 +638,7 @@ } else if(direction == 0 && chip->playback_substream != NULL) { + unsigned long bytes_to_frame_factor; struct snd_pcm_runtime *runtime = chip->playback_substream->runtime; ring_buffer_size = chip->current_dsd ? MR_ALSA_RINGBUFFER_NB_FRAMES : runtime->period_size * runtime->periods; if (ring_buffer_size > MR_ALSA_RINGBUFFER_NB_FRAMES) @@ -662,23 +647,14 @@ return -2; } - /// 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 * 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); - mr_alsa_audio_pcm_playback_copy_internal(chip->playback_substream, runtime->channels/*channel*/, - chip->playback_buffer_pos/*pos*/, chip->dma_playback_buffer + chip->dma_playback_offset/*src*/, ptp_frame_size/*count*/, false); - - chip->dma_playback_offset += ptp_frame_size * bytes_to_frame_factor; - if (chip->dma_playback_offset >= chip->pcm_playback_buffer_size) - { - chip->dma_playback_offset -= chip->pcm_playback_buffer_size; - } - } + 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); + mr_alsa_audio_pcm_playback_copy_internal(chip->playback_substream, runtime->channels/*channel*/, + chip->playback_buffer_pos/*pos*/, chip->dma_playback_buffer + chip->dma_playback_offset/*src*/, ptp_frame_size/*count*/); + + chip->dma_playback_offset += ptp_frame_size * bytes_to_frame_factor; + if (chip->dma_playback_offset >= chip->pcm_playback_buffer_size) + chip->dma_playback_offset -= chip->pcm_playback_buffer_size; chip->playback_buffer_pos += ptp_frame_size; if (chip->playback_buffer_pos >= ring_buffer_size) @@ -988,18 +964,9 @@ if(alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) { /// DMA case - if (alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED || - alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED || - alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) - { - struct snd_pcm_runtime *runtime = alsa_sub->runtime; - unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_playback_stride; - offset = chip->dma_playback_offset / bytes_to_frame_factor; - } - else - { - offset = chip->playback_buffer_pos; - } + struct snd_pcm_runtime *runtime = alsa_sub->runtime; + unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_playback_stride; + offset = chip->dma_playback_offset / bytes_to_frame_factor; /// 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 @@ -1022,19 +989,9 @@ } else if(alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) { - /// DMA case - if (alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED || - alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED || - alsa_sub->runtime->access == SNDRV_PCM_ACCESS_MMAP_COMPLEX) - { - struct snd_pcm_runtime *runtime = alsa_sub->runtime; - unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_capture_stride; - offset = chip->dma_capture_offset / bytes_to_frame_factor; - } - else - { - chip->mr_alsa_audio_ops->get_input_jitter_buffer_offset(chip->ravenna_peer, &offset); - } + struct snd_pcm_runtime *runtime = alsa_sub->runtime; + unsigned long bytes_to_frame_factor = runtime->channels * chip->current_alsa_capture_stride; + offset = chip->dma_capture_offset / bytes_to_frame_factor; /// 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 @@ -1166,36 +1123,10 @@ }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) -static int mr_alsa_audio_pcm_capture_copy_user( struct snd_pcm_substream *substream, - int channel, unsigned long pos, - 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 * 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 - -static int mr_alsa_audio_pcm_capture_copy( struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct mr_alsa_audio_chip *chip = snd_pcm_substream_chip(substream); - uint32_t ravenna_buffer_pos = pos * chip->nb_capture_interrupts_per_period; - - return mr_alsa_audio_pcm_capture_copy_internal(substream, channel, ravenna_buffer_pos, src, count, true); -} - 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) { struct mr_alsa_audio_chip *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -1204,43 +1135,22 @@ unsigned int strideIn = chip->current_alsa_capture_stride; uint32_t ravenna_buffer_pos = pos; - // todo DSD capture - //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); - - - /// 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 - /// so respective ring buffers might have different scale and size - //uint32_t alsa_ring_buffer_nb_frames = MR_ALSA_RINGBUFFER_NB_FRAMES / chip->nb_capture_interrupts_per_period; - - //printk("entering mr_alsa_audio_pcm_capture_copy (channel=%d, count=%lu) (substream name=%s #%d) ...\n", channel, count, substream->name, substream->number); - //printk("Bitwidth = %u, strideIn = %u\n", nb_logical_bits, strideIn); - - //if(snd_BUG_ON(ravenna_buffer_pos >= MR_ALSA_RINGBUFFER_NB_FRAMES)) - // ravenna_buffer_pos -= MR_ALSA_RINGBUFFER_NB_FRAMES; - - - //printk("capture_copy: rate = %u, dsdmode = %u, #IRQ per period = %u, count = %lu, pos = %lu, ravenna_buffer_pos = %u\n", (dsdrate > 0? dsdrate : runtime->rate), dsdmode, chip->nb_capture_interrupts_per_period, count, pos, ravenna_buffer_pos); - //printk("capture_copy: rate = %u, #IRQ per period = %u, count = %zu, pos = %u, ravenna_buffer_pos = %u, channels = %u\n", runtime->rate, chip->nb_capture_interrupts_per_period, count, pos, ravenna_buffer_pos, runtime->channels); - - if(interleaved) { switch(nb_logical_bits) { case 16: - MTConvertMappedInt32ToInt16LEInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, to_user_space); + MTConvertMappedInt32ToInt16LEInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, false); break; case 24: { switch(strideIn) { case 3: - MTConvertMappedInt32ToInt24LEInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, to_user_space); + MTConvertMappedInt32ToInt24LEInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, false); break; case 4: - MTConvertMappedInt32ToInt24LE4ByteInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, to_user_space); + MTConvertMappedInt32ToInt24LE4ByteInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, false); break; default: { @@ -1251,7 +1161,7 @@ break; } case 32: - MTConvertMappedInt32ToInt32LEInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, to_user_space); + MTConvertMappedInt32ToInt32LEInterleave(chip->capture_buffer_channels_map, ravenna_buffer_pos, src, runtime->channels, count, false); break; } } @@ -1263,47 +1173,11 @@ 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() -/// The incoming data (src) is user land memory pointer, so copy_from_user() must be used for memory copy -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) -static int mr_alsa_audio_pcm_playback_copy_user( struct snd_pcm_substream *substream, - int channel, unsigned long pos, - void __user *src, - unsigned long count) -{ - struct mr_alsa_audio_chip* chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - 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 - -/// 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() -/// The incoming data (src) is user land memory pointer, so copy_from_user() must be used for memory copy -static int mr_alsa_audio_pcm_playback_copy( struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct mr_alsa_audio_chip *chip = snd_pcm_substream_chip(substream); - /// 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 - /// so respective ring buffers might have different scale and size - uint32_t ravenna_buffer_pos = pos * chip->nb_playback_interrupts_per_period; - - 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, - bool from_user_space) + snd_pcm_uframes_t count) { struct mr_alsa_audio_chip *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -1316,8 +1190,6 @@ uint32_t dsdmode = (dsdrate > 0? mr_alsa_audio_get_dsd_mode(dsdrate) : 0); uint32_t ravenna_buffer_pos = pos; - //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(interleaved) { /// de-interleaving @@ -1325,145 +1197,70 @@ 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) + 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 * ring_buffer_size + currentOutPos; + // + ///Conversion to Signed integer 32 bit LE + for (frmCnt = 0; frmCnt < count; ++frmCnt) { - uint32_t currentOutPos = ravenna_buffer_pos * strideOut; - snd_pcm_uframes_t frmCnt = 0; - 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) + /// assumes Little Endian + if (dsdmode == 0) { - /// assumes Little Endian - int32_t val = 0; - if (dsdmode == 0) - { - switch (nb_logical_bits) - { - 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; - } - else - { - /// 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) - { - switch (dsdmode) - { - 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 >= ring_buffer_size) + switch (nb_logical_bits) { - currentOutPos = 0; - out = chip->playback_buffer + chn * ring_buffer_size; - } - else - { - currentOutPos += stepOut; - out += stepOut; + case 16: + out[3] = in[1]; + out[2] = in[0]; + out[1] = 0; + out[0] = 0; + break; + case 24: + out[3] = in[2]; + out[2] = in[1]; + out[1] = in[0]; + out[0] = 0; + break; + case 32: + *(int32_t*)out = *(int32_t*)in; + break; } } - } - } - else - { - 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 * ring_buffer_size + currentOutPos; - // - ///Conversion to Signed integer 32 bit LE - for (frmCnt = 0; frmCnt < count; ++frmCnt) + else { - /// assumes Little Endian - int32_t val = 0; - if (dsdmode == 0) + /// 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) { - switch (nb_logical_bits) + switch (dsdmode) { - case 16: - - ((unsigned char*)&val)[3] = in[1]; - ((unsigned char*)&val)[2] = in[0]; + case 1: ///DSD64 + ((int32_t*)out)[out_cnt] = *(int32_t*)(in + out_cnt) & 0xFF; break; - case 24: - ((unsigned char*)&val)[3] = in[2]; - ((unsigned char*)&val)[2] = in[1]; - ((unsigned char*)&val)[1] = in[0]; + case 2: ///DSD128 + ((int32_t*)out)[out_cnt] = (((int32_t)(in[2 * out_cnt + 1]) << 8) | ((int32_t)(in[2 * out_cnt]))) & 0xFFFF; break; - case 32: - val = *(int32_t*)(in); + case 4: ///DSD256 + ((int32_t*)out)[out_cnt] = *(int32_t*)(in); break; } - *((int32_t*)out) = val; - } - else - { - /// 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) - { - switch (dsdmode) - { - 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 >= ring_buffer_size) - { - currentOutPos = 0; - out = chip->playback_buffer + chn * ring_buffer_size; - } - else - { - currentOutPos += stepOut; - out += stepOut; - } + in += stepIn; + if (currentOutPos + stepOut >= ring_buffer_size) + { + currentOutPos = 0; + out = chip->playback_buffer + chn * ring_buffer_size; + } + else + { + currentOutPos += stepOut; + out += stepOut; } } } @@ -2042,11 +1839,6 @@ .prepare = mr_alsa_audio_pcm_prepare, .trigger = mr_alsa_audio_pcm_trigger, .pointer = mr_alsa_audio_pcm_pointer, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) - .copy_user = mr_alsa_audio_pcm_playback_copy_user, -#else - .copy = mr_alsa_audio_pcm_playback_copy, -#endif .page = snd_pcm_lib_get_vmalloc_page, }; @@ -2060,13 +1852,6 @@ .prepare = mr_alsa_audio_pcm_prepare, .trigger = mr_alsa_audio_pcm_trigger, .pointer = mr_alsa_audio_pcm_pointer, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) - .copy_user = mr_alsa_audio_pcm_capture_copy_user, - .fill_silence = NULL, -#else - .copy = mr_alsa_audio_pcm_capture_copy, - .silence = NULL, //mr_alsa_audio_pcm_silence, -#endif .page = snd_pcm_lib_get_vmalloc_page, };