Merge remote branch 'alsa/devel' into topic/misc
authorTakashi Iwai <tiwai@suse.de>
Thu, 21 Jan 2010 13:27:14 +0000 (14:27 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 21 Jan 2010 13:27:14 +0000 (14:27 +0100)
1  2 
include/sound/pcm.h
sound/core/pcm_lib.c
sound/core/pcm_native.c

diff --combined include/sound/pcm.h
index 1d4ca2aae50dc8ea71e8ab7f96734f03143cd7d3,3bc9bca771ece4e24714d0481f63360fd52d009f..768e3098656cbbd4abe5697f57d1c30d273ea599
@@@ -311,8 -311,9 +311,9 @@@ struct snd_pcm_runtime 
        struct snd_pcm_mmap_control *control;
  
        /* -- locking / scheduling -- */
-       unsigned int nowake: 1;         /* no wakeup (data-copy in progress) */
-       wait_queue_head_t sleep;
+       unsigned int twake: 1;          /* do transfer (!poll) wakeup */
+       wait_queue_head_t sleep;        /* poll sleep */
+       wait_queue_head_t tsleep;       /* transfer sleep */
        struct fasync_struct *fasync;
  
        /* -- private section -- */
@@@ -913,44 -914,6 +914,44 @@@ int snd_pcm_lib_preallocate_pages_for_a
  int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
  int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
  
 +int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
 +                                    size_t size, gfp_t gfp_flags);
 +int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream);
 +struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
 +                                        unsigned long offset);
 +#if 0 /* for kernel-doc */
 +/**
 + * snd_pcm_lib_alloc_vmalloc_buffer - allocate virtual DMA buffer
 + * @substream: the substream to allocate the buffer to
 + * @size: the requested buffer size, in bytes
 + *
 + * Allocates the PCM substream buffer using vmalloc(), i.e., the memory is
 + * contiguous in kernel virtual space, but not in physical memory.  Use this
 + * if the buffer is accessed by kernel code but not by device DMA.
 + *
 + * Returns 1 if the buffer was changed, 0 if not changed, or a negative error
 + * code.
 + */
 +static int snd_pcm_lib_alloc_vmalloc_buffer
 +                      (struct snd_pcm_substream *substream, size_t size);
 +/**
 + * snd_pcm_lib_alloc_vmalloc_32_buffer - allocate 32-bit-addressable buffer
 + * @substream: the substream to allocate the buffer to
 + * @size: the requested buffer size, in bytes
 + *
 + * This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses
 + * vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory.
 + */
 +static int snd_pcm_lib_alloc_vmalloc_32_buffer
 +                      (struct snd_pcm_substream *substream, size_t size);
 +#endif
 +#define snd_pcm_lib_alloc_vmalloc_buffer(subs, size) \
 +      _snd_pcm_lib_alloc_vmalloc_buffer \
 +                      (subs, size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO)
 +#define snd_pcm_lib_alloc_vmalloc_32_buffer(subs, size) \
 +      _snd_pcm_lib_alloc_vmalloc_buffer \
 +                      (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO)
 +
  #ifdef CONFIG_SND_DMA_SGBUF
  /*
   * SG-buffer handling
diff --combined sound/core/pcm_lib.c
index 720019560794993905d4c8f1d891dfaa327d08d4,e2a817eac2a9a3a7d4087599a8e6c147120a8a3d..272f15d19017f25815ee208bf226d2a76436aef2
@@@ -285,8 -285,8 +285,8 @@@ int snd_pcm_update_state(struct snd_pcm
                        return -EPIPE;
                }
        }
-       if (!runtime->nowake && avail >= runtime->control->avail_min)
-               wake_up(&runtime->sleep);
+       if (avail >= runtime->control->avail_min)
+               wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
        return 0;
  }
  
@@@ -763,13 -763,10 +763,13 @@@ int snd_interval_ratnum(struct snd_inte
                        unsigned int rats_count, struct snd_ratnum *rats,
                        unsigned int *nump, unsigned int *denp)
  {
 -      unsigned int best_num, best_diff, best_den;
 +      unsigned int best_num, best_den;
 +      int best_diff;
        unsigned int k;
        struct snd_interval t;
        int err;
 +      unsigned int result_num, result_den;
 +      int result_diff;
  
        best_num = best_den = best_diff = 0;
        for (k = 0; k < rats_count; ++k) {
                                den -= r;
                }
                diff = num - q * den;
 +              if (diff < 0)
 +                      diff = -diff;
                if (best_num == 0 ||
                    diff * best_den < best_diff * den) {
                        best_diff = diff;
        t.min = div_down(best_num, best_den);
        t.openmin = !!(best_num % best_den);
        
 +      result_num = best_num;
 +      result_diff = best_diff;
 +      result_den = best_den;
        best_num = best_den = best_diff = 0;
        for (k = 0; k < rats_count; ++k) {
                unsigned int num = rats[k].num;
                                den += rats[k].den_step - r;
                }
                diff = q * den - num;
 +              if (diff < 0)
 +                      diff = -diff;
                if (best_num == 0 ||
                    diff * best_den < best_diff * den) {
                        best_diff = diff;
                return err;
  
        if (snd_interval_single(i)) {
 +              if (best_diff * result_den < result_diff * best_den) {
 +                      result_num = best_num;
 +                      result_den = best_den;
 +              }
                if (nump)
 -                      *nump = best_num;
 +                      *nump = result_num;
                if (denp)
 -                      *denp = best_den;
 +                      *denp = result_den;
        }
        return err;
  }
@@@ -1706,7 -1692,7 +1706,7 @@@ static int wait_for_avail_min(struct sn
        long tout;
  
        init_waitqueue_entry(&wait, current);
-       add_wait_queue(&runtime->sleep, &wait);
+       add_wait_queue(&runtime->tsleep, &wait);
        for (;;) {
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
        }
   _endloop:
-       remove_wait_queue(&runtime->sleep, &wait);
+       remove_wait_queue(&runtime->tsleep, &wait);
        *availp = avail;
        return err;
  }
@@@ -1808,7 -1794,7 +1808,7 @@@ static snd_pcm_sframes_t snd_pcm_lib_wr
                goto _end_unlock;
        }
  
-       runtime->nowake = 1;
+       runtime->twake = 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
                if (frames > cont)
                        frames = cont;
                if (snd_BUG_ON(!frames)) {
-                       runtime->nowake = 0;
+                       runtime->twake = 0;
                        snd_pcm_stream_unlock_irq(substream);
                        return -EINVAL;
                }
                }
        }
   _end_unlock:
-       runtime->nowake = 0;
+       runtime->twake = 0;
        if (xfer > 0 && err >= 0)
                snd_pcm_update_state(substream, runtime);
        snd_pcm_stream_unlock_irq(substream);
@@@ -2030,7 -2016,7 +2030,7 @@@ static snd_pcm_sframes_t snd_pcm_lib_re
                goto _end_unlock;
        }
  
-       runtime->nowake = 1;
+       runtime->twake = 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
                if (frames > cont)
                        frames = cont;
                if (snd_BUG_ON(!frames)) {
-                       runtime->nowake = 0;
+                       runtime->twake = 0;
                        snd_pcm_stream_unlock_irq(substream);
                        return -EINVAL;
                }
                xfer += frames;
        }
   _end_unlock:
-       runtime->nowake = 0;
+       runtime->twake = 0;
        if (xfer > 0 && err >= 0)
                snd_pcm_update_state(substream, runtime);
        snd_pcm_stream_unlock_irq(substream);
diff --combined sound/core/pcm_native.c
index a870fe69657890186fb92314fe7769bf743f1e6f,56ec35e8510b1fdf296c260245820ca1c89a1189..43552fd73d2467d25f5a24b847a544d867d60fd6
@@@ -919,6 -919,7 +919,7 @@@ static void snd_pcm_post_stop(struct sn
                runtime->status->state = state;
        }
        wake_up(&runtime->sleep);
+       wake_up(&runtime->tsleep);
  }
  
  static struct action_ops snd_pcm_action_stop = {
@@@ -1004,6 -1005,7 +1005,7 @@@ static void snd_pcm_post_pause(struct s
                                         SNDRV_TIMER_EVENT_MPAUSE,
                                         &runtime->trigger_tstamp);
                wake_up(&runtime->sleep);
+               wake_up(&runtime->tsleep);
        } else {
                runtime->status->state = SNDRV_PCM_STATE_RUNNING;
                if (substream->timer)
@@@ -1061,6 -1063,7 +1063,7 @@@ static void snd_pcm_post_suspend(struc
        runtime->status->suspended_state = runtime->status->state;
        runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
        wake_up(&runtime->sleep);
+       wake_up(&runtime->tsleep);
  }
  
  static struct action_ops snd_pcm_action_suspend = {
@@@ -1918,13 -1921,13 +1921,13 @@@ int snd_pcm_hw_constraints_complete(str
  
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
                                           hw->rate_min, hw->rate_max);
 -       if (err < 0)
 -               return err;
 +      if (err < 0)
 +              return err;
  
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
                                           hw->period_bytes_min, hw->period_bytes_max);
 -       if (err < 0)
 -               return err;
 +      if (err < 0)
 +              return err;
  
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
                                           hw->periods_min, hw->periods_max);