aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-08 18:07:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-08 18:07:14 -0400
commitf5a246eab9a268f51ba8189ea5b098a1bfff200e (patch)
treea6ff7169e0bcaca498d9aec8b0624de1b74eaecb /sound/core
parentd5bbd43d5f450c3fca058f5b85f3dfb4e8cc88c9 (diff)
parent7ff34ad80b7080fafaac8efa9ef0061708eddd51 (diff)
Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "This contains pretty many small commits covering fairly large range of files in sound/ directory. Partly because of additional API support and partly because of constantly developed ASoC and ARM stuff. Some highlights: - Introduced the helper function and documentation for exposing the channel map via control API, as discussed in Plumbers; most of PCI drivers are covered, will follow more drivers later - Most of drivers have been replaced with the new PM callbacks (if the bus is supported) - HD-audio controller got the support of runtime PM and the support of D3 clock-stop. Also changing the power_save option in sysfs kicks off immediately to enable / disable the power-save mode. - Another significant code change in HD-audio is the rewrite of firmware loading code. Other than that, most of changes in HD-audio are continued cleanups and standardization for the generic auto parser and bug fixes (HBR, device-specific fixups), in addition to the support of channel-map API. - Addition of ASoC bindings for the compressed API, used by the mid-x86 drivers. - Lots of cleanups and API refreshes for ASoC codec drivers and DaVinci. - Conversion of OMAP to dmaengine. - New machine driver for Wolfson Microelectronics Bells. - New CODEC driver for Wolfson Microelectronics WM0010. - Enhancements to the ux500 and wm2000 drivers - A new driver for DA9055 and the support for regulator bypass mode." Fix up various arm soc header file reorg conflicts. * tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (339 commits) ALSA: hda - Add new codec ALC283 ALC290 support ALSA: hda - avoid unneccesary indices on "Headphone Jack" controls ALSA: hda - fix indices on boost volume on Conexant ALSA: aloop - add locking to timer access ALSA: hda - Fix hang caused by race during suspend. sound: Remove unnecessary semicolon ALSA: hda/realtek - Fix detection of ALC271X codec ALSA: hda - Add inverted internal mic quirk for Lenovo IdeaPad U310 ALSA: hda - make Realtek/Sigmatel/Conexant use the generic unsol event ALSA: hda - make a generic unsol event handler ASoC: codecs: Add DA9055 codec driver ASoC: eukrea-tlv320: Convert it to platform driver ALSA: ASoC: add DT bindings for CS4271 ASoC: wm_hubs: Ensure volume updates are handled during class W startup ASoC: wm5110: Adding missing volume update bits ASoC: wm5110: Add OUT3R support ASoC: wm5110: Add AEC loopback support ASoC: wm5110: Rename EPOUT to HPOUT3 ASoC: arizona: Add more clock rates ASoC: arizona: Add more DSP options for mixer input muxes ...
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/compress_offload.c26
-rw-r--r--sound/core/control.c1
-rw-r--r--sound/core/info.c7
-rw-r--r--sound/core/info_oss.c3
-rw-r--r--sound/core/oss/mixer_oss.c2
-rw-r--r--sound/core/pcm.c4
-rw-r--r--sound/core/pcm_lib.c214
-rw-r--r--sound/core/pcm_memory.c26
-rw-r--r--sound/core/seq/seq_device.c2
-rw-r--r--sound/core/sgbuf.c27
-rw-r--r--sound/core/sound.c3
11 files changed, 281 insertions, 34 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index eb60cb8dbb8a..c40ae573346d 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -425,6 +425,26 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
425 return 0; 425 return 0;
426} 426}
427 427
428static int snd_compress_check_input(struct snd_compr_params *params)
429{
430 /* first let's check the buffer parameter's */
431 if (params->buffer.fragment_size == 0 ||
432 params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size)
433 return -EINVAL;
434
435 /* now codec parameters */
436 if (params->codec.id == 0 || params->codec.id > SND_AUDIOCODEC_MAX)
437 return -EINVAL;
438
439 if (params->codec.ch_in == 0 || params->codec.ch_out == 0)
440 return -EINVAL;
441
442 if (!(params->codec.sample_rate & SNDRV_PCM_RATE_8000_192000))
443 return -EINVAL;
444
445 return 0;
446}
447
428static int 448static int
429snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) 449snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
430{ 450{
@@ -443,11 +463,17 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
443 retval = -EFAULT; 463 retval = -EFAULT;
444 goto out; 464 goto out;
445 } 465 }
466
467 retval = snd_compress_check_input(params);
468 if (retval)
469 goto out;
470
446 retval = snd_compr_allocate_buffer(stream, params); 471 retval = snd_compr_allocate_buffer(stream, params);
447 if (retval) { 472 if (retval) {
448 retval = -ENOMEM; 473 retval = -ENOMEM;
449 goto out; 474 goto out;
450 } 475 }
476
451 retval = stream->ops->set_params(stream, params); 477 retval = stream->ops->set_params(stream, params);
452 if (retval) 478 if (retval)
453 goto out; 479 goto out;
diff --git a/sound/core/control.c b/sound/core/control.c
index 2487a6bb1c54..7e86a5b9f3b5 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -246,6 +246,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
246 kctl.count = ncontrol->count ? ncontrol->count : 1; 246 kctl.count = ncontrol->count ? ncontrol->count : 1;
247 access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : 247 access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
248 (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| 248 (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
249 SNDRV_CTL_ELEM_ACCESS_VOLATILE|
249 SNDRV_CTL_ELEM_ACCESS_INACTIVE| 250 SNDRV_CTL_ELEM_ACCESS_INACTIVE|
250 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| 251 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE|
251 SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND| 252 SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND|
diff --git a/sound/core/info.c b/sound/core/info.c
index c1e611c65c8f..6b368d25073b 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -28,7 +28,7 @@
28#include <sound/core.h> 28#include <sound/core.h>
29#include <sound/minors.h> 29#include <sound/minors.h>
30#include <sound/info.h> 30#include <sound/info.h>
31#include <sound/version.h> 31#include <linux/utsname.h>
32#include <linux/proc_fs.h> 32#include <linux/proc_fs.h>
33#include <linux/mutex.h> 33#include <linux/mutex.h>
34#include <stdarg.h> 34#include <stdarg.h>
@@ -986,9 +986,8 @@ static struct snd_info_entry *snd_info_version_entry;
986static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 986static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
987{ 987{
988 snd_iprintf(buffer, 988 snd_iprintf(buffer,
989 "Advanced Linux Sound Architecture Driver Version " 989 "Advanced Linux Sound Architecture Driver Version k%s.\n",
990 CONFIG_SND_VERSION CONFIG_SND_DATE ".\n" 990 init_utsname()->release);
991 );
992} 991}
993 992
994static int __init snd_info_version_init(void) 993static int __init snd_info_version_init(void)
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index cf42ab5080eb..83c29dbff9c0 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -26,7 +26,6 @@
26#include <sound/core.h> 26#include <sound/core.h>
27#include <sound/minors.h> 27#include <sound/minors.h>
28#include <sound/info.h> 28#include <sound/info.h>
29#include <sound/version.h>
30#include <linux/utsname.h> 29#include <linux/utsname.h>
31#include <linux/mutex.h> 30#include <linux/mutex.h>
32 31
@@ -94,7 +93,7 @@ static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int d
94static void snd_sndstat_proc_read(struct snd_info_entry *entry, 93static void snd_sndstat_proc_read(struct snd_info_entry *entry,
95 struct snd_info_buffer *buffer) 94 struct snd_info_buffer *buffer)
96{ 95{
97 snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA v" CONFIG_SND_VERSION " emulation code)\n"); 96 snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA emulation code)\n");
98 snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n", 97 snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n",
99 init_utsname()->sysname, 98 init_utsname()->sysname,
100 init_utsname()->nodename, 99 init_utsname()->nodename,
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 18297f7f2c55..29f6ded02555 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1046,6 +1046,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix
1046 1046
1047 if (kctl->info(kctl, uinfo)) { 1047 if (kctl->info(kctl, uinfo)) {
1048 up_read(&mixer->card->controls_rwsem); 1048 up_read(&mixer->card->controls_rwsem);
1049 kfree(uinfo);
1049 return 0; 1050 return 0;
1050 } 1051 }
1051 strcpy(str, ptr->name); 1052 strcpy(str, ptr->name);
@@ -1061,6 +1062,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix
1061 uinfo->value.enumerated.item = slot.capture_item; 1062 uinfo->value.enumerated.item = slot.capture_item;
1062 if (kctl->info(kctl, uinfo)) { 1063 if (kctl->info(kctl, uinfo)) {
1063 up_read(&mixer->card->controls_rwsem); 1064 up_read(&mixer->card->controls_rwsem);
1065 kfree(uinfo);
1064 return 0; 1066 return 0;
1065 } 1067 }
1066 if (!strcmp(uinfo->value.enumerated.name, str)) { 1068 if (!strcmp(uinfo->value.enumerated.name, str)) {
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 1a3070b4e5b5..f2991940b271 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -1105,6 +1105,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
1105 break; 1105 break;
1106 } 1106 }
1107 snd_unregister_device(devtype, pcm->card, pcm->device); 1107 snd_unregister_device(devtype, pcm->card, pcm->device);
1108 if (pcm->streams[cidx].chmap_kctl) {
1109 snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
1110 pcm->streams[cidx].chmap_kctl = NULL;
1111 }
1108 } 1112 }
1109 unlock: 1113 unlock:
1110 mutex_unlock(&register_mutex); 1114 mutex_unlock(&register_mutex);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 7ae671923393..f42c10a43315 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -26,6 +26,7 @@
26#include <linux/export.h> 26#include <linux/export.h>
27#include <sound/core.h> 27#include <sound/core.h>
28#include <sound/control.h> 28#include <sound/control.h>
29#include <sound/tlv.h>
29#include <sound/info.h> 30#include <sound/info.h>
30#include <sound/pcm.h> 31#include <sound/pcm.h>
31#include <sound/pcm_params.h> 32#include <sound/pcm_params.h>
@@ -2302,3 +2303,216 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
2302} 2303}
2303 2304
2304EXPORT_SYMBOL(snd_pcm_lib_readv); 2305EXPORT_SYMBOL(snd_pcm_lib_readv);
2306
2307/*
2308 * standard channel mapping helpers
2309 */
2310
2311/* default channel maps for multi-channel playbacks, up to 8 channels */
2312const struct snd_pcm_chmap_elem snd_pcm_std_chmaps[] = {
2313 { .channels = 1,
2314 .map = { SNDRV_CHMAP_MONO } },
2315 { .channels = 2,
2316 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
2317 { .channels = 4,
2318 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
2319 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
2320 { .channels = 6,
2321 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
2322 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
2323 SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
2324 { .channels = 8,
2325 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
2326 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
2327 SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE,
2328 SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
2329 { }
2330};
2331EXPORT_SYMBOL_GPL(snd_pcm_std_chmaps);
2332
2333/* alternative channel maps with CLFE <-> surround swapped for 6/8 channels */
2334const struct snd_pcm_chmap_elem snd_pcm_alt_chmaps[] = {
2335 { .channels = 1,
2336 .map = { SNDRV_CHMAP_MONO } },
2337 { .channels = 2,
2338 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
2339 { .channels = 4,
2340 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
2341 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
2342 { .channels = 6,
2343 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
2344 SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE,
2345 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
2346 { .channels = 8,
2347 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
2348 SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE,
2349 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
2350 SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
2351 { }
2352};
2353EXPORT_SYMBOL_GPL(snd_pcm_alt_chmaps);
2354
2355static bool valid_chmap_channels(const struct snd_pcm_chmap *info, int ch)
2356{
2357 if (ch > info->max_channels)
2358 return false;
2359 return !info->channel_mask || (info->channel_mask & (1U << ch));
2360}
2361
2362static int pcm_chmap_ctl_info(struct snd_kcontrol *kcontrol,
2363 struct snd_ctl_elem_info *uinfo)
2364{
2365 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
2366
2367 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2368 uinfo->count = 0;
2369 uinfo->count = info->max_channels;
2370 uinfo->value.integer.min = 0;
2371 uinfo->value.integer.max = SNDRV_CHMAP_LAST;
2372 return 0;
2373}
2374
2375/* get callback for channel map ctl element
2376 * stores the channel position firstly matching with the current channels
2377 */
2378static int pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
2379 struct snd_ctl_elem_value *ucontrol)
2380{
2381 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
2382 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2383 struct snd_pcm_substream *substream;
2384 const struct snd_pcm_chmap_elem *map;
2385
2386 if (snd_BUG_ON(!info->chmap))
2387 return -EINVAL;
2388 substream = snd_pcm_chmap_substream(info, idx);
2389 if (!substream)
2390 return -ENODEV;
2391 memset(ucontrol->value.integer.value, 0,
2392 sizeof(ucontrol->value.integer.value));
2393 if (!substream->runtime)
2394 return 0; /* no channels set */
2395 for (map = info->chmap; map->channels; map++) {
2396 int i;
2397 if (map->channels == substream->runtime->channels &&
2398 valid_chmap_channels(info, map->channels)) {
2399 for (i = 0; i < map->channels; i++)
2400 ucontrol->value.integer.value[i] = map->map[i];
2401 return 0;
2402 }
2403 }
2404 return -EINVAL;
2405}
2406
2407/* tlv callback for channel map ctl element
2408 * expands the pre-defined channel maps in a form of TLV
2409 */
2410static int pcm_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2411 unsigned int size, unsigned int __user *tlv)
2412{
2413 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
2414 const struct snd_pcm_chmap_elem *map;
2415 unsigned int __user *dst;
2416 int c, count = 0;
2417
2418 if (snd_BUG_ON(!info->chmap))
2419 return -EINVAL;
2420 if (size < 8)
2421 return -ENOMEM;
2422 if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
2423 return -EFAULT;
2424 size -= 8;
2425 dst = tlv + 2;
2426 for (map = info->chmap; map->channels; map++) {
2427 int chs_bytes = map->channels * 4;
2428 if (!valid_chmap_channels(info, map->channels))
2429 continue;
2430 if (size < 8)
2431 return -ENOMEM;
2432 if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
2433 put_user(chs_bytes, dst + 1))
2434 return -EFAULT;
2435 dst += 2;
2436 size -= 8;
2437 count += 8;
2438 if (size < chs_bytes)
2439 return -ENOMEM;
2440 size -= chs_bytes;
2441 count += chs_bytes;
2442 for (c = 0; c < map->channels; c++) {
2443 if (put_user(map->map[c], dst))
2444 return -EFAULT;
2445 dst++;
2446 }
2447 }
2448 if (put_user(count, tlv + 1))
2449 return -EFAULT;
2450 return 0;
2451}
2452
2453static void pcm_chmap_ctl_private_free(struct snd_kcontrol *kcontrol)
2454{
2455 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
2456 info->pcm->streams[info->stream].chmap_kctl = NULL;
2457 kfree(info);
2458}
2459
2460/**
2461 * snd_pcm_add_chmap_ctls - create channel-mapping control elements
2462 * @pcm: the assigned PCM instance
2463 * @stream: stream direction
2464 * @chmap: channel map elements (for query)
2465 * @max_channels: the max number of channels for the stream
2466 * @private_value: the value passed to each kcontrol's private_value field
2467 * @info_ret: store struct snd_pcm_chmap instance if non-NULL
2468 *
2469 * Create channel-mapping control elements assigned to the given PCM stream(s).
2470 * Returns zero if succeed, or a negative error value.
2471 */
2472int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
2473 const struct snd_pcm_chmap_elem *chmap,
2474 int max_channels,
2475 unsigned long private_value,
2476 struct snd_pcm_chmap **info_ret)
2477{
2478 struct snd_pcm_chmap *info;
2479 struct snd_kcontrol_new knew = {
2480 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2481 .access = SNDRV_CTL_ELEM_ACCESS_READ |
2482 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2483 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
2484 .info = pcm_chmap_ctl_info,
2485 .get = pcm_chmap_ctl_get,
2486 .tlv.c = pcm_chmap_ctl_tlv,
2487 };
2488 int err;
2489
2490 info = kzalloc(sizeof(*info), GFP_KERNEL);
2491 if (!info)
2492 return -ENOMEM;
2493 info->pcm = pcm;
2494 info->stream = stream;
2495 info->chmap = chmap;
2496 info->max_channels = max_channels;
2497 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2498 knew.name = "Playback Channel Map";
2499 else
2500 knew.name = "Capture Channel Map";
2501 knew.device = pcm->device;
2502 knew.count = pcm->streams[stream].substream_count;
2503 knew.private_value = private_value;
2504 info->kctl = snd_ctl_new1(&knew, info);
2505 if (!info->kctl) {
2506 kfree(info);
2507 return -ENOMEM;
2508 }
2509 info->kctl->private_free = pcm_chmap_ctl_private_free;
2510 err = snd_ctl_add(pcm->card, info->kctl);
2511 if (err < 0)
2512 return err;
2513 pcm->streams[stream].chmap_kctl = info->kctl;
2514 if (info_ret)
2515 *info_ret = info;
2516 return 0;
2517}
2518EXPORT_SYMBOL_GPL(snd_pcm_add_chmap_ctls);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 957131366dd9..69e01c4fc32d 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -327,32 +327,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
327} 327}
328 328
329EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); 329EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
330
331/*
332 * compute the max chunk size with continuous pages on sg-buffer
333 */
334unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
335 unsigned int ofs, unsigned int size)
336{
337 struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
338 unsigned int start, end, pg;
339
340 start = ofs >> PAGE_SHIFT;
341 end = (ofs + size - 1) >> PAGE_SHIFT;
342 /* check page continuity */
343 pg = sg->table[start].addr >> PAGE_SHIFT;
344 for (;;) {
345 start++;
346 if (start > end)
347 break;
348 pg++;
349 if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
350 return (start << PAGE_SHIFT) - ofs;
351 }
352 /* ok, all on continuous pages */
353 return size;
354}
355EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size);
356#endif /* CONFIG_SND_DMA_SGBUF */ 330#endif /* CONFIG_SND_DMA_SGBUF */
357 331
358/** 332/**
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 5cf8d65ed5ef..60e8fc1b3440 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -569,5 +569,7 @@ EXPORT_SYMBOL(snd_seq_device_load_drivers);
569EXPORT_SYMBOL(snd_seq_device_new); 569EXPORT_SYMBOL(snd_seq_device_new);
570EXPORT_SYMBOL(snd_seq_device_register_driver); 570EXPORT_SYMBOL(snd_seq_device_register_driver);
571EXPORT_SYMBOL(snd_seq_device_unregister_driver); 571EXPORT_SYMBOL(snd_seq_device_unregister_driver);
572#ifdef CONFIG_MODULES
572EXPORT_SYMBOL(snd_seq_autoload_lock); 573EXPORT_SYMBOL(snd_seq_autoload_lock);
573EXPORT_SYMBOL(snd_seq_autoload_unlock); 574EXPORT_SYMBOL(snd_seq_autoload_unlock);
575#endif
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index d0f00356fc11..0a418503ec41 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -22,6 +22,7 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
25#include <linux/export.h>
25#include <sound/memalloc.h> 26#include <sound/memalloc.h>
26 27
27 28
@@ -136,3 +137,29 @@ void *snd_malloc_sgbuf_pages(struct device *device,
136 snd_free_sgbuf_pages(dmab); /* free the table */ 137 snd_free_sgbuf_pages(dmab); /* free the table */
137 return NULL; 138 return NULL;
138} 139}
140
141/*
142 * compute the max chunk size with continuous pages on sg-buffer
143 */
144unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
145 unsigned int ofs, unsigned int size)
146{
147 struct snd_sg_buf *sg = dmab->private_data;
148 unsigned int start, end, pg;
149
150 start = ofs >> PAGE_SHIFT;
151 end = (ofs + size - 1) >> PAGE_SHIFT;
152 /* check page continuity */
153 pg = sg->table[start].addr >> PAGE_SHIFT;
154 for (;;) {
155 start++;
156 if (start > end)
157 break;
158 pg++;
159 if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
160 return (start << PAGE_SHIFT) - ofs;
161 }
162 /* ok, all on continuous pages */
163 return size;
164}
165EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 28f35593a750..643976000ce8 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -27,7 +27,6 @@
27#include <sound/core.h> 27#include <sound/core.h>
28#include <sound/minors.h> 28#include <sound/minors.h>
29#include <sound/info.h> 29#include <sound/info.h>
30#include <sound/version.h>
31#include <sound/control.h> 30#include <sound/control.h>
32#include <sound/initval.h> 31#include <sound/initval.h>
33#include <linux/kmod.h> 32#include <linux/kmod.h>
@@ -468,7 +467,7 @@ static int __init alsa_sound_init(void)
468 } 467 }
469 snd_info_minor_register(); 468 snd_info_minor_register();
470#ifndef MODULE 469#ifndef MODULE
471 printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); 470 printk(KERN_INFO "Advanced Linux Sound Architecture Driver Initialized.\n");
472#endif 471#endif
473 return 0; 472 return 0;
474} 473}