ALSA: firewire: Convert to the common vmalloc memalloc
[linux-2.6-block.git] / sound / firewire / oxfw / oxfw-pcm.c
index 7c6d1c277d4d9e52a107c8079ff9f5a3254b4ac9..9124603edabe58690d90562f0aa00d9413909d84 100644 (file)
@@ -170,30 +170,56 @@ end:
 static int pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_oxfw *oxfw = substream->private_data;
+       struct amdtp_domain *d = &oxfw->domain;
        int err;
 
        err = snd_oxfw_stream_lock_try(oxfw);
        if (err < 0)
-               goto end;
+               return err;
 
        err = init_hw_params(oxfw, substream);
        if (err < 0)
                goto err_locked;
 
-       /*
-        * When any PCM streams are already running, the available sampling
-        * rate is limited at current value.
-        */
-       if (amdtp_stream_pcm_running(&oxfw->tx_stream) ||
-           amdtp_stream_pcm_running(&oxfw->rx_stream)) {
+       mutex_lock(&oxfw->mutex);
+
+       // When source of clock is not internal or any stream is reserved for
+       // transmission of PCM frames, the available sampling rate is limited
+       // at current one.
+       if (oxfw->substreams_count > 0 && d->events_per_period > 0) {
+               unsigned int frames_per_period = d->events_per_period;
+               unsigned int frames_per_buffer = d->events_per_buffer;
+
                err = limit_to_current_params(substream);
-               if (err < 0)
-                       goto end;
+               if (err < 0) {
+                       mutex_unlock(&oxfw->mutex);
+                       goto err_locked;
+               }
+
+               if (frames_per_period > 0) {
+                       err = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                       SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                       frames_per_period, frames_per_period);
+                       if (err < 0) {
+                               mutex_unlock(&oxfw->mutex);
+                               goto err_locked;
+                       }
+
+                       err = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                       SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+                                       frames_per_buffer, frames_per_buffer);
+                       if (err < 0) {
+                               mutex_unlock(&oxfw->mutex);
+                               goto err_locked;
+                       }
+               }
        }
 
+       mutex_unlock(&oxfw->mutex);
+
        snd_pcm_set_sync(substream);
-end:
-       return err;
+
+       return 0;
 err_locked:
        snd_oxfw_stream_lock_release(oxfw);
        return err;
@@ -213,18 +239,20 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
        struct snd_oxfw *oxfw = substream->private_data;
        int err;
 
-       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                              params_buffer_bytes(hw_params));
+       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
        if (err < 0)
                return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
                unsigned int channels = params_channels(hw_params);
+               unsigned int frames_per_period = params_period_size(hw_params);
+               unsigned int frames_per_buffer = params_buffer_size(hw_params);
 
                mutex_lock(&oxfw->mutex);
                err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
-                                                    rate, channels);
+                                       rate, channels, frames_per_period,
+                                       frames_per_buffer);
                if (err >= 0)
                        ++oxfw->substreams_count;
                mutex_unlock(&oxfw->mutex);
@@ -238,18 +266,20 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
        struct snd_oxfw *oxfw = substream->private_data;
        int err;
 
-       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                              params_buffer_bytes(hw_params));
+       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
        if (err < 0)
                return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
                unsigned int channels = params_channels(hw_params);
+               unsigned int frames_per_period = params_period_size(hw_params);
+               unsigned int frames_per_buffer = params_buffer_size(hw_params);
 
                mutex_lock(&oxfw->mutex);
                err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream,
-                                                    rate, channels);
+                                       rate, channels, frames_per_period,
+                                       frames_per_buffer);
                if (err >= 0)
                        ++oxfw->substreams_count;
                mutex_unlock(&oxfw->mutex);
@@ -271,7 +301,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&oxfw->mutex);
 
-       return snd_pcm_lib_free_vmalloc_buffer(substream);
+       return snd_pcm_lib_free_pages(substream);
 }
 static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
 {
@@ -286,7 +316,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&oxfw->mutex);
 
-       return snd_pcm_lib_free_vmalloc_buffer(substream);
+       return snd_pcm_lib_free_pages(substream);
 }
 
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
@@ -361,27 +391,27 @@ static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstm)
 {
        struct snd_oxfw *oxfw = sbstm->private_data;
 
-       return amdtp_stream_pcm_pointer(&oxfw->tx_stream);
+       return amdtp_domain_stream_pcm_pointer(&oxfw->domain, &oxfw->tx_stream);
 }
 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm)
 {
        struct snd_oxfw *oxfw = sbstm->private_data;
 
-       return amdtp_stream_pcm_pointer(&oxfw->rx_stream);
+       return amdtp_domain_stream_pcm_pointer(&oxfw->domain, &oxfw->rx_stream);
 }
 
 static int pcm_capture_ack(struct snd_pcm_substream *substream)
 {
        struct snd_oxfw *oxfw = substream->private_data;
 
-       return amdtp_stream_pcm_ack(&oxfw->tx_stream);
+       return amdtp_domain_stream_pcm_ack(&oxfw->domain, &oxfw->tx_stream);
 }
 
 static int pcm_playback_ack(struct snd_pcm_substream *substream)
 {
        struct snd_oxfw *oxfw = substream->private_data;
 
-       return amdtp_stream_pcm_ack(&oxfw->rx_stream);
+       return amdtp_domain_stream_pcm_ack(&oxfw->domain, &oxfw->rx_stream);
 }
 
 int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
@@ -396,7 +426,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
                .trigger   = pcm_capture_trigger,
                .pointer   = pcm_capture_pointer,
                .ack       = pcm_capture_ack,
-               .page      = snd_pcm_lib_get_vmalloc_page,
        };
        static const struct snd_pcm_ops playback_ops = {
                .open      = pcm_open,
@@ -408,7 +437,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
                .trigger   = pcm_playback_trigger,
                .pointer   = pcm_playback_pointer,
                .ack       = pcm_playback_ack,
-               .page      = snd_pcm_lib_get_vmalloc_page,
        };
        struct snd_pcm *pcm;
        unsigned int cap = 0;
@@ -426,6 +454,8 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
        if (cap > 0)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
+                                             NULL, 0, 0);
 
        return 0;
 }