aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_lib.c20
-rw-r--r--sound/core/pcm_memory.c55
-rw-r--r--sound/core/pcm_native.c8
3 files changed, 76 insertions, 7 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 5417f7dce834..720019560794 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -763,10 +763,13 @@ int snd_interval_ratnum(struct snd_interval *i,
763 unsigned int rats_count, struct snd_ratnum *rats, 763 unsigned int rats_count, struct snd_ratnum *rats,
764 unsigned int *nump, unsigned int *denp) 764 unsigned int *nump, unsigned int *denp)
765{ 765{
766 unsigned int best_num, best_diff, best_den; 766 unsigned int best_num, best_den;
767 int best_diff;
767 unsigned int k; 768 unsigned int k;
768 struct snd_interval t; 769 struct snd_interval t;
769 int err; 770 int err;
771 unsigned int result_num, result_den;
772 int result_diff;
770 773
771 best_num = best_den = best_diff = 0; 774 best_num = best_den = best_diff = 0;
772 for (k = 0; k < rats_count; ++k) { 775 for (k = 0; k < rats_count; ++k) {
@@ -788,6 +791,8 @@ int snd_interval_ratnum(struct snd_interval *i,
788 den -= r; 791 den -= r;
789 } 792 }
790 diff = num - q * den; 793 diff = num - q * den;
794 if (diff < 0)
795 diff = -diff;
791 if (best_num == 0 || 796 if (best_num == 0 ||
792 diff * best_den < best_diff * den) { 797 diff * best_den < best_diff * den) {
793 best_diff = diff; 798 best_diff = diff;
@@ -802,6 +807,9 @@ int snd_interval_ratnum(struct snd_interval *i,
802 t.min = div_down(best_num, best_den); 807 t.min = div_down(best_num, best_den);
803 t.openmin = !!(best_num % best_den); 808 t.openmin = !!(best_num % best_den);
804 809
810 result_num = best_num;
811 result_diff = best_diff;
812 result_den = best_den;
805 best_num = best_den = best_diff = 0; 813 best_num = best_den = best_diff = 0;
806 for (k = 0; k < rats_count; ++k) { 814 for (k = 0; k < rats_count; ++k) {
807 unsigned int num = rats[k].num; 815 unsigned int num = rats[k].num;
@@ -824,6 +832,8 @@ int snd_interval_ratnum(struct snd_interval *i,
824 den += rats[k].den_step - r; 832 den += rats[k].den_step - r;
825 } 833 }
826 diff = q * den - num; 834 diff = q * den - num;
835 if (diff < 0)
836 diff = -diff;
827 if (best_num == 0 || 837 if (best_num == 0 ||
828 diff * best_den < best_diff * den) { 838 diff * best_den < best_diff * den) {
829 best_diff = diff; 839 best_diff = diff;
@@ -843,10 +853,14 @@ int snd_interval_ratnum(struct snd_interval *i,
843 return err; 853 return err;
844 854
845 if (snd_interval_single(i)) { 855 if (snd_interval_single(i)) {
856 if (best_diff * result_den < result_diff * best_den) {
857 result_num = best_num;
858 result_den = best_den;
859 }
846 if (nump) 860 if (nump)
847 *nump = best_num; 861 *nump = result_num;
848 if (denp) 862 if (denp)
849 *denp = best_den; 863 *denp = result_den;
850 } 864 }
851 return err; 865 return err;
852} 866}
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index caa7796bc2f5..d6d49d6651f9 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -23,6 +23,7 @@
23#include <linux/time.h> 23#include <linux/time.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
26#include <linux/vmalloc.h>
26#include <sound/core.h> 27#include <sound/core.h>
27#include <sound/pcm.h> 28#include <sound/pcm.h>
28#include <sound/info.h> 29#include <sound/info.h>
@@ -434,3 +435,57 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
434} 435}
435 436
436EXPORT_SYMBOL(snd_pcm_lib_free_pages); 437EXPORT_SYMBOL(snd_pcm_lib_free_pages);
438
439int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
440 size_t size, gfp_t gfp_flags)
441{
442 struct snd_pcm_runtime *runtime;
443
444 if (PCM_RUNTIME_CHECK(substream))
445 return -EINVAL;
446 runtime = substream->runtime;
447 if (runtime->dma_area) {
448 if (runtime->dma_bytes >= size)
449 return 0; /* already large enough */
450 vfree(runtime->dma_area);
451 }
452 runtime->dma_area = __vmalloc(size, gfp_flags, PAGE_KERNEL);
453 if (!runtime->dma_area)
454 return -ENOMEM;
455 runtime->dma_bytes = size;
456 return 1;
457}
458EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
459
460/**
461 * snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
462 * @substream: the substream with a buffer allocated by
463 * snd_pcm_lib_alloc_vmalloc_buffer()
464 */
465int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
466{
467 struct snd_pcm_runtime *runtime;
468
469 if (PCM_RUNTIME_CHECK(substream))
470 return -EINVAL;
471 runtime = substream->runtime;
472 vfree(runtime->dma_area);
473 runtime->dma_area = NULL;
474 return 0;
475}
476EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
477
478/**
479 * snd_pcm_lib_get_vmalloc_page - map vmalloc buffer offset to page struct
480 * @substream: the substream with a buffer allocated by
481 * snd_pcm_lib_alloc_vmalloc_buffer()
482 * @offset: offset in the buffer
483 *
484 * This function is to be used as the page callback in the PCM ops.
485 */
486struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
487 unsigned long offset)
488{
489 return vmalloc_to_page(substream->runtime->dma_area + offset);
490}
491EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 27284f628361..a870fe696578 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1918,13 +1918,13 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
1918 1918
1919 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 1919 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
1920 hw->rate_min, hw->rate_max); 1920 hw->rate_min, hw->rate_max);
1921 if (err < 0) 1921 if (err < 0)
1922 return err; 1922 return err;
1923 1923
1924 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 1924 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
1925 hw->period_bytes_min, hw->period_bytes_max); 1925 hw->period_bytes_min, hw->period_bytes_max);
1926 if (err < 0) 1926 if (err < 0)
1927 return err; 1927 return err;
1928 1928
1929 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS, 1929 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
1930 hw->periods_min, hw->periods_max); 1930 hw->periods_min, hw->periods_max);