11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * PCM Interface - misc routines 3c1017a4cSJaroslav Kysela * Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz> 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This library is free software; you can redistribute it and/or modify 71da177e4SLinus Torvalds * it under the terms of the GNU Library General Public License as 81da177e4SLinus Torvalds * published by the Free Software Foundation; either version 2 of 91da177e4SLinus Torvalds * the License, or (at your option) any later version. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 121da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 131da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141da177e4SLinus Torvalds * GNU Library General Public License for more details. 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * You should have received a copy of the GNU Library General Public 171da177e4SLinus Torvalds * License along with this library; if not, write to the Free Software 181da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds */ 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #include <sound/driver.h> 231da177e4SLinus Torvalds #include <linux/time.h> 241da177e4SLinus Torvalds #include <sound/core.h> 251da177e4SLinus Torvalds #include <sound/pcm.h> 261da177e4SLinus Torvalds #define SND_PCM_FORMAT_UNKNOWN (-1) 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds /* NOTE: "signed" prefix must be given below since the default char is 291da177e4SLinus Torvalds * unsigned on some architectures! 301da177e4SLinus Torvalds */ 311da177e4SLinus Torvalds struct pcm_format_data { 321da177e4SLinus Torvalds unsigned char width; /* bit width */ 331da177e4SLinus Torvalds unsigned char phys; /* physical bit width */ 341da177e4SLinus Torvalds signed char le; /* 0 = big-endian, 1 = little-endian, -1 = others */ 351da177e4SLinus Torvalds signed char signd; /* 0 = unsigned, 1 = signed, -1 = others */ 361da177e4SLinus Torvalds unsigned char silence[8]; /* silence data to fill */ 371da177e4SLinus Torvalds }; 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = { 401da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S8] = { 411da177e4SLinus Torvalds .width = 8, .phys = 8, .le = -1, .signd = 1, 421da177e4SLinus Torvalds .silence = {}, 431da177e4SLinus Torvalds }, 441da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U8] = { 451da177e4SLinus Torvalds .width = 8, .phys = 8, .le = -1, .signd = 0, 461da177e4SLinus Torvalds .silence = { 0x80 }, 471da177e4SLinus Torvalds }, 481da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S16_LE] = { 491da177e4SLinus Torvalds .width = 16, .phys = 16, .le = 1, .signd = 1, 501da177e4SLinus Torvalds .silence = {}, 511da177e4SLinus Torvalds }, 521da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S16_BE] = { 531da177e4SLinus Torvalds .width = 16, .phys = 16, .le = 0, .signd = 1, 541da177e4SLinus Torvalds .silence = {}, 551da177e4SLinus Torvalds }, 561da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U16_LE] = { 571da177e4SLinus Torvalds .width = 16, .phys = 16, .le = 1, .signd = 0, 581da177e4SLinus Torvalds .silence = { 0x00, 0x80 }, 591da177e4SLinus Torvalds }, 601da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U16_BE] = { 611da177e4SLinus Torvalds .width = 16, .phys = 16, .le = 0, .signd = 0, 621da177e4SLinus Torvalds .silence = { 0x80, 0x00 }, 631da177e4SLinus Torvalds }, 641da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S24_LE] = { 651da177e4SLinus Torvalds .width = 24, .phys = 32, .le = 1, .signd = 1, 661da177e4SLinus Torvalds .silence = {}, 671da177e4SLinus Torvalds }, 681da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S24_BE] = { 691da177e4SLinus Torvalds .width = 24, .phys = 32, .le = 0, .signd = 1, 701da177e4SLinus Torvalds .silence = {}, 711da177e4SLinus Torvalds }, 721da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U24_LE] = { 731da177e4SLinus Torvalds .width = 24, .phys = 32, .le = 1, .signd = 0, 741da177e4SLinus Torvalds .silence = { 0x00, 0x00, 0x80 }, 751da177e4SLinus Torvalds }, 761da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U24_BE] = { 771da177e4SLinus Torvalds .width = 24, .phys = 32, .le = 0, .signd = 0, 78*67a7be7eSJaroslav Kysela .silence = { 0x00, 0x80, 0x00, 0x00 }, 791da177e4SLinus Torvalds }, 801da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S32_LE] = { 811da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 1, .signd = 1, 821da177e4SLinus Torvalds .silence = {}, 831da177e4SLinus Torvalds }, 841da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S32_BE] = { 851da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 0, .signd = 1, 861da177e4SLinus Torvalds .silence = {}, 871da177e4SLinus Torvalds }, 881da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U32_LE] = { 891da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 1, .signd = 0, 901da177e4SLinus Torvalds .silence = { 0x00, 0x00, 0x00, 0x80 }, 911da177e4SLinus Torvalds }, 921da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U32_BE] = { 931da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 0, .signd = 0, 941da177e4SLinus Torvalds .silence = { 0x80, 0x00, 0x00, 0x00 }, 951da177e4SLinus Torvalds }, 961da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_FLOAT_LE] = { 971da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 1, .signd = -1, 981da177e4SLinus Torvalds .silence = {}, 991da177e4SLinus Torvalds }, 1001da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_FLOAT_BE] = { 1011da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 0, .signd = -1, 1021da177e4SLinus Torvalds .silence = {}, 1031da177e4SLinus Torvalds }, 1041da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_FLOAT64_LE] = { 1051da177e4SLinus Torvalds .width = 64, .phys = 64, .le = 1, .signd = -1, 1061da177e4SLinus Torvalds .silence = {}, 1071da177e4SLinus Torvalds }, 1081da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_FLOAT64_BE] = { 1091da177e4SLinus Torvalds .width = 64, .phys = 64, .le = 0, .signd = -1, 1101da177e4SLinus Torvalds .silence = {}, 1111da177e4SLinus Torvalds }, 1121da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = { 1131da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 1, .signd = -1, 1141da177e4SLinus Torvalds .silence = {}, 1151da177e4SLinus Torvalds }, 1161da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = { 1171da177e4SLinus Torvalds .width = 32, .phys = 32, .le = 0, .signd = -1, 1181da177e4SLinus Torvalds .silence = {}, 1191da177e4SLinus Torvalds }, 1201da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_MU_LAW] = { 1211da177e4SLinus Torvalds .width = 8, .phys = 8, .le = -1, .signd = -1, 1221da177e4SLinus Torvalds .silence = { 0x7f }, 1231da177e4SLinus Torvalds }, 1241da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_A_LAW] = { 1251da177e4SLinus Torvalds .width = 8, .phys = 8, .le = -1, .signd = -1, 1261da177e4SLinus Torvalds .silence = { 0x55 }, 1271da177e4SLinus Torvalds }, 1281da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_IMA_ADPCM] = { 1291da177e4SLinus Torvalds .width = 4, .phys = 4, .le = -1, .signd = -1, 1301da177e4SLinus Torvalds .silence = {}, 1311da177e4SLinus Torvalds }, 1321da177e4SLinus Torvalds /* FIXME: the following three formats are not defined properly yet */ 1331da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_MPEG] = { 1341da177e4SLinus Torvalds .le = -1, .signd = -1, 1351da177e4SLinus Torvalds }, 1361da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_GSM] = { 1371da177e4SLinus Torvalds .le = -1, .signd = -1, 1381da177e4SLinus Torvalds }, 1391da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_SPECIAL] = { 1401da177e4SLinus Torvalds .le = -1, .signd = -1, 1411da177e4SLinus Torvalds }, 1421da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S24_3LE] = { 1431da177e4SLinus Torvalds .width = 24, .phys = 24, .le = 1, .signd = 1, 1441da177e4SLinus Torvalds .silence = {}, 1451da177e4SLinus Torvalds }, 1461da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S24_3BE] = { 1471da177e4SLinus Torvalds .width = 24, .phys = 24, .le = 0, .signd = 1, 1481da177e4SLinus Torvalds .silence = {}, 1491da177e4SLinus Torvalds }, 1501da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U24_3LE] = { 1511da177e4SLinus Torvalds .width = 24, .phys = 24, .le = 1, .signd = 0, 1521da177e4SLinus Torvalds .silence = { 0x00, 0x00, 0x80 }, 1531da177e4SLinus Torvalds }, 1541da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U24_3BE] = { 1551da177e4SLinus Torvalds .width = 24, .phys = 24, .le = 0, .signd = 0, 1561da177e4SLinus Torvalds .silence = { 0x80, 0x00, 0x00 }, 1571da177e4SLinus Torvalds }, 1581da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S20_3LE] = { 1591da177e4SLinus Torvalds .width = 20, .phys = 24, .le = 1, .signd = 1, 1601da177e4SLinus Torvalds .silence = {}, 1611da177e4SLinus Torvalds }, 1621da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S20_3BE] = { 1631da177e4SLinus Torvalds .width = 20, .phys = 24, .le = 0, .signd = 1, 1641da177e4SLinus Torvalds .silence = {}, 1651da177e4SLinus Torvalds }, 1661da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U20_3LE] = { 1671da177e4SLinus Torvalds .width = 20, .phys = 24, .le = 1, .signd = 0, 1681da177e4SLinus Torvalds .silence = { 0x00, 0x00, 0x08 }, 1691da177e4SLinus Torvalds }, 1701da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U20_3BE] = { 1711da177e4SLinus Torvalds .width = 20, .phys = 24, .le = 0, .signd = 0, 1721da177e4SLinus Torvalds .silence = { 0x08, 0x00, 0x00 }, 1731da177e4SLinus Torvalds }, 1741da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S18_3LE] = { 1751da177e4SLinus Torvalds .width = 18, .phys = 24, .le = 1, .signd = 1, 1761da177e4SLinus Torvalds .silence = {}, 1771da177e4SLinus Torvalds }, 1781da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_S18_3BE] = { 1791da177e4SLinus Torvalds .width = 18, .phys = 24, .le = 0, .signd = 1, 1801da177e4SLinus Torvalds .silence = {}, 1811da177e4SLinus Torvalds }, 1821da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U18_3LE] = { 1831da177e4SLinus Torvalds .width = 18, .phys = 24, .le = 1, .signd = 0, 1841da177e4SLinus Torvalds .silence = { 0x00, 0x00, 0x02 }, 1851da177e4SLinus Torvalds }, 1861da177e4SLinus Torvalds [SNDRV_PCM_FORMAT_U18_3BE] = { 1871da177e4SLinus Torvalds .width = 18, .phys = 24, .le = 0, .signd = 0, 1881da177e4SLinus Torvalds .silence = { 0x02, 0x00, 0x00 }, 1891da177e4SLinus Torvalds }, 1901da177e4SLinus Torvalds }; 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /** 1941da177e4SLinus Torvalds * snd_pcm_format_signed - Check the PCM format is signed linear 1951da177e4SLinus Torvalds * @format: the format to check 1961da177e4SLinus Torvalds * 1971da177e4SLinus Torvalds * Returns 1 if the given PCM format is signed linear, 0 if unsigned 1981da177e4SLinus Torvalds * linear, and a negative error code for non-linear formats. 1991da177e4SLinus Torvalds */ 2001da177e4SLinus Torvalds int snd_pcm_format_signed(snd_pcm_format_t format) 2011da177e4SLinus Torvalds { 2021da177e4SLinus Torvalds int val; 2031da177e4SLinus Torvalds if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) 2041da177e4SLinus Torvalds return -EINVAL; 2051da177e4SLinus Torvalds if ((val = pcm_formats[format].signd) < 0) 2061da177e4SLinus Torvalds return -EINVAL; 2071da177e4SLinus Torvalds return val; 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds 210e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_signed); 211e88e8ae6STakashi Iwai 2121da177e4SLinus Torvalds /** 2131da177e4SLinus Torvalds * snd_pcm_format_unsigned - Check the PCM format is unsigned linear 2141da177e4SLinus Torvalds * @format: the format to check 2151da177e4SLinus Torvalds * 2161da177e4SLinus Torvalds * Returns 1 if the given PCM format is unsigned linear, 0 if signed 2171da177e4SLinus Torvalds * linear, and a negative error code for non-linear formats. 2181da177e4SLinus Torvalds */ 2191da177e4SLinus Torvalds int snd_pcm_format_unsigned(snd_pcm_format_t format) 2201da177e4SLinus Torvalds { 2211da177e4SLinus Torvalds int val; 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds val = snd_pcm_format_signed(format); 2241da177e4SLinus Torvalds if (val < 0) 2251da177e4SLinus Torvalds return val; 2261da177e4SLinus Torvalds return !val; 2271da177e4SLinus Torvalds } 2281da177e4SLinus Torvalds 229e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_unsigned); 230e88e8ae6STakashi Iwai 2311da177e4SLinus Torvalds /** 2321da177e4SLinus Torvalds * snd_pcm_format_linear - Check the PCM format is linear 2331da177e4SLinus Torvalds * @format: the format to check 2341da177e4SLinus Torvalds * 2351da177e4SLinus Torvalds * Returns 1 if the given PCM format is linear, 0 if not. 2361da177e4SLinus Torvalds */ 2371da177e4SLinus Torvalds int snd_pcm_format_linear(snd_pcm_format_t format) 2381da177e4SLinus Torvalds { 2391da177e4SLinus Torvalds return snd_pcm_format_signed(format) >= 0; 2401da177e4SLinus Torvalds } 2411da177e4SLinus Torvalds 242e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_linear); 243e88e8ae6STakashi Iwai 2441da177e4SLinus Torvalds /** 2451da177e4SLinus Torvalds * snd_pcm_format_little_endian - Check the PCM format is little-endian 2461da177e4SLinus Torvalds * @format: the format to check 2471da177e4SLinus Torvalds * 2481da177e4SLinus Torvalds * Returns 1 if the given PCM format is little-endian, 0 if 2491da177e4SLinus Torvalds * big-endian, or a negative error code if endian not specified. 2501da177e4SLinus Torvalds */ 2511da177e4SLinus Torvalds int snd_pcm_format_little_endian(snd_pcm_format_t format) 2521da177e4SLinus Torvalds { 2531da177e4SLinus Torvalds int val; 2541da177e4SLinus Torvalds if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) 2551da177e4SLinus Torvalds return -EINVAL; 2561da177e4SLinus Torvalds if ((val = pcm_formats[format].le) < 0) 2571da177e4SLinus Torvalds return -EINVAL; 2581da177e4SLinus Torvalds return val; 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds 261e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_little_endian); 262e88e8ae6STakashi Iwai 2631da177e4SLinus Torvalds /** 2641da177e4SLinus Torvalds * snd_pcm_format_big_endian - Check the PCM format is big-endian 2651da177e4SLinus Torvalds * @format: the format to check 2661da177e4SLinus Torvalds * 2671da177e4SLinus Torvalds * Returns 1 if the given PCM format is big-endian, 0 if 2681da177e4SLinus Torvalds * little-endian, or a negative error code if endian not specified. 2691da177e4SLinus Torvalds */ 2701da177e4SLinus Torvalds int snd_pcm_format_big_endian(snd_pcm_format_t format) 2711da177e4SLinus Torvalds { 2721da177e4SLinus Torvalds int val; 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds val = snd_pcm_format_little_endian(format); 2751da177e4SLinus Torvalds if (val < 0) 2761da177e4SLinus Torvalds return val; 2771da177e4SLinus Torvalds return !val; 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 280e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_big_endian); 281e88e8ae6STakashi Iwai 2821da177e4SLinus Torvalds /** 2831da177e4SLinus Torvalds * snd_pcm_format_width - return the bit-width of the format 2841da177e4SLinus Torvalds * @format: the format to check 2851da177e4SLinus Torvalds * 2861da177e4SLinus Torvalds * Returns the bit-width of the format, or a negative error code 2871da177e4SLinus Torvalds * if unknown format. 2881da177e4SLinus Torvalds */ 2891da177e4SLinus Torvalds int snd_pcm_format_width(snd_pcm_format_t format) 2901da177e4SLinus Torvalds { 2911da177e4SLinus Torvalds int val; 2921da177e4SLinus Torvalds if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) 2931da177e4SLinus Torvalds return -EINVAL; 2941da177e4SLinus Torvalds if ((val = pcm_formats[format].width) == 0) 2951da177e4SLinus Torvalds return -EINVAL; 2961da177e4SLinus Torvalds return val; 2971da177e4SLinus Torvalds } 2981da177e4SLinus Torvalds 299e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_width); 300e88e8ae6STakashi Iwai 3011da177e4SLinus Torvalds /** 3021da177e4SLinus Torvalds * snd_pcm_format_physical_width - return the physical bit-width of the format 3031da177e4SLinus Torvalds * @format: the format to check 3041da177e4SLinus Torvalds * 3051da177e4SLinus Torvalds * Returns the physical bit-width of the format, or a negative error code 3061da177e4SLinus Torvalds * if unknown format. 3071da177e4SLinus Torvalds */ 3081da177e4SLinus Torvalds int snd_pcm_format_physical_width(snd_pcm_format_t format) 3091da177e4SLinus Torvalds { 3101da177e4SLinus Torvalds int val; 3111da177e4SLinus Torvalds if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) 3121da177e4SLinus Torvalds return -EINVAL; 3131da177e4SLinus Torvalds if ((val = pcm_formats[format].phys) == 0) 3141da177e4SLinus Torvalds return -EINVAL; 3151da177e4SLinus Torvalds return val; 3161da177e4SLinus Torvalds } 3171da177e4SLinus Torvalds 318e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_physical_width); 319e88e8ae6STakashi Iwai 3201da177e4SLinus Torvalds /** 3211da177e4SLinus Torvalds * snd_pcm_format_size - return the byte size of samples on the given format 3221da177e4SLinus Torvalds * @format: the format to check 3231da177e4SLinus Torvalds * 3241da177e4SLinus Torvalds * Returns the byte size of the given samples for the format, or a 3251da177e4SLinus Torvalds * negative error code if unknown format. 3261da177e4SLinus Torvalds */ 3271da177e4SLinus Torvalds ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) 3281da177e4SLinus Torvalds { 3291da177e4SLinus Torvalds int phys_width = snd_pcm_format_physical_width(format); 3301da177e4SLinus Torvalds if (phys_width < 0) 3311da177e4SLinus Torvalds return -EINVAL; 3321da177e4SLinus Torvalds return samples * phys_width / 8; 3331da177e4SLinus Torvalds } 3341da177e4SLinus Torvalds 335e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_size); 336e88e8ae6STakashi Iwai 3371da177e4SLinus Torvalds /** 3381da177e4SLinus Torvalds * snd_pcm_format_silence_64 - return the silent data in 8 bytes array 3391da177e4SLinus Torvalds * @format: the format to check 3401da177e4SLinus Torvalds * 3411da177e4SLinus Torvalds * Returns the format pattern to fill or NULL if error. 3421da177e4SLinus Torvalds */ 3431da177e4SLinus Torvalds const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) 3441da177e4SLinus Torvalds { 3451da177e4SLinus Torvalds if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) 3461da177e4SLinus Torvalds return NULL; 3471da177e4SLinus Torvalds if (! pcm_formats[format].phys) 3481da177e4SLinus Torvalds return NULL; 3491da177e4SLinus Torvalds return pcm_formats[format].silence; 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 352e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_silence_64); 353e88e8ae6STakashi Iwai 3541da177e4SLinus Torvalds /** 3551da177e4SLinus Torvalds * snd_pcm_format_set_silence - set the silence data on the buffer 3561da177e4SLinus Torvalds * @format: the PCM format 3571da177e4SLinus Torvalds * @data: the buffer pointer 3581da177e4SLinus Torvalds * @samples: the number of samples to set silence 3591da177e4SLinus Torvalds * 3601da177e4SLinus Torvalds * Sets the silence data on the buffer for the given samples. 3611da177e4SLinus Torvalds * 3621da177e4SLinus Torvalds * Returns zero if successful, or a negative error code on failure. 3631da177e4SLinus Torvalds */ 3641da177e4SLinus Torvalds int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples) 3651da177e4SLinus Torvalds { 3661da177e4SLinus Torvalds int width; 3671da177e4SLinus Torvalds unsigned char *dst, *pat; 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) 3701da177e4SLinus Torvalds return -EINVAL; 3711da177e4SLinus Torvalds if (samples == 0) 3721da177e4SLinus Torvalds return 0; 3731da177e4SLinus Torvalds width = pcm_formats[format].phys; /* physical width */ 3741da177e4SLinus Torvalds pat = pcm_formats[format].silence; 3751da177e4SLinus Torvalds if (! width) 3761da177e4SLinus Torvalds return -EINVAL; 3771da177e4SLinus Torvalds /* signed or 1 byte data */ 3781da177e4SLinus Torvalds if (pcm_formats[format].signd == 1 || width <= 8) { 3791da177e4SLinus Torvalds unsigned int bytes = samples * width / 8; 3801da177e4SLinus Torvalds memset(data, *pat, bytes); 3811da177e4SLinus Torvalds return 0; 3821da177e4SLinus Torvalds } 3831da177e4SLinus Torvalds /* non-zero samples, fill using a loop */ 3841da177e4SLinus Torvalds width /= 8; 3851da177e4SLinus Torvalds dst = data; 3861da177e4SLinus Torvalds #if 0 3871da177e4SLinus Torvalds while (samples--) { 3881da177e4SLinus Torvalds memcpy(dst, pat, width); 3891da177e4SLinus Torvalds dst += width; 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds #else 3921da177e4SLinus Torvalds /* a bit optimization for constant width */ 3931da177e4SLinus Torvalds switch (width) { 3941da177e4SLinus Torvalds case 2: 3951da177e4SLinus Torvalds while (samples--) { 3961da177e4SLinus Torvalds memcpy(dst, pat, 2); 3971da177e4SLinus Torvalds dst += 2; 3981da177e4SLinus Torvalds } 3991da177e4SLinus Torvalds break; 4001da177e4SLinus Torvalds case 3: 4011da177e4SLinus Torvalds while (samples--) { 4021da177e4SLinus Torvalds memcpy(dst, pat, 3); 4031da177e4SLinus Torvalds dst += 3; 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds break; 4061da177e4SLinus Torvalds case 4: 4071da177e4SLinus Torvalds while (samples--) { 4081da177e4SLinus Torvalds memcpy(dst, pat, 4); 4091da177e4SLinus Torvalds dst += 4; 4101da177e4SLinus Torvalds } 4111da177e4SLinus Torvalds break; 4121da177e4SLinus Torvalds case 8: 4131da177e4SLinus Torvalds while (samples--) { 4141da177e4SLinus Torvalds memcpy(dst, pat, 8); 4151da177e4SLinus Torvalds dst += 8; 4161da177e4SLinus Torvalds } 4171da177e4SLinus Torvalds break; 4181da177e4SLinus Torvalds } 4191da177e4SLinus Torvalds #endif 4201da177e4SLinus Torvalds return 0; 4211da177e4SLinus Torvalds } 4221da177e4SLinus Torvalds 423e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_format_set_silence); 424e88e8ae6STakashi Iwai 4251da177e4SLinus Torvalds /** 4261da177e4SLinus Torvalds * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields 4271da177e4SLinus Torvalds * @runtime: the runtime instance 4281da177e4SLinus Torvalds * 4291da177e4SLinus Torvalds * Determines the rate_min and rate_max fields from the rates bits of 4301da177e4SLinus Torvalds * the given runtime->hw. 4311da177e4SLinus Torvalds * 4321da177e4SLinus Torvalds * Returns zero if successful. 4331da177e4SLinus Torvalds */ 434877211f5STakashi Iwai int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) 4351da177e4SLinus Torvalds { 4361da177e4SLinus Torvalds int i; 4377653d557SClemens Ladisch for (i = 0; i < (int)snd_pcm_known_rates.count; i++) { 4381da177e4SLinus Torvalds if (runtime->hw.rates & (1 << i)) { 4397653d557SClemens Ladisch runtime->hw.rate_min = snd_pcm_known_rates.list[i]; 4401da177e4SLinus Torvalds break; 4411da177e4SLinus Torvalds } 4421da177e4SLinus Torvalds } 4437653d557SClemens Ladisch for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) { 4441da177e4SLinus Torvalds if (runtime->hw.rates & (1 << i)) { 4457653d557SClemens Ladisch runtime->hw.rate_max = snd_pcm_known_rates.list[i]; 4461da177e4SLinus Torvalds break; 4471da177e4SLinus Torvalds } 4481da177e4SLinus Torvalds } 4491da177e4SLinus Torvalds return 0; 4501da177e4SLinus Torvalds } 451e88e8ae6STakashi Iwai 452e88e8ae6STakashi Iwai EXPORT_SYMBOL(snd_pcm_limit_hw_rates); 453918f3a0eSClemens Ladisch 454918f3a0eSClemens Ladisch /** 455918f3a0eSClemens Ladisch * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit 456918f3a0eSClemens Ladisch * @rate: the sample rate to convert 457918f3a0eSClemens Ladisch * 458918f3a0eSClemens Ladisch * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or 459918f3a0eSClemens Ladisch * SNDRV_PCM_RATE_KNOT for an unknown rate. 460918f3a0eSClemens Ladisch */ 461918f3a0eSClemens Ladisch unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate) 462918f3a0eSClemens Ladisch { 463918f3a0eSClemens Ladisch unsigned int i; 464918f3a0eSClemens Ladisch 465918f3a0eSClemens Ladisch for (i = 0; i < snd_pcm_known_rates.count; i++) 466918f3a0eSClemens Ladisch if (snd_pcm_known_rates.list[i] == rate) 467918f3a0eSClemens Ladisch return 1u << i; 468918f3a0eSClemens Ladisch return SNDRV_PCM_RATE_KNOT; 469918f3a0eSClemens Ladisch } 470918f3a0eSClemens Ladisch EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit); 471