pcm_plugin.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. /*
  2. * PCM Plug-In shared (kernel/library) code
  3. * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
  4. * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
  5. *
  6. *
  7. * This library is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Library General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. */
  22. #if 0
  23. #define PLUGIN_DEBUG
  24. #endif
  25. #include <sound/driver.h>
  26. #ifdef CONFIG_SND_PCM_OSS_PLUGINS
  27. #include <linux/slab.h>
  28. #include <linux/time.h>
  29. #include <linux/vmalloc.h>
  30. #include <sound/core.h>
  31. #include <sound/pcm.h>
  32. #include <sound/pcm_params.h>
  33. #include "pcm_plugin.h"
  34. #define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
  35. #define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
  36. static int snd_pcm_plugin_src_channels_mask(struct snd_pcm_plugin *plugin,
  37. unsigned long *dst_vmask,
  38. unsigned long **src_vmask)
  39. {
  40. unsigned long *vmask = plugin->src_vmask;
  41. bitmap_copy(vmask, dst_vmask, plugin->src_format.channels);
  42. *src_vmask = vmask;
  43. return 0;
  44. }
  45. static int snd_pcm_plugin_dst_channels_mask(struct snd_pcm_plugin *plugin,
  46. unsigned long *src_vmask,
  47. unsigned long **dst_vmask)
  48. {
  49. unsigned long *vmask = plugin->dst_vmask;
  50. bitmap_copy(vmask, src_vmask, plugin->dst_format.channels);
  51. *dst_vmask = vmask;
  52. return 0;
  53. }
  54. /*
  55. * because some cards might have rates "very close", we ignore
  56. * all "resampling" requests within +-5%
  57. */
  58. static int rate_match(unsigned int src_rate, unsigned int dst_rate)
  59. {
  60. unsigned int low = (src_rate * 95) / 100;
  61. unsigned int high = (src_rate * 105) / 100;
  62. return dst_rate >= low && dst_rate <= high;
  63. }
  64. static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
  65. {
  66. struct snd_pcm_plugin_format *format;
  67. ssize_t width;
  68. size_t size;
  69. unsigned int channel;
  70. struct snd_pcm_plugin_channel *c;
  71. if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  72. format = &plugin->src_format;
  73. } else {
  74. format = &plugin->dst_format;
  75. }
  76. if ((width = snd_pcm_format_physical_width(format->format)) < 0)
  77. return width;
  78. size = frames * format->channels * width;
  79. snd_assert((size % 8) == 0, return -ENXIO);
  80. size /= 8;
  81. if (plugin->buf_frames < frames) {
  82. vfree(plugin->buf);
  83. plugin->buf = vmalloc(size);
  84. plugin->buf_frames = frames;
  85. }
  86. if (!plugin->buf) {
  87. plugin->buf_frames = 0;
  88. return -ENOMEM;
  89. }
  90. c = plugin->buf_channels;
  91. if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
  92. for (channel = 0; channel < format->channels; channel++, c++) {
  93. c->frames = frames;
  94. c->enabled = 1;
  95. c->wanted = 0;
  96. c->area.addr = plugin->buf;
  97. c->area.first = channel * width;
  98. c->area.step = format->channels * width;
  99. }
  100. } else if (plugin->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
  101. snd_assert((size % format->channels) == 0,);
  102. size /= format->channels;
  103. for (channel = 0; channel < format->channels; channel++, c++) {
  104. c->frames = frames;
  105. c->enabled = 1;
  106. c->wanted = 0;
  107. c->area.addr = plugin->buf + (channel * size);
  108. c->area.first = 0;
  109. c->area.step = width;
  110. }
  111. } else
  112. return -EINVAL;
  113. return 0;
  114. }
  115. int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
  116. {
  117. int err;
  118. snd_assert(snd_pcm_plug_first(plug) != NULL, return -ENXIO);
  119. if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
  120. struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
  121. while (plugin->next) {
  122. if (plugin->dst_frames)
  123. frames = plugin->dst_frames(plugin, frames);
  124. snd_assert(frames > 0, return -ENXIO);
  125. plugin = plugin->next;
  126. err = snd_pcm_plugin_alloc(plugin, frames);
  127. if (err < 0)
  128. return err;
  129. }
  130. } else {
  131. struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
  132. while (plugin->prev) {
  133. if (plugin->src_frames)
  134. frames = plugin->src_frames(plugin, frames);
  135. snd_assert(frames > 0, return -ENXIO);
  136. plugin = plugin->prev;
  137. err = snd_pcm_plugin_alloc(plugin, frames);
  138. if (err < 0)
  139. return err;
  140. }
  141. }
  142. return 0;
  143. }
  144. snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin,
  145. snd_pcm_uframes_t frames,
  146. struct snd_pcm_plugin_channel **channels)
  147. {
  148. *channels = plugin->buf_channels;
  149. return frames;
  150. }
  151. int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
  152. const char *name,
  153. struct snd_pcm_plugin_format *src_format,
  154. struct snd_pcm_plugin_format *dst_format,
  155. size_t extra,
  156. struct snd_pcm_plugin **ret)
  157. {
  158. struct snd_pcm_plugin *plugin;
  159. unsigned int channels;
  160. snd_assert(plug != NULL, return -ENXIO);
  161. snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
  162. plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL);
  163. if (plugin == NULL)
  164. return -ENOMEM;
  165. plugin->name = name;
  166. plugin->plug = plug;
  167. plugin->stream = snd_pcm_plug_stream(plug);
  168. plugin->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
  169. plugin->src_format = *src_format;
  170. plugin->src_width = snd_pcm_format_physical_width(src_format->format);
  171. snd_assert(plugin->src_width > 0, );
  172. plugin->dst_format = *dst_format;
  173. plugin->dst_width = snd_pcm_format_physical_width(dst_format->format);
  174. snd_assert(plugin->dst_width > 0, );
  175. if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK)
  176. channels = src_format->channels;
  177. else
  178. channels = dst_format->channels;
  179. plugin->buf_channels = kcalloc(channels, sizeof(*plugin->buf_channels), GFP_KERNEL);
  180. if (plugin->buf_channels == NULL) {
  181. snd_pcm_plugin_free(plugin);
  182. return -ENOMEM;
  183. }
  184. plugin->src_vmask = bitmap_alloc(src_format->channels);
  185. if (plugin->src_vmask == NULL) {
  186. snd_pcm_plugin_free(plugin);
  187. return -ENOMEM;
  188. }
  189. plugin->dst_vmask = bitmap_alloc(dst_format->channels);
  190. if (plugin->dst_vmask == NULL) {
  191. snd_pcm_plugin_free(plugin);
  192. return -ENOMEM;
  193. }
  194. plugin->client_channels = snd_pcm_plugin_client_channels;
  195. plugin->src_channels_mask = snd_pcm_plugin_src_channels_mask;
  196. plugin->dst_channels_mask = snd_pcm_plugin_dst_channels_mask;
  197. *ret = plugin;
  198. return 0;
  199. }
  200. int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
  201. {
  202. if (! plugin)
  203. return 0;
  204. if (plugin->private_free)
  205. plugin->private_free(plugin);
  206. kfree(plugin->buf_channels);
  207. vfree(plugin->buf);
  208. kfree(plugin->src_vmask);
  209. kfree(plugin->dst_vmask);
  210. kfree(plugin);
  211. return 0;
  212. }
  213. snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames)
  214. {
  215. struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
  216. int stream = snd_pcm_plug_stream(plug);
  217. snd_assert(plug != NULL, return -ENXIO);
  218. if (drv_frames == 0)
  219. return 0;
  220. if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
  221. plugin = snd_pcm_plug_last(plug);
  222. while (plugin && drv_frames > 0) {
  223. plugin_prev = plugin->prev;
  224. if (plugin->src_frames)
  225. drv_frames = plugin->src_frames(plugin, drv_frames);
  226. plugin = plugin_prev;
  227. }
  228. } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
  229. plugin = snd_pcm_plug_first(plug);
  230. while (plugin && drv_frames > 0) {
  231. plugin_next = plugin->next;
  232. if (plugin->dst_frames)
  233. drv_frames = plugin->dst_frames(plugin, drv_frames);
  234. plugin = plugin_next;
  235. }
  236. } else
  237. snd_BUG();
  238. return drv_frames;
  239. }
  240. snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames)
  241. {
  242. struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
  243. snd_pcm_sframes_t frames;
  244. int stream = snd_pcm_plug_stream(plug);
  245. snd_assert(plug != NULL, return -ENXIO);
  246. if (clt_frames == 0)
  247. return 0;
  248. frames = clt_frames;
  249. if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
  250. plugin = snd_pcm_plug_first(plug);
  251. while (plugin && frames > 0) {
  252. plugin_next = plugin->next;
  253. if (plugin->dst_frames) {
  254. frames = plugin->dst_frames(plugin, frames);
  255. if (frames < 0)
  256. return frames;
  257. }
  258. plugin = plugin_next;
  259. }
  260. } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
  261. plugin = snd_pcm_plug_last(plug);
  262. while (plugin) {
  263. plugin_prev = plugin->prev;
  264. if (plugin->src_frames) {
  265. frames = plugin->src_frames(plugin, frames);
  266. if (frames < 0)
  267. return frames;
  268. }
  269. plugin = plugin_prev;
  270. }
  271. } else
  272. snd_BUG();
  273. return frames;
  274. }
  275. static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
  276. {
  277. struct snd_mask formats = *mask;
  278. u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
  279. SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
  280. SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
  281. SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
  282. SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
  283. SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
  284. SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
  285. snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
  286. if (formats.bits[0] & (u32)linfmts)
  287. formats.bits[0] |= (u32)linfmts;
  288. if (formats.bits[1] & (u32)(linfmts >> 32))
  289. formats.bits[1] |= (u32)(linfmts >> 32);
  290. return snd_mask_test(&formats, format);
  291. }
  292. static int preferred_formats[] = {
  293. SNDRV_PCM_FORMAT_S16_LE,
  294. SNDRV_PCM_FORMAT_S16_BE,
  295. SNDRV_PCM_FORMAT_U16_LE,
  296. SNDRV_PCM_FORMAT_U16_BE,
  297. SNDRV_PCM_FORMAT_S24_LE,
  298. SNDRV_PCM_FORMAT_S24_BE,
  299. SNDRV_PCM_FORMAT_U24_LE,
  300. SNDRV_PCM_FORMAT_U24_BE,
  301. SNDRV_PCM_FORMAT_S32_LE,
  302. SNDRV_PCM_FORMAT_S32_BE,
  303. SNDRV_PCM_FORMAT_U32_LE,
  304. SNDRV_PCM_FORMAT_U32_BE,
  305. SNDRV_PCM_FORMAT_S8,
  306. SNDRV_PCM_FORMAT_U8
  307. };
  308. int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
  309. {
  310. if (snd_mask_test(format_mask, format))
  311. return format;
  312. if (! snd_pcm_plug_formats(format_mask, format))
  313. return -EINVAL;
  314. if (snd_pcm_format_linear(format)) {
  315. int width = snd_pcm_format_width(format);
  316. int unsignd = snd_pcm_format_unsigned(format);
  317. int big = snd_pcm_format_big_endian(format);
  318. int format1;
  319. int wid, width1=width;
  320. int dwidth1 = 8;
  321. for (wid = 0; wid < 4; ++wid) {
  322. int end, big1 = big;
  323. for (end = 0; end < 2; ++end) {
  324. int sgn, unsignd1 = unsignd;
  325. for (sgn = 0; sgn < 2; ++sgn) {
  326. format1 = snd_pcm_build_linear_format(width1, unsignd1, big1);
  327. if (format1 >= 0 &&
  328. snd_mask_test(format_mask, format1))
  329. goto _found;
  330. unsignd1 = !unsignd1;
  331. }
  332. big1 = !big1;
  333. }
  334. if (width1 == 32) {
  335. dwidth1 = -dwidth1;
  336. width1 = width;
  337. }
  338. width1 += dwidth1;
  339. }
  340. return -EINVAL;
  341. _found:
  342. return format1;
  343. } else {
  344. unsigned int i;
  345. switch (format) {
  346. case SNDRV_PCM_FORMAT_MU_LAW:
  347. for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
  348. int format1 = preferred_formats[i];
  349. if (snd_mask_test(format_mask, format1))
  350. return format1;
  351. }
  352. default:
  353. return -EINVAL;
  354. }
  355. }
  356. }
  357. int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
  358. struct snd_pcm_hw_params *params,
  359. struct snd_pcm_hw_params *slave_params)
  360. {
  361. struct snd_pcm_plugin_format tmpformat;
  362. struct snd_pcm_plugin_format dstformat;
  363. struct snd_pcm_plugin_format srcformat;
  364. int src_access, dst_access;
  365. struct snd_pcm_plugin *plugin = NULL;
  366. int err;
  367. int stream = snd_pcm_plug_stream(plug);
  368. int slave_interleaved = (params_channels(slave_params) == 1 ||
  369. params_access(slave_params) == SNDRV_PCM_ACCESS_RW_INTERLEAVED);
  370. switch (stream) {
  371. case SNDRV_PCM_STREAM_PLAYBACK:
  372. dstformat.format = params_format(slave_params);
  373. dstformat.rate = params_rate(slave_params);
  374. dstformat.channels = params_channels(slave_params);
  375. srcformat.format = params_format(params);
  376. srcformat.rate = params_rate(params);
  377. srcformat.channels = params_channels(params);
  378. src_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
  379. dst_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED :
  380. SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
  381. break;
  382. case SNDRV_PCM_STREAM_CAPTURE:
  383. dstformat.format = params_format(params);
  384. dstformat.rate = params_rate(params);
  385. dstformat.channels = params_channels(params);
  386. srcformat.format = params_format(slave_params);
  387. srcformat.rate = params_rate(slave_params);
  388. srcformat.channels = params_channels(slave_params);
  389. src_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED :
  390. SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
  391. dst_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
  392. break;
  393. default:
  394. snd_BUG();
  395. return -EINVAL;
  396. }
  397. tmpformat = srcformat;
  398. pdprintf("srcformat: format=%i, rate=%i, channels=%i\n",
  399. srcformat.format,
  400. srcformat.rate,
  401. srcformat.channels);
  402. pdprintf("dstformat: format=%i, rate=%i, channels=%i\n",
  403. dstformat.format,
  404. dstformat.rate,
  405. dstformat.channels);
  406. /* Format change (linearization) */
  407. if ((srcformat.format != dstformat.format ||
  408. !rate_match(srcformat.rate, dstformat.rate) ||
  409. srcformat.channels != dstformat.channels) &&
  410. !snd_pcm_format_linear(srcformat.format)) {
  411. if (snd_pcm_format_linear(dstformat.format))
  412. tmpformat.format = dstformat.format;
  413. else
  414. tmpformat.format = SNDRV_PCM_FORMAT_S16;
  415. switch (srcformat.format) {
  416. case SNDRV_PCM_FORMAT_MU_LAW:
  417. err = snd_pcm_plugin_build_mulaw(plug,
  418. &srcformat, &tmpformat,
  419. &plugin);
  420. break;
  421. default:
  422. return -EINVAL;
  423. }
  424. pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err);
  425. if (err < 0)
  426. return err;
  427. err = snd_pcm_plugin_append(plugin);
  428. if (err < 0) {
  429. snd_pcm_plugin_free(plugin);
  430. return err;
  431. }
  432. srcformat = tmpformat;
  433. src_access = dst_access;
  434. }
  435. /* channels reduction */
  436. if (srcformat.channels > dstformat.channels) {
  437. int sv = srcformat.channels;
  438. int dv = dstformat.channels;
  439. int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
  440. if (ttable == NULL)
  441. return -ENOMEM;
  442. #if 1
  443. if (sv == 2 && dv == 1) {
  444. ttable[0] = HALF;
  445. ttable[1] = HALF;
  446. } else
  447. #endif
  448. {
  449. int v;
  450. for (v = 0; v < dv; ++v)
  451. ttable[v * sv + v] = FULL;
  452. }
  453. tmpformat.channels = dstformat.channels;
  454. if (rate_match(srcformat.rate, dstformat.rate) &&
  455. snd_pcm_format_linear(dstformat.format))
  456. tmpformat.format = dstformat.format;
  457. err = snd_pcm_plugin_build_route(plug,
  458. &srcformat, &tmpformat,
  459. ttable, &plugin);
  460. kfree(ttable);
  461. pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
  462. if (err < 0) {
  463. snd_pcm_plugin_free(plugin);
  464. return err;
  465. }
  466. err = snd_pcm_plugin_append(plugin);
  467. if (err < 0) {
  468. snd_pcm_plugin_free(plugin);
  469. return err;
  470. }
  471. srcformat = tmpformat;
  472. src_access = dst_access;
  473. }
  474. /* rate resampling */
  475. if (!rate_match(srcformat.rate, dstformat.rate)) {
  476. tmpformat.rate = dstformat.rate;
  477. if (srcformat.channels == dstformat.channels &&
  478. snd_pcm_format_linear(dstformat.format))
  479. tmpformat.format = dstformat.format;
  480. err = snd_pcm_plugin_build_rate(plug,
  481. &srcformat, &tmpformat,
  482. &plugin);
  483. pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, err);
  484. if (err < 0) {
  485. snd_pcm_plugin_free(plugin);
  486. return err;
  487. }
  488. err = snd_pcm_plugin_append(plugin);
  489. if (err < 0) {
  490. snd_pcm_plugin_free(plugin);
  491. return err;
  492. }
  493. srcformat = tmpformat;
  494. src_access = dst_access;
  495. }
  496. /* channels extension */
  497. if (srcformat.channels < dstformat.channels) {
  498. int sv = srcformat.channels;
  499. int dv = dstformat.channels;
  500. int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
  501. if (ttable == NULL)
  502. return -ENOMEM;
  503. #if 0
  504. {
  505. int v;
  506. for (v = 0; v < sv; ++v)
  507. ttable[v * sv + v] = FULL;
  508. }
  509. #else
  510. {
  511. /* Playback is spreaded on all channels */
  512. int vd, vs;
  513. for (vd = 0, vs = 0; vd < dv; ++vd) {
  514. ttable[vd * sv + vs] = FULL;
  515. vs++;
  516. if (vs == sv)
  517. vs = 0;
  518. }
  519. }
  520. #endif
  521. tmpformat.channels = dstformat.channels;
  522. if (snd_pcm_format_linear(dstformat.format))
  523. tmpformat.format = dstformat.format;
  524. err = snd_pcm_plugin_build_route(plug,
  525. &srcformat, &tmpformat,
  526. ttable, &plugin);
  527. kfree(ttable);
  528. pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
  529. if (err < 0) {
  530. snd_pcm_plugin_free(plugin);
  531. return err;
  532. }
  533. err = snd_pcm_plugin_append(plugin);
  534. if (err < 0) {
  535. snd_pcm_plugin_free(plugin);
  536. return err;
  537. }
  538. srcformat = tmpformat;
  539. src_access = dst_access;
  540. }
  541. /* format change */
  542. if (srcformat.format != dstformat.format) {
  543. tmpformat.format = dstformat.format;
  544. if (tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) {
  545. err = snd_pcm_plugin_build_mulaw(plug,
  546. &srcformat, &tmpformat,
  547. &plugin);
  548. }
  549. else if (snd_pcm_format_linear(srcformat.format) &&
  550. snd_pcm_format_linear(tmpformat.format)) {
  551. err = snd_pcm_plugin_build_linear(plug,
  552. &srcformat, &tmpformat,
  553. &plugin);
  554. }
  555. else
  556. return -EINVAL;
  557. pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err);
  558. if (err < 0)
  559. return err;
  560. err = snd_pcm_plugin_append(plugin);
  561. if (err < 0) {
  562. snd_pcm_plugin_free(plugin);
  563. return err;
  564. }
  565. srcformat = tmpformat;
  566. src_access = dst_access;
  567. }
  568. /* de-interleave */
  569. if (src_access != dst_access) {
  570. err = snd_pcm_plugin_build_copy(plug,
  571. &srcformat,
  572. &tmpformat,
  573. &plugin);
  574. pdprintf("interleave change (copy: returns %i)\n", err);
  575. if (err < 0)
  576. return err;
  577. err = snd_pcm_plugin_append(plugin);
  578. if (err < 0) {
  579. snd_pcm_plugin_free(plugin);
  580. return err;
  581. }
  582. }
  583. return 0;
  584. }
  585. snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plug,
  586. char *buf,
  587. snd_pcm_uframes_t count,
  588. struct snd_pcm_plugin_channel **channels)
  589. {
  590. struct snd_pcm_plugin *plugin;
  591. struct snd_pcm_plugin_channel *v;
  592. struct snd_pcm_plugin_format *format;
  593. int width, nchannels, channel;
  594. int stream = snd_pcm_plug_stream(plug);
  595. snd_assert(buf != NULL, return -ENXIO);
  596. if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
  597. plugin = snd_pcm_plug_first(plug);
  598. format = &plugin->src_format;
  599. } else {
  600. plugin = snd_pcm_plug_last(plug);
  601. format = &plugin->dst_format;
  602. }
  603. v = plugin->buf_channels;
  604. *channels = v;
  605. if ((width = snd_pcm_format_physical_width(format->format)) < 0)
  606. return width;
  607. nchannels = format->channels;
  608. snd_assert(plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || format->channels <= 1, return -ENXIO);
  609. for (channel = 0; channel < nchannels; channel++, v++) {
  610. v->frames = count;
  611. v->enabled = 1;
  612. v->wanted = (stream == SNDRV_PCM_STREAM_CAPTURE);
  613. v->area.addr = buf;
  614. v->area.first = channel * width;
  615. v->area.step = nchannels * width;
  616. }
  617. return count;
  618. }
  619. static int snd_pcm_plug_playback_channels_mask(struct snd_pcm_substream *plug,
  620. unsigned long *client_vmask)
  621. {
  622. struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
  623. if (plugin == NULL) {
  624. return 0;
  625. } else {
  626. int schannels = plugin->dst_format.channels;
  627. DECLARE_BITMAP(bs, schannels);
  628. unsigned long *srcmask;
  629. unsigned long *dstmask = bs;
  630. int err;
  631. bitmap_fill(dstmask, schannels);
  632. while (1) {
  633. err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
  634. if (err < 0)
  635. return err;
  636. dstmask = srcmask;
  637. if (plugin->prev == NULL)
  638. break;
  639. plugin = plugin->prev;
  640. }
  641. bitmap_and(client_vmask, client_vmask, dstmask, plugin->src_format.channels);
  642. return 0;
  643. }
  644. }
  645. static int snd_pcm_plug_playback_disable_useless_channels(struct snd_pcm_substream *plug,
  646. struct snd_pcm_plugin_channel *src_channels)
  647. {
  648. struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
  649. unsigned int nchannels = plugin->src_format.channels;
  650. DECLARE_BITMAP(bs, nchannels);
  651. unsigned long *srcmask = bs;
  652. int err;
  653. unsigned int channel;
  654. for (channel = 0; channel < nchannels; channel++) {
  655. if (src_channels[channel].enabled)
  656. set_bit(channel, srcmask);
  657. else
  658. clear_bit(channel, srcmask);
  659. }
  660. err = snd_pcm_plug_playback_channels_mask(plug, srcmask);
  661. if (err < 0)
  662. return err;
  663. for (channel = 0; channel < nchannels; channel++) {
  664. if (!test_bit(channel, srcmask))
  665. src_channels[channel].enabled = 0;
  666. }
  667. return 0;
  668. }
  669. static int snd_pcm_plug_capture_disable_useless_channels(struct snd_pcm_substream *plug,
  670. struct snd_pcm_plugin_channel *src_channels,
  671. struct snd_pcm_plugin_channel *client_channels)
  672. {
  673. struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
  674. unsigned int nchannels = plugin->dst_format.channels;
  675. DECLARE_BITMAP(bs, nchannels);
  676. unsigned long *dstmask = bs;
  677. unsigned long *srcmask;
  678. int err;
  679. unsigned int channel;
  680. for (channel = 0; channel < nchannels; channel++) {
  681. if (client_channels[channel].enabled)
  682. set_bit(channel, dstmask);
  683. else
  684. clear_bit(channel, dstmask);
  685. }
  686. while (plugin) {
  687. err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
  688. if (err < 0)
  689. return err;
  690. dstmask = srcmask;
  691. plugin = plugin->prev;
  692. }
  693. plugin = snd_pcm_plug_first(plug);
  694. nchannels = plugin->src_format.channels;
  695. for (channel = 0; channel < nchannels; channel++) {
  696. if (!test_bit(channel, dstmask))
  697. src_channels[channel].enabled = 0;
  698. }
  699. return 0;
  700. }
  701. snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size)
  702. {
  703. struct snd_pcm_plugin *plugin, *next;
  704. struct snd_pcm_plugin_channel *dst_channels;
  705. int err;
  706. snd_pcm_sframes_t frames = size;
  707. if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0)
  708. return err;
  709. plugin = snd_pcm_plug_first(plug);
  710. while (plugin && frames > 0) {
  711. if ((next = plugin->next) != NULL) {
  712. snd_pcm_sframes_t frames1 = frames;
  713. if (plugin->dst_frames)
  714. frames1 = plugin->dst_frames(plugin, frames);
  715. if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) {
  716. return err;
  717. }
  718. if (err != frames1) {
  719. frames = err;
  720. if (plugin->src_frames)
  721. frames = plugin->src_frames(plugin, frames1);
  722. }
  723. } else
  724. dst_channels = NULL;
  725. pdprintf("write plugin: %s, %li\n", plugin->name, frames);
  726. if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
  727. return frames;
  728. src_channels = dst_channels;
  729. plugin = next;
  730. }
  731. return snd_pcm_plug_client_size(plug, frames);
  732. }
  733. snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size)
  734. {
  735. struct snd_pcm_plugin *plugin, *next;
  736. struct snd_pcm_plugin_channel *src_channels, *dst_channels;
  737. snd_pcm_sframes_t frames = size;
  738. int err;
  739. frames = snd_pcm_plug_slave_size(plug, frames);
  740. if (frames < 0)
  741. return frames;
  742. src_channels = NULL;
  743. plugin = snd_pcm_plug_first(plug);
  744. while (plugin && frames > 0) {
  745. if ((next = plugin->next) != NULL) {
  746. if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) {
  747. return err;
  748. }
  749. frames = err;
  750. if (!plugin->prev) {
  751. if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final)) < 0)
  752. return err;
  753. }
  754. } else {
  755. dst_channels = dst_channels_final;
  756. }
  757. pdprintf("read plugin: %s, %li\n", plugin->name, frames);
  758. if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
  759. return frames;
  760. plugin = next;
  761. src_channels = dst_channels;
  762. }
  763. return frames;
  764. }
  765. int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
  766. size_t samples, int format)
  767. {
  768. /* FIXME: sub byte resolution and odd dst_offset */
  769. unsigned char *dst;
  770. unsigned int dst_step;
  771. int width;
  772. const unsigned char *silence;
  773. if (!dst_area->addr)
  774. return 0;
  775. dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
  776. width = snd_pcm_format_physical_width(format);
  777. if (width <= 0)
  778. return -EINVAL;
  779. if (dst_area->step == (unsigned int) width && width >= 8)
  780. return snd_pcm_format_set_silence(format, dst, samples);
  781. silence = snd_pcm_format_silence_64(format);
  782. if (! silence)
  783. return -EINVAL;
  784. dst_step = dst_area->step / 8;
  785. if (width == 4) {
  786. /* Ima ADPCM */
  787. int dstbit = dst_area->first % 8;
  788. int dstbit_step = dst_area->step % 8;
  789. while (samples-- > 0) {
  790. if (dstbit)
  791. *dst &= 0xf0;
  792. else
  793. *dst &= 0x0f;
  794. dst += dst_step;
  795. dstbit += dstbit_step;
  796. if (dstbit == 8) {
  797. dst++;
  798. dstbit = 0;
  799. }
  800. }
  801. } else {
  802. width /= 8;
  803. while (samples-- > 0) {
  804. memcpy(dst, silence, width);
  805. dst += dst_step;
  806. }
  807. }
  808. return 0;
  809. }
  810. int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,
  811. const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
  812. size_t samples, int format)
  813. {
  814. /* FIXME: sub byte resolution and odd dst_offset */
  815. char *src, *dst;
  816. int width;
  817. int src_step, dst_step;
  818. src = src_area->addr + (src_area->first + src_area->step * src_offset) / 8;
  819. if (!src_area->addr)
  820. return snd_pcm_area_silence(dst_area, dst_offset, samples, format);
  821. dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
  822. if (!dst_area->addr)
  823. return 0;
  824. width = snd_pcm_format_physical_width(format);
  825. if (width <= 0)
  826. return -EINVAL;
  827. if (src_area->step == (unsigned int) width &&
  828. dst_area->step == (unsigned int) width && width >= 8) {
  829. size_t bytes = samples * width / 8;
  830. memcpy(dst, src, bytes);
  831. return 0;
  832. }
  833. src_step = src_area->step / 8;
  834. dst_step = dst_area->step / 8;
  835. if (width == 4) {
  836. /* Ima ADPCM */
  837. int srcbit = src_area->first % 8;
  838. int srcbit_step = src_area->step % 8;
  839. int dstbit = dst_area->first % 8;
  840. int dstbit_step = dst_area->step % 8;
  841. while (samples-- > 0) {
  842. unsigned char srcval;
  843. if (srcbit)
  844. srcval = *src & 0x0f;
  845. else
  846. srcval = (*src & 0xf0) >> 4;
  847. if (dstbit)
  848. *dst = (*dst & 0xf0) | srcval;
  849. else
  850. *dst = (*dst & 0x0f) | (srcval << 4);
  851. src += src_step;
  852. srcbit += srcbit_step;
  853. if (srcbit == 8) {
  854. src++;
  855. srcbit = 0;
  856. }
  857. dst += dst_step;
  858. dstbit += dstbit_step;
  859. if (dstbit == 8) {
  860. dst++;
  861. dstbit = 0;
  862. }
  863. }
  864. } else {
  865. width /= 8;
  866. while (samples-- > 0) {
  867. memcpy(dst, src, width);
  868. src += src_step;
  869. dst += dst_step;
  870. }
  871. }
  872. return 0;
  873. }
  874. #endif