summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core.c23
-rw-r--r--pcm.c81
-rw-r--r--sound/avirt.h10
3 files changed, 87 insertions, 27 deletions
diff --git a/core.c b/core.c
index 41cc555..6698a9e 100644
--- a/core.c
+++ b/core.c
@@ -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;
}
diff --git a/pcm.c b/pcm.c
index babc8b6..73f87c9 100644
--- a/pcm.c
+++ b/pcm.c
@@ -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 {