diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/pcm_lib.c | 20 | ||||
-rw-r--r-- | sound/core/pcm_memory.c | 55 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 8 |
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 | ||
436 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); | 437 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); |
438 | |||
439 | int _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 | } | ||
458 | EXPORT_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 | */ | ||
465 | int 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 | } | ||
476 | EXPORT_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 | */ | ||
486 | struct 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 | } | ||
491 | EXPORT_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); |