diff options
-rw-r--r-- | core.c | 23 | ||||
-rw-r--r-- | pcm.c | 81 | ||||
-rw-r--r-- | sound/avirt.h | 10 |
3 files changed, 87 insertions, 27 deletions
@@ -198,8 +198,26 @@ static void destroy_snd_avirt_audiopath_obj(struct snd_avirt_audiopath_obj *p) kobject_put(&p->kobj); } +/** + * pcm_private_data_free - callback function to free private data allocated to pcm + * @pcm: the PCM with private data + */ +void pcm_private_data_free(struct snd_pcm *pcm) +{ + struct snd_avirt_private_data *avirt_private_data; + D_PRINTK("Issuing free to private data struct"); + if(pcm->private_data){ + avirt_private_data = pcm->private_data; + if(avirt_private_data->ap_userdata) + avirt_private_data->private_free(pcm); + } + + kfree(pcm->private_data); +} + static struct snd_pcm *pcm_create(struct snd_avirt_stream *stream) { + struct snd_avirt_private_data *avirt_private_data; bool playback = false, capture = false; struct snd_pcm *pcm; int err; @@ -230,6 +248,11 @@ static struct snd_pcm *pcm_create(struct snd_avirt_stream *stream) pcm->info_flags = 0; strcpy(pcm->name, stream->name); + avirt_private_data = kzalloc(sizeof(*avirt_private_data), GFP_KERNEL); + pcm->private_data = avirt_private_data; + // Set the private free function for the private user data + pcm->private_free = pcm_private_data_free; + return pcm; } @@ -20,6 +20,9 @@ (ap)->pcm_ops->callback((substream), ##__VA_ARGS__) : \ 0) +#define PRIVATE_DATA(substream) \ + ((struct snd_avirt_private_data *) substream->private_data) + /** * snd_avirt_pcm_period_elapsed - PCM buffer complete callback * @substreamid: pointer to ALSA PCM substream @@ -48,6 +51,7 @@ EXPORT_SYMBOL_GPL(snd_avirt_pcm_period_elapsed); */ static int pcm_open(struct snd_pcm_substream *substream) { + struct snd_avirt_private_data *avirt_private_data; struct snd_avirt_audiopath *audiopath; struct snd_avirt_stream *stream; struct snd_pcm_hardware *hw; @@ -56,7 +60,8 @@ static int pcm_open(struct snd_pcm_substream *substream) stream = snd_avirt_stream_find_by_device(substream->pcm->device); audiopath = snd_avirt_audiopath_get(stream->map); CHK_NULL_V(audiopath, "Cannot find Audio Path uid: '%s'!", stream->map); - substream->private_data = audiopath; + avirt_private_data = substream->private_data; + avirt_private_data->audiopath = audiopath; // Copy the hw params from the audiopath to the pcm hw = &substream->runtime->hw; @@ -87,8 +92,8 @@ static int pcm_close(struct snd_pcm_substream *substream) { // Do additional Audio Path 'close' callback return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), close, - substream); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + close, substream); } /** @@ -120,7 +125,8 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - audiopath = ((struct snd_avirt_audiopath *)substream->private_data); + audiopath = + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath; bufsz = params_buffer_bytes(hw_params) * audiopath->hw->periods_max; retval = snd_pcm_lib_alloc_vmalloc_buffer(substream, bufsz); @@ -145,8 +151,8 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) // Do additional Audio Path 'hw_free' callback err = DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), - hw_free, substream); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + hw_free, substream); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -163,10 +169,11 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) */ static int pcm_prepare(struct snd_pcm_substream *substream) { + // Do additional Audio Path 'prepare' callback return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), - prepare, substream); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + prepare, substream); } /** @@ -181,7 +188,8 @@ static int pcm_prepare(struct snd_pcm_substream *substream) */ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - switch (cmd) { + + switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_STOP: @@ -194,8 +202,8 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) // Do additional Audio Path 'trigger' callback return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), - trigger, substream, cmd); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + trigger, substream, cmd); } /** @@ -212,8 +220,8 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) { // Do additional Audio Path 'pointer' callback return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), - pointer, substream); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + pointer, substream); } /** @@ -228,14 +236,14 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) * * Returns 0 on success or error code otherwise */ -static int pcm_get_time_info( - struct snd_pcm_substream *substream, struct timespec *system_ts, - struct timespec *audio_ts, - struct snd_pcm_audio_tstamp_config *audio_tstamp_config, - struct snd_pcm_audio_tstamp_report *audio_tstamp_report) +static int +pcm_get_time_info(struct snd_pcm_substream *substream, + struct timespec *system_ts, struct timespec *audio_ts, + struct snd_pcm_audio_tstamp_config *audio_tstamp_config, + struct snd_pcm_audio_tstamp_report *audio_tstamp_report) { return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, get_time_info, substream, system_ts, audio_ts, audio_tstamp_config, audio_tstamp_report); } @@ -257,6 +265,7 @@ static int pcm_copy_user(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) { + // struct snd_pcm_runtime *runtime; // int offset; @@ -265,8 +274,8 @@ static int pcm_copy_user(struct snd_pcm_substream *substream, int channel, // Do additional Audio Path 'copy_user' callback return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), - copy_user, substream, channel, pos, src, count); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + copy_user, substream, channel, pos, src, count); } /** @@ -286,8 +295,8 @@ static int pcm_copy_kernel(struct snd_pcm_substream *substream, int channel, unsigned long pos, void *buf, unsigned long count) { return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), - copy_kernel, substream, channel, pos, buf, count); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + copy_kernel, substream, channel, pos, buf, count); } /** @@ -302,16 +311,33 @@ static int pcm_copy_kernel(struct snd_pcm_substream *substream, int channel, static int pcm_ack(struct snd_pcm_substream *substream) { return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), ack, - substream); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + ack, substream); } static int pcm_silence(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { return DO_AUDIOPATH_CB( - ((struct snd_avirt_audiopath *)substream->private_data), - fill_silence, substream, channel, pos, count); + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + fill_silence, substream, channel, pos, count); +} + +/** + * pcm_mmap - Implements 'mmap' callback for PCM middle layer + * @substream: pointer to ALSA PCM substream + * + * This is where we need to ack + * + * Returns 0 on success or error code otherwise. + * + */ +static int pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + return DO_AUDIOPATH_CB( + (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath, + mmap, substream, vma); } struct snd_pcm_ops pcm_ops = { @@ -329,4 +355,5 @@ struct snd_pcm_ops pcm_ops = { .copy_kernel = pcm_copy_kernel, .page = snd_pcm_lib_get_vmalloc_page, .ack = pcm_ack, + .mmap = pcm_mmap, }; diff --git a/sound/avirt.h b/sound/avirt.h index 55db1eb..52d2404 100644 --- a/sound/avirt.h +++ b/sound/avirt.h @@ -64,6 +64,16 @@ struct snd_avirt_stream { }; /** + * Private Data Expansion + */ +struct snd_avirt_private_data { + void *audiopath; + void *ap_userdata; + + void (*private_free)(struct snd_pcm *pcm); +}; + +/** * Audio stream group */ struct snd_avirt_stream_array { |