Merge branch 'linus' into cont_syslog
[safe/jmp/linux-2.6] / sound / core / pcm_lib.c
index aa54195..e9d98be 100644 (file)
@@ -148,6 +148,9 @@ static void pcm_debug_name(struct snd_pcm_substream *substream,
 
 #define xrun_debug(substream, mask) \
                        ((substream)->pstr->xrun_debug & (mask))
+#else
+#define xrun_debug(substream, mask)    0
+#endif
 
 #define dump_stack_on_xrun(substream) do {                     \
                if (xrun_debug(substream, XRUN_DEBUG_STACK))    \
@@ -169,6 +172,7 @@ static void xrun(struct snd_pcm_substream *substream)
        }
 }
 
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
 #define hw_ptr_error(substream, fmt, args...)                          \
        do {                                                            \
                if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {          \
@@ -255,8 +259,6 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
 
 #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
 
-#define xrun_debug(substream, mask)    0
-#define xrun(substream)                        do { } while (0)
 #define hw_ptr_error(substream, fmt, args...) do { } while (0)
 #define xrun_log(substream, pos)       do { } while (0)
 #define xrun_log_show(substream)       do { } while (0)
@@ -343,7 +345,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                new_hw_ptr = hw_base + pos;
        }
       __delta:
-       delta = (new_hw_ptr - old_hw_ptr) % runtime->boundary;
+       delta = new_hw_ptr - old_hw_ptr;
+       if (delta < 0)
+               delta += runtime->boundary;
        if (xrun_debug(substream, in_interrupt ?
                        XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
                char name[16];
@@ -437,8 +441,13 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                snd_pcm_playback_silence(substream, new_hw_ptr);
 
        if (in_interrupt) {
-               runtime->hw_ptr_interrupt = new_hw_ptr -
-                               (new_hw_ptr % runtime->period_size);
+               delta = new_hw_ptr - runtime->hw_ptr_interrupt;
+               if (delta < 0)
+                       delta += runtime->boundary;
+               delta -= (snd_pcm_uframes_t)delta % runtime->period_size;
+               runtime->hw_ptr_interrupt += delta;
+               if (runtime->hw_ptr_interrupt >= runtime->boundary)
+                       runtime->hw_ptr_interrupt -= runtime->boundary;
        }
        runtime->hw_ptr_base = hw_base;
        runtime->status->hw_ptr = new_hw_ptr;
@@ -766,10 +775,13 @@ int snd_interval_ratnum(struct snd_interval *i,
                        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) {
@@ -791,6 +803,8 @@ int snd_interval_ratnum(struct snd_interval *i,
                                den -= r;
                }
                diff = num - q * den;
+               if (diff < 0)
+                       diff = -diff;
                if (best_num == 0 ||
                    diff * best_den < best_diff * den) {
                        best_diff = diff;
@@ -805,6 +819,9 @@ int snd_interval_ratnum(struct snd_interval *i,
        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;
@@ -827,6 +844,8 @@ int snd_interval_ratnum(struct snd_interval *i,
                                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;
@@ -846,10 +865,14 @@ int snd_interval_ratnum(struct snd_interval *i,
                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;
 }