]> git.hungrycats.org Git - linux/commitdiff
ALSA 0.9.6 update
authorJaroslav Kysela <perex@suse.cz>
Mon, 28 Jul 2003 15:35:31 +0000 (17:35 +0200)
committerJaroslav Kysela <perex@suse.cz>
Mon, 28 Jul 2003 15:35:31 +0000 (17:35 +0200)
  - added __setup() to all midlevel modules
  - sequencer protocol 1.0.1
    - added timestamping flags for ports
  - OSS PCM emulation
    - fixed write() behaviour
    - added two new options no-silence & whole-frag
    - a try to fix OOPSes caused in the rate plugin
  - emu10k1 driver
    - more support for Audigy/Audigy2 EX
    - fixed soundfont locking
  - sb16 driver
    - fixed fm_res handling (and proc OOPS)
  - via82xx driver
    - fixed revision check for 8233A
  - usbaudio driver
    - added a workaround for M-Audio Audiophile USB

37 files changed:
Documentation/sound/alsa/ALSA-Configuration.txt
include/sound/asequencer.h
include/sound/asound.h
include/sound/emu10k1.h
include/sound/pcm_oss.h
include/sound/soundfont.h
include/sound/version.h
sound/core/memalloc.c
sound/core/oss/pcm_oss.c
sound/core/oss/pcm_plugin.c
sound/core/oss/pcm_plugin.h
sound/core/oss/plugin_ops.h
sound/core/oss/rate.c
sound/core/oss/route.c
sound/core/pcm_lib.c
sound/core/pcm_memory.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/rtctimer.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_ports.c
sound/core/seq/seq_ports.h
sound/core/sound.c
sound/core/timer.c
sound/drivers/dummy.c
sound/isa/sb/sb16.c
sound/pci/ac97/ac97_patch.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/irq.c
sound/pci/intel8x0.c
sound/pci/maestro3.c
sound/pci/via82xx.c
sound/synth/emux/soundfont.c
sound/usb/usbaudio.c

index e7a5a5f770e17b1dab268b0b553616128108c2b9..3e1c1dacb1dc64e079db0640138ca417d7a90df2 100644 (file)
@@ -1303,6 +1303,9 @@ Proc interfaces (/proc/asound)
          - direct    don't use plugins
          - block     force block mode (rvplayer)
          - non-block force non-block mode
+         - whole-frag  write only whole fragments (optimization affecting
+                       playback only)
+         - no-silence  do not fill silence ahead to avoid clicks
 
   Example: echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
            echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
index 3c6cce97174d71d1709b34fcb36579e66d4e6135..a787ca9a2ef039f6f5fd81f40a85749e294a40bf 100644 (file)
@@ -29,7 +29,7 @@
 #include <sound/asound.h>
 
 /** version of the sequencer */
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 0)
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
 
 /**
  * definition of sequencer event types
@@ -604,6 +604,8 @@ struct sndrv_seq_remove_events {
 
 /* misc. conditioning flags */
 #define SNDRV_SEQ_PORT_FLG_GIVEN_PORT  (1<<0)
+#define SNDRV_SEQ_PORT_FLG_TIMESTAMP   (1<<1)
+#define SNDRV_SEQ_PORT_FLG_TIME_REAL   (1<<1)
 
 struct sndrv_seq_port_info {
        struct sndrv_seq_addr addr;     /* client/port numbers */
@@ -620,7 +622,8 @@ struct sndrv_seq_port_info {
 
        void *kernel;                   /* reserved for kernel use (must be NULL) */
        unsigned int flags;             /* misc. conditioning */
-       char reserved[60];              /* for future use */
+       unsigned char time_queue;       /* queue # for timestamping */
+       char reserved[59];              /* for future use */
 };
 
 
index 7fdf1c4ce346ebbc37ae38fb2651d5dcab5e243a..99547ab3e252729e596e70637b908dbff29dfea4 100644 (file)
@@ -105,9 +105,10 @@ enum sndrv_hwdep_iface {
        SNDRV_HWDEP_IFACE_ICS2115,      /* Wavetable synth */
        SNDRV_HWDEP_IFACE_SSCAPE,       /* Ensoniq SoundScape ISA card (MC68EC000) */
        SNDRV_HWDEP_IFACE_VX,           /* Digigram VX cards */
+       SNDRV_HWDEP_IFACE_MIXART,       /* Digigram miXart cards */
 
        /* Don't forget to change the following: */
-       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_VX,
+       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_MIXART,
 };
 
 struct sndrv_hwdep_info {
index 438e8bb2adb10f66afb42dac309e924ef3942ab7..0babb7dce20faf0c491b6165952b5d9e4d6f900f 100644 (file)
@@ -931,6 +931,7 @@ struct _snd_emu10k1 {
        unsigned long port;                     /* I/O port number */
        struct resource *res_port;
        int APS: 1,                             /* APS flag */
+           no_ac97: 1,                         /* no AC'97 */
            tos_link: 1;                        /* tos link detected */
        unsigned int audigy;                    /* is Audigy? */
        unsigned int revision;                  /* chip revision */
index d6274a5a1c7605a330b8f1ce6c9d0e4bac6ae845..ca49220494234ab7b052cfe72cbdd8884a30eb5f 100644 (file)
@@ -30,7 +30,9 @@ struct _snd_pcm_oss_setup {
        unsigned int disable:1,
                     direct:1,
                     block:1,
-                    nonblock:1;
+                    nonblock:1,
+                    wholefrag:1,
+                    nosilence:1;
        unsigned int periods;
        unsigned int period_size;
        snd_pcm_oss_setup_t *next;
index a5c68cf7275d2e9afc87e4dd1b21365bd2e2649e..cdd493c387c77b18db9d80c7f5f4f2dc2e938f1e 100644 (file)
@@ -95,7 +95,6 @@ typedef struct snd_sf_list {
        int zone_locked;        /* locked time for zone */
        int sample_locked;      /* locked time for sample */
        snd_sf_callback_t callback;     /* callback functions */
-       char sf_locked;         /* font lock flag */
        struct semaphore presets_mutex;
        spinlock_t lock;
        snd_util_memhdr_t *memhdr;
index 58685a9fb93e428c4d77fc5893671a2cedd712fd..7a720532c1b7d4c71f9a1921a69f06d8765ccdf6 100644 (file)
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
-#define CONFIG_SND_VERSION "0.9.5"
-#define CONFIG_SND_DATE " (Mon Jul 21 08:59:59 2003 UTC)"
+#define CONFIG_SND_VERSION "0.9.6"
+#define CONFIG_SND_DATE " (Mon Jul 28 11:08:42 2003 UTC)"
index 5efa14f5987c9cc39dea6fe19fb4de06f2ed33f9..0a17b04c3bf64df63930cbf5982c4d8901ca3ffd 100644 (file)
@@ -946,6 +946,25 @@ module_init(snd_mem_init)
 module_exit(snd_mem_exit)
 
 
+#ifndef MODULE
+
+/* format is: snd-page-alloc=enable */
+
+static int __init snd_mem_setup(char *str)
+{
+       static unsigned __initdata nr_dev = 0;
+
+       if (nr_dev >= SNDRV_CARDS)
+               return 0;
+       (void)(get_option(&str,&enable[nr_dev]) == 2);
+       nr_dev++;
+       return 1;
+}
+
+__setup("snd-page-alloc=", snd_mem_setup);
+
+#endif
+
 /*
  * exports
  */
index 0cbaac6076d3e441b5d7eee7e05065bdc0030f01..257ad284120f9bf09b17b6b8b70f4a1f14a30249 100644 (file)
@@ -454,8 +454,18 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
        sw_params->sleep_min = 0;
        sw_params->avail_min = runtime->period_size;
        sw_params->xfer_align = 1;
-       sw_params->silence_threshold = 0;
-       sw_params->silence_size = 0;
+       if (atomic_read(&runtime->mmap_count) ||
+           (substream->oss.setup && substream->oss.setup->nosilence)) {
+               sw_params->silence_threshold = 0;
+               sw_params->silence_size = 0;
+       } else {
+               snd_pcm_uframes_t frames;
+               frames = runtime->period_size + 16;
+               if (frames > runtime->buffer_size)
+                       frames = runtime->buffer_size;
+               sw_params->silence_threshold = frames;
+               sw_params->silence_size = frames;
+       }
 
        if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) {
                snd_printd("SW_PARAMS failed: %i\n", err);
@@ -581,7 +591,7 @@ static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, sn
                if (err < 0)
                        break;
                runtime = substream->runtime;
-               if (*delay <= runtime->buffer_size)
+               if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size)
                        break;
                /* in case of overrun, skip whole periods like OSS/Linux driver does */
                /* until avail(delay) <= buffer_size */
@@ -802,8 +812,9 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char *bu
                        buf += tmp;
                        bytes -= tmp;
                        xfer += tmp;
-                       if (runtime->oss.buffer_used == runtime->oss.period_bytes) {
-                               tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
+                       if (substream->oss.setup == NULL || !substream->oss.setup->wholefrag ||
+                           runtime->oss.buffer_used == runtime->oss.period_bytes) {
+                               tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.buffer_used, 1);
                                if (tmp <= 0)
                                        return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
                                runtime->oss.bytes += tmp;
@@ -2108,14 +2119,16 @@ static void snd_pcm_oss_proc_read(snd_info_entry_t *entry,
        snd_pcm_oss_setup_t *setup = pstr->oss.setup_list;
        down(&pstr->oss.setup_mutex);
        while (setup) {
-               snd_iprintf(buffer, "%s %u %u%s%s%s%s\n",
+               snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
                            setup->task_name,
                            setup->periods,
                            setup->period_size,
                            setup->disable ? " disable" : "",
                            setup->direct ? " direct" : "",
                            setup->block ? " block" : "",
-                           setup->nonblock ? " non-block" : "");
+                           setup->nonblock ? " non-block" : "",
+                           setup->wholefrag ? " whole-frag" : "",
+                           setup->nosilence ? " no-silence" : "");
                setup = setup->next;
        }
        up(&pstr->oss.setup_mutex);
@@ -2181,6 +2194,10 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
                                template.block = 1;
                        } else if (!strcmp(str, "non-block")) {
                                template.nonblock = 1;
+                       } else if (!strcmp(str, "whole-frag")) {
+                               template.wholefrag = 1;
+                       } else if (!strcmp(str, "no-silence")) {
+                               template.nosilence = 1;
                        }
                } while (*str);
                if (setup == NULL) {
@@ -2372,3 +2389,24 @@ static void __exit alsa_pcm_oss_exit(void)
 
 module_init(alsa_pcm_oss_init)
 module_exit(alsa_pcm_oss_exit)
+
+#ifndef MODULE
+
+/* format is: snd-pcm-oss=dsp_map,adsp_map[,nonblock_open] */
+
+static int __init alsa_pcm_oss_setup(char *str)
+{
+       static unsigned __initdata nr_dev = 0;
+
+       if (nr_dev >= SNDRV_CARDS)
+               return 0;
+       (void)(get_option(&str,&dsp_map[nr_dev]) == 2 &&
+              get_option(&str,&adsp_map[nr_dev]) == 2);
+       (void)(get_option(&str,&nonblock_open) == 2);
+       nr_dev++;
+       return 1;
+}
+
+__setup("snd-pcm-oss=", alsa_pcm_oss_setup);
+
+#endif /* !MODULE */
index cfeb97127bf985be59d1386f878f44c026dba662..5da5c1bc004ffe9042d016dc58bff33ff7bfe51e 100644 (file)
@@ -56,6 +56,17 @@ static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin,
        return 0;
 }
 
+/*
+ *  because some cards might have rates "very close", we ignore
+ *  all "resampling" requests within +-5%
+ */
+static int rate_match(unsigned int src_rate, unsigned int dst_rate)
+{
+       unsigned int low = (src_rate * 95) / 100;
+       unsigned int high = (src_rate * 105) / 100;
+       return dst_rate >= low && dst_rate <= high;
+}
+
 static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames)
 {
        snd_pcm_plugin_format_t *format;
@@ -80,11 +91,14 @@ static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t fram
                plugin->buf = vmalloc(size);
                plugin->buf_frames = frames;
        }
-       if (!plugin->buf)
+       if (!plugin->buf) {
+               plugin->buf_frames = 0;
                return -ENOMEM;
+       }
        c = plugin->buf_channels;
        if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
                for (channel = 0; channel < format->channels; channel++, c++) {
+                       c->frames = frames;
                        c->enabled = 1;
                        c->wanted = 0;
                        c->area.addr = plugin->buf;
@@ -95,6 +109,7 @@ static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t fram
                snd_assert((size % format->channels) == 0,);
                size /= format->channels;
                for (channel = 0; channel < format->channels; channel++, c++) {
+                       c->frames = frames;
                        c->enabled = 1;
                        c->wanted = 0;
                        c->area.addr = plugin->buf + (channel * size);
@@ -420,7 +435,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
 
        /* Format change (linearization) */
        if ((srcformat.format != dstformat.format ||
-            srcformat.rate != dstformat.rate ||
+            !rate_match(srcformat.rate, dstformat.rate) ||
             srcformat.channels != dstformat.channels) &&
            !snd_pcm_format_linear(srcformat.format)) {
                if (snd_pcm_format_linear(dstformat.format))
@@ -468,7 +483,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
                                ttable[v * sv + v] = FULL;
                }
                tmpformat.channels = dstformat.channels;
-               if (srcformat.rate == dstformat.rate &&
+               if (rate_match(srcformat.rate, dstformat.rate) &&
                    snd_pcm_format_linear(dstformat.format))
                        tmpformat.format = dstformat.format;
                err = snd_pcm_plugin_build_route(plug,
@@ -490,7 +505,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
        }
 
        /* rate resampling */
-       if (srcformat.rate != dstformat.rate) {
+       if (!rate_match(srcformat.rate, dstformat.rate)) {
                tmpformat.rate = dstformat.rate;
                if (srcformat.channels == dstformat.channels &&
                    snd_pcm_format_linear(dstformat.format))
index 48b63a5cb7e86d34a05c28105a42432266ad1b09..e010af47992f8a7df96b26253a158599ca5f1398 100644 (file)
@@ -106,6 +106,7 @@ typedef struct _snd_pcm_channel_area {
 typedef struct _snd_pcm_plugin_channel {
        void *aptr;                     /* pointer to the allocated area */
        snd_pcm_channel_area_t area;
+       snd_pcm_uframes_t frames;       /* allocated frames */
        unsigned int enabled:1;         /* channel need to be processed */
        unsigned int wanted:1;          /* channel is wanted */
 } snd_pcm_plugin_channel_t;
index 1bf0fc7f80ec2b800e0a91905e21abc505039199..0607e956608471c4bfe5748a658a964d237cea09 100644 (file)
@@ -323,7 +323,7 @@ get_s16_1234_xxC3: sample = swab16(as_u32(src) ^ 0x80); goto GET_S16_END;
 
 #ifdef PUT_S16_LABELS
 /* dst_wid dst_endswap unsigned */
-static void *put_s16_labels[4 * 2 * 2 * 4 * 2] = {
+static void *put_s16_labels[4 * 2 * 2] = {
        &&put_s16_xx12_xxx1,     /* 16h ->  8h */
        &&put_s16_xx12_xxx9,     /* 16h ^>  8h */
        &&put_s16_xx12_xxx1,     /* 16h ->  8s */
index 6b952ec2d0f63beff440ebfe60883e1c4cb4af02..70a79d3e8c3d3e3d2b24a265075010e531135ae1 100644 (file)
@@ -85,11 +85,7 @@ static void resample_expand(snd_pcm_plugin_t *plugin,
 #undef PUT_S16_LABELS
        void *get = get_s16_labels[data->get];
        void *put = put_s16_labels[data->put];
-       void *get_s16_end = 0;
        signed short sample = 0;
-#define GET_S16_END *get_s16_end
-#include "plugin_ops.h"
-#undef GET_S16_END
        
        for (channel = 0; channel < plugin->src_format.channels; channel++) {
                pos = data->pos;
@@ -108,24 +104,16 @@ static void resample_expand(snd_pcm_plugin_t *plugin,
                dst_step = dst_channels[channel].area.step / 8;
                src_frames1 = src_frames;
                dst_frames1 = dst_frames;
-               if (pos & ~R_MASK) {
-                       get_s16_end = &&after_get1;
-                       goto *get;
-               after_get1:
-                       pos &= R_MASK;
-                       S1 = S2;
-                       S2 = sample;
-                       src += src_step;
-                       src_frames1--;
-               }
                while (dst_frames1-- > 0) {
                        if (pos & ~R_MASK) {
                                pos &= R_MASK;
                                S1 = S2;
                                if (src_frames1-- > 0) {
-                                       get_s16_end = &&after_get2;
                                        goto *get;
-                               after_get2:
+#define GET_S16_END after_get
+#include "plugin_ops.h"
+#undef GET_S16_END
+                               after_get:
                                        S2 = sample;
                                        src += src_step;
                                }
@@ -318,6 +306,8 @@ static snd_pcm_sframes_t rate_transfer(snd_pcm_plugin_t *plugin,
 #endif
 
        dst_frames = rate_dst_frames(plugin, frames);
+       if (dst_frames > dst_channels[0].frames)
+               dst_frames = dst_channels[0].frames;
        data = (rate_t *)plugin->extra_data;
        data->func(plugin, src_channels, dst_channels, frames, dst_frames);
        return dst_frames;
index bef8c83efdbb35f2024250a5fe7a81c37ddc98a7..fadc265a0cc5990f217b9b5e0ca8a10cef6074d8 100644 (file)
@@ -518,6 +518,10 @@ int getput_index(int format)
        int sign, width, endian;
        sign = !snd_pcm_format_signed(format);
        width = snd_pcm_format_width(format) / 8 - 1;
+       if (width < 0 || width > 3) {
+               snd_printk(KERN_ERR "snd-pcm-oss: invalid format %d\n", format);
+               width = 0;
+       }
 #ifdef SNDRV_LITTLE_ENDIAN
        endian = snd_pcm_format_big_endian(format);
 #else
index 8406c7ae26534e48a7681599f2338850a870d554..4fa1665bc37bde98d7659c75cc63021a766dea3c 100644 (file)
@@ -60,13 +60,11 @@ void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t
                        return;
                snd_assert(runtime->silence_filled <= runtime->buffer_size, return);
                noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
-               if (noise_dist > (snd_pcm_sframes_t) runtime->silence_threshold)
+               if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold)
                        return;
                frames = runtime->silence_threshold - noise_dist;
                if (frames > runtime->silence_size)
                        frames = runtime->silence_size;
-               else
-                       frames = runtime->silence_threshold;
        } else {
                if (new_hw_ptr == ULONG_MAX) {  /* initialization */
                        runtime->silence_filled = 0;
@@ -86,10 +84,9 @@ void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t
                        if ((snd_pcm_sframes_t)runtime->silence_start < 0)
                                runtime->silence_start += runtime->boundary;
                }
-               frames = runtime->buffer_size;
+               frames = runtime->buffer_size - runtime->silence_filled;
        }
-       snd_assert(frames >= runtime->silence_filled, return);
-       frames -= runtime->silence_filled;
+       snd_assert(frames <= runtime->buffer_size, return);
        if (frames == 0)
                return;
        ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size;
index 07964d699fc102b5e52cb022abea6f8be3cdb02e..156d2c800698e0a5a1b63ce72e0a578cd3008356 100644 (file)
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/time.h>
+#include <linux/init.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/info.h>
@@ -568,3 +569,18 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon
 }
 
 #endif /* CONFIG_PCI */
+
+#ifndef MODULE
+
+/* format is: snd-pcm=preallocate_dma,maximum_substreams */
+
+static int __init alsa_pcm_setup(char *str)
+{
+       (void)(get_option(&str,&preallocate_dma) == 2 &&
+              get_option(&str,&maximum_substreams) == 2);
+       return 1;
+}
+
+__setup("snd-pcm=", alsa_pcm_setup);
+
+#endif /* ifndef MODULE */
index 24b451032bedb06466675ee1d919082d67524ece..f82b4f5cfce0645ae39b06debc97ed4879fbc8cb 100644 (file)
@@ -461,9 +461,15 @@ static int snd_pcm_sw_params(snd_pcm_substream_t * substream, snd_pcm_sw_params_
        if (params->xfer_align == 0 ||
            params->xfer_align % runtime->min_align != 0)
                return -EINVAL;
-       if ((params->silence_threshold != 0 || params->silence_size < runtime->boundary) &&
-           (params->silence_threshold + params->silence_size > runtime->buffer_size))
-               return -EINVAL;
+       if (params->silence_size >= runtime->boundary) {
+               if (params->silence_threshold != 0)
+                       return -EINVAL;
+       } else {
+               if (params->silence_size > params->silence_threshold)
+                       return -EINVAL;
+               if (params->silence_threshold > runtime->buffer_size)
+                       return -EINVAL;
+       }
        snd_pcm_stream_lock_irq(substream);
        runtime->tstamp_mode = params->tstamp_mode;
        runtime->sleep_min = params->sleep_min;
index 67564ab38a2e2085b4ed27146e6050d46e6c66ec..8be2292ad25e4f454ce6fca9f5fc30c908a0e12a 100644 (file)
@@ -1630,6 +1630,26 @@ static void __exit alsa_rawmidi_exit(void)
 module_init(alsa_rawmidi_init)
 module_exit(alsa_rawmidi_exit)
 
+#ifndef MODULE
+#ifdef CONFIG_SND_OSSEMUL
+/* format is: snd-rawmidi=midi_map,amidi_map */
+
+static int __init alsa_rawmidi_setup(char *str)
+{
+       static unsigned __initdata nr_dev = 0;
+
+       if (nr_dev >= SNDRV_CARDS)
+               return 0;
+       (void)(get_option(&str,&midi_map[nr_dev]) == 2 &&
+              get_option(&str,&amidi_map[nr_dev]) == 2);
+       nr_dev++;
+       return 1;
+}
+
+__setup("snd-rawmidi=", alsa_rawmidi_setup);
+#endif /* CONFIG_SND_OSSEMUL */
+#endif /* ifndef MODULE */
+
 EXPORT_SYMBOL(snd_rawmidi_output_params);
 EXPORT_SYMBOL(snd_rawmidi_input_params);
 EXPORT_SYMBOL(snd_rawmidi_drop_output);
index 0c08b14ce17ef124060b758157ccbdef70acf24d..79b30f13f21d1c89284eb82c581cc274be013d3e 100644 (file)
@@ -57,7 +57,7 @@ static struct _snd_timer_hardware rtc_hw = {
        .stop =         rtctimer_stop,
 };
 
-int rtctimer_freq = RTC_FREQ;          /* frequency */
+static int rtctimer_freq = RTC_FREQ;           /* frequency */
 static snd_timer_t *rtctimer;
 static atomic_t rtc_inc = ATOMIC_INIT(0);
 static rtc_task_t rtc_task;
@@ -182,4 +182,16 @@ MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz");
 
 MODULE_LICENSE("GPL");
 
+#ifndef MODULE
+/* format is: snd-rtctimer=freq */
+
+static int __init rtctimer_setup(char *str)
+{
+       (void)(get_option(&str,&rtctimer_freq) == 2);
+       return 1;
+}
+
+__setup("snd-rtctimer=", rtctimer_setup);
+#endif /* ifndef MODULE */
+
 #endif /* CONFIG_RTC || CONFIG_RTC_MODULE */
index 929bd8d9dbf9d2135b5d9ec4eb8dce081a06e1f8..fabed51c89b31d7d5e944655fdf38b4da4808a99 100644 (file)
@@ -520,6 +520,32 @@ static int bounce_error_event(client_t *client, snd_seq_event_t *event,
 }
 
 
+/*
+ * rewrite the time-stamp of the event record with the curren time
+ * of the given queue.
+ * return non-zero if updated.
+ */
+static int update_timestamp_of_queue(snd_seq_event_t *event, int queue, int real_time)
+{
+       queue_t *q;
+
+       q = queueptr(queue);
+       if (! q)
+               return 0;
+       event->queue = queue;
+       event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
+       if (real_time) {
+               event->time.time = snd_seq_timer_get_cur_time(q->timer);
+               event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
+       } else {
+               event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
+               event->flags |= SNDRV_SEQ_TIME_STAMP_TICK;
+       }
+       queuefree(q);
+       return 1;
+}
+
+
 /*
  * deliver an event to the specified destination.
  * if filter is non-zero, client filter bitmap is tested.
@@ -551,6 +577,10 @@ static int snd_seq_deliver_single_event(client_t *client,
                goto __skip;
        }
                
+       if (dest_port->timestamping)
+               update_timestamp_of_queue(event, dest_port->time_queue,
+                                         dest_port->time_real);
+
        /* expand the quoted event */
        if (event->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE) {
                quoted = 1;
@@ -597,27 +627,6 @@ static int snd_seq_deliver_single_event(client_t *client,
 }
 
 
-static void snd_seq_subs_update_event_header(subscribers_t *subs, snd_seq_event_t *event)
-{
-       if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) {
-               /* convert time according to flag with subscription */
-               queue_t *q;
-               q = queueptr(subs->info.queue);
-               if (q) {
-                       event->queue = subs->info.queue;
-                       event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
-                       if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) {
-                               event->time.time = snd_seq_timer_get_cur_time(q->timer);
-                               event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
-                       } else {
-                               event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
-                               event->flags |= SNDRV_SEQ_TIME_STAMP_TICK;
-                       }
-                       queuefree(q);
-               }
-       }
-}
-
 /*
  * send the event to all subscribers:
  */
@@ -647,7 +656,10 @@ static int deliver_to_subscribers(client_t *client,
        list_for_each(p, &grp->list_head) {
                subs = list_entry(p, subscribers_t, src_list);
                event->dest = subs->info.dest;
-               snd_seq_subs_update_event_header(subs, event);
+               if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
+                       /* convert time according to flag with subscription */
+                       update_timestamp_of_queue(event, subs->info.queue,
+                                                 subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);
                err = snd_seq_deliver_single_event(client, event,
                                                   0, atomic, hop);
                if (err < 0)
index 9167e164d5924aa6587c84ca37b42be15c2cea46..6f29eb0009a7f5ff874abc6e2a2ae15f715c2ae2 100644 (file)
@@ -352,6 +352,11 @@ int snd_seq_set_port_info(client_port_t * port, snd_seq_port_info_t * info)
        port->midi_voices = info->midi_voices;
        port->synth_voices = info->synth_voices;
 
+       /* timestamping */
+       port->timestamping = (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0;
+       port->time_real = (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
+       port->time_queue = info->time_queue;
+
        return 0;
 }
 
@@ -378,6 +383,15 @@ int snd_seq_get_port_info(client_port_t * port, snd_seq_port_info_t * info)
        info->read_use = port->c_src.count;
        info->write_use = port->c_dest.count;
        
+       /* timestamping */
+       info->flags = 0;
+       if (port->timestamping) {
+               info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP;
+               if (port->time_real)
+                       info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL;
+               info->time_queue = port->time_queue;
+       }
+
        return 0;
 }
 
index a6b5395aa26a4c86b5307f1e6ceffcab654c3b51..4d0dc144554e41d4f7b30730d4d7ab1fd13899e9 100644 (file)
@@ -74,6 +74,9 @@ typedef struct client_port_t {
        void *private_data;
        unsigned int callback_all : 1;
        unsigned int closing : 1;
+       unsigned int timestamping: 1;
+       unsigned int time_real: 1;
+       int time_queue;
        
        /* capability, inport, output, sync */
        unsigned int capability;        /* port capability bits */
index fbf21531eeba072881464d955db17fb0a0c54626..5d0c19889d781343ab18ae6ac782434097870077 100644 (file)
@@ -389,6 +389,24 @@ static void __exit alsa_sound_exit(void)
 module_init(alsa_sound_init)
 module_exit(alsa_sound_exit)
 
+#ifndef MODULE
+
+/* format is: snd=major,cards_limit[,device_mode] */
+
+static int __init alsa_sound_setup(char *str)
+{
+       (void)(get_option(&str,&major) == 2 &&
+              get_option(&str,&cards_limit) == 2);
+#ifdef CONFIG_DEVFS_FS
+       (void)(get_option(&str,&device_mode) == 2);
+#endif
+       return 1;
+}
+
+__setup("snd=", alsa_sound_setup);
+
+#endif /* ifndef MODULE */
+
   /* sound.c */
 EXPORT_SYMBOL(snd_major);
 EXPORT_SYMBOL(snd_ecards_limit);
index 81ff5d17abfc72976dca7e9233804092a5670a5d..99a5c984e378e499937853d73fb3ce40e5c85674 100644 (file)
@@ -41,7 +41,7 @@
 #define DEFAULT_TIMER_LIMIT 2
 #endif
 
-int timer_limit = DEFAULT_TIMER_LIMIT;
+static int timer_limit = DEFAULT_TIMER_LIMIT;
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA timer interface");
 MODULE_LICENSE("GPL");
@@ -1806,6 +1806,18 @@ static void __exit alsa_timer_exit(void)
 module_init(alsa_timer_init)
 module_exit(alsa_timer_exit)
 
+#ifndef MODULE
+/* format is: snd-timer=timer_limit */
+
+static int __init alsa_timer_setup(char *str)
+{
+       (void)(get_option(&str,&timer_limit) == 2);
+       return 1;
+}
+
+__setup("snd-timer=", alsa_timer_setup);
+#endif /* ifndef MODULE */
+
 EXPORT_SYMBOL(snd_timer_open);
 EXPORT_SYMBOL(snd_timer_close);
 EXPORT_SYMBOL(snd_timer_resolution);
index c7edada0fdf27d4c5512f24ffc9ceb93a557f9be..991d593f127b63af0ff0d1de7f17b2389de57be1 100644 (file)
@@ -69,6 +69,15 @@ MODULE_DEVICES("{{ALSA,Dummy soundcard}}");
 #define USE_PERIODS_MAX                255
 #endif
 
+#if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */
+#define USE_FORMATS            SNDRV_PCM_FMTBIT_S16_LE
+#define USE_CHANNELS_MIN       2
+#define USE_CHANNELS_MAX       2
+#define USE_RATE               SNDRV_PCM_RATE_48000
+#define USE_RATE_MIN           48000
+#define USE_RATE_MAX           48000
+#endif
+
 
 /* defaults */
 #ifndef MAX_BUFFER_SIZE
@@ -77,6 +86,11 @@ MODULE_DEVICES("{{ALSA,Dummy soundcard}}");
 #ifndef USE_FORMATS
 #define USE_FORMATS            (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
 #endif
+#ifndef USE_RATE
+#define USE_RATE               SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
+#define USE_RATE_MIN           5500
+#define USE_RATE_MAX           48000
+#endif
 #ifndef USE_CHANNELS_MIN
 #define USE_CHANNELS_MIN       1
 #endif
@@ -271,9 +285,9 @@ static snd_pcm_hardware_t snd_card_dummy_playback =
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_MMAP_VALID),
        .formats =              USE_FORMATS,
-       .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-       .rate_min =             5500,
-       .rate_max =             48000,
+       .rates =                USE_RATE,
+       .rate_min =             USE_RATE_MIN,
+       .rate_max =             USE_RATE_MAX,
        .channels_min =         USE_CHANNELS_MIN,
        .channels_max =         USE_CHANNELS_MAX,
        .buffer_bytes_max =     MAX_BUFFER_SIZE,
@@ -289,9 +303,9 @@ static snd_pcm_hardware_t snd_card_dummy_capture =
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_MMAP_VALID),
        .formats =              USE_FORMATS,
-       .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-       .rate_min =             5500,
-       .rate_max =             48000,
+       .rates =                USE_RATE,
+       .rate_min =             USE_RATE_MIN,
+       .rate_max =             USE_RATE_MAX,
        .channels_min =         USE_CHANNELS_MIN,
        .channels_max =         USE_CHANNELS_MAX,
        .buffer_bytes_max =     MAX_BUFFER_SIZE,
index 1370bef958f07ec65910763053d3587bde2465cd..68f5a7567177222a633f7f86b136f4eb3d6f453f 100644 (file)
@@ -350,6 +350,18 @@ __wt_error:
 
 #endif /* CONFIG_PNP */
 
+static void snd_sb16_free(snd_card_t *card)
+{
+       struct snd_card_sb16 *acard = (struct snd_card_sb16 *)card->private_data;
+        
+       if (acard == NULL)
+               return;
+       if (acard->fm_res) {
+               release_resource(acard->fm_res);
+               kfree_nocheck(acard->fm_res);
+       }
+}
+
 static int __init snd_sb16_probe(int dev,
                                 struct pnp_card_link *pcard,
                                 const struct pnp_card_device_id *pid)
@@ -374,6 +386,7 @@ static int __init snd_sb16_probe(int dev,
        if (card == NULL)
                return -ENOMEM;
        acard = (struct snd_card_sb16 *) card->private_data;
+       card->private_free = snd_sb16_free;
 #ifdef CONFIG_PNP
        if (isapnp[dev]) {
                if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid))) {
@@ -464,7 +477,8 @@ static int __init snd_sb16_probe(int dev,
 
        if (fm_port[dev] > 0) {
                if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
-                                   OPL3_HW_OPL3, fm_port[dev] == port[dev],
+                                   OPL3_HW_OPL3,
+                                   fm_port[dev] == port[dev] || fm_port[dev] == 0x388,
                                    &opl3) < 0) {
                        snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
                                   fm_port[dev], fm_port[dev] + 2);
index 37015df7f905162322fff9944c039ff2946d1d0a..ebd7c1f35d7c2d076de17d88dd7455f8045d0fe9 100644 (file)
@@ -650,6 +650,26 @@ int patch_ad1881(ac97_t * ac97)
        return 0;
 }
 
+static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
+       AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
+       AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0),
+       AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
+       AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
+};
+
+static int patch_ad1885_specific(ac97_t * ac97)
+{
+       int err;
+
+       if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
+               return err;
+       return 0;
+}
+
+static struct snd_ac97_build_ops patch_ad1885_build_ops = {
+       .build_specific = &patch_ad1885_specific
+};
+
 int patch_ad1885(ac97_t * ac97)
 {
        unsigned short jack;
@@ -661,6 +681,8 @@ int patch_ad1885(ac97_t * ac97)
        /* turn off jack sense bits D8 & D9 */
        jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF);
        snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300);
+
+       ac97->build_ops = &patch_ad1885_build_ops;
        return 0;
 }
 
index 122235142da4345a11530468341f2cc2dcafaccf..8c39d76ebae180db7e4322b7637780a5fd836fe0 100644 (file)
@@ -135,11 +135,9 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
                snd_card_free(card);
                return err;
        }               
-       if (!emu->APS) {        /* APS board has not an AC97 mixer */
-               if ((err = snd_emu10k1_mixer(emu)) < 0) {
-                       snd_card_free(card);
-                       return err;
-               }               
+       if ((err = snd_emu10k1_mixer(emu)) < 0) {
+               snd_card_free(card);
+               return err;
        }
        if (emu->audigy) {
                if ((err = snd_emu10k1_audigy_midi(emu)) < 0) {
index 939ad83cb7834e0e4c0da4e261b4bc02026dfe49..262270ad07331712a3ec39235864e1e5c34f45e1 100644 (file)
@@ -674,6 +674,14 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
        if (emu->serial == 0x40011102) {
                emu->card_type = EMU10K1_CARD_EMUAPS;
                emu->APS = 1;
+               emu->no_ac97 = 1; /* APS has no AC97 chip */
+       }
+       else if (emu->revision == 4 && emu->serial == 0x10051102) {
+               /* Audigy 2 EX has apparently no effective AC97 controls
+                * (for both input and output), so we skip the AC97 detections
+                */
+               snd_printdd(KERN_INFO "Audigy2 EX is detected. skpping ac97.\n");
+               emu->no_ac97 = 1;
        }
        
        emu->fx8010.fxbus_mask = 0x303f;
index 3dfa09ce8c74420e433f4f0338f56809bbdd8ba7..d2683e849da03f4823c081939557f59a3993c127 100644 (file)
@@ -1238,7 +1238,10 @@ static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_contr
 
 static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
 {
-       int err, i, z, gpr, tmp, playback, capture, nctl;
+       int err, i, z, gpr, nctl;
+       const int playback = 10;
+       const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
+       const int tmp = 0x88;
        u32 ptr;
        emu10k1_fx8010_code_t *icode;
        emu10k1_fx8010_control_gpr_t *controls, *ctl;
@@ -1261,19 +1264,15 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
        strcpy(icode->name, "Audigy DSP code for ALSA");
        ptr = 0;
        nctl = 0;
-       playback = 10;
-       capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
        gpr = capture + 10;
-       tmp = 0x88;
 
        /* stop FX processor */
        snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
 
-       /* Wave Playback */
+       /* Wave Playback Volume */
        A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
        A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
-       snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr,
-                                       emu->revision == 4 ? 50 : 100);
+       snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
        gpr += 2;
 
        /* Wave Surround Playback */
@@ -1497,6 +1496,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
        gpr += 2;
 
+       /* Master volume for audigy2 */
+       if (emu->revision == 4) {
+               A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS));
+               A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
+               snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
+               gpr += 2;
+       }
+
        /* digital outputs */
        A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
        A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
@@ -1504,7 +1511,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
 
        /* analog speakers */
-       if (emu->audigy && emu->revision == 4) { /* audigy2 */
+       if (emu->revision == 4) { /* audigy2 */
                A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
        } else {
                A_PUT_STEREO_OUTPUT(A_EXTOUT_AC97_L, A_EXTOUT_AC97_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
index e5c041561da3a78910ab82053ccd983cef6f95b9..5781efaa46d1c1931be2cf1c765e4bd27ff36318 100644 (file)
@@ -423,6 +423,36 @@ static void snd_emu10k1_mixer_free_ac97(ac97_t *ac97)
        emu->ac97 = NULL;
 }
 
+/*
+ */
+static int remove_ctl(snd_card_t *card, const char *name)
+{
+       snd_ctl_elem_id_t id;
+       memset(&id, 0, sizeof(id));
+       strcpy(id.name, name);
+       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       return snd_ctl_remove_id(card, &id);
+}
+
+static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name)
+{
+       snd_ctl_elem_id_t sid;
+       memset(&sid, 0, sizeof(sid));
+       strcpy(sid.name, name);
+       sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       return snd_ctl_find_id(card, &sid);
+}
+
+static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
+{
+       snd_kcontrol_t *kctl = ctl_find(card, src);
+       if (kctl) {
+               strcpy(kctl->id.name, dst);
+               return 0;
+       }
+       return -ENOENT;
+}
+
 int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
 {
        ac97_t ac97;
@@ -430,7 +460,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
        snd_kcontrol_t *kctl;
        snd_card_t *card = emu->card;
 
-       if (!emu->APS) {
+       if (!emu->no_ac97) {
                memset(&ac97, 0, sizeof(ac97));
                ac97.write = snd_emu10k1_ac97_write;
                ac97.read = snd_emu10k1_ac97_read;
@@ -438,8 +468,33 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
                ac97.private_free = snd_emu10k1_mixer_free_ac97;
                if ((err = snd_ac97_mixer(emu->card, &ac97, &emu->ac97)) < 0)
                        return err;
+               if (emu->audigy && emu->revision == 4) {
+                       /* Master/PCM controls on ac97 of Audigy2 has no effect */
+                       /* FIXME: keep master volume/switch to be sure.
+                        * once after we check that they play really no roles,
+                        * they shall be removed.
+                        */
+                       rename_ctl(card, "Master Playback Switch", "AC97 Master Playback Switch");
+                       rename_ctl(card, "Master Playback Volume", "AC97 Master Playback Volume");
+                       /* pcm controls are removed */
+                       remove_ctl(card, "PCM Playback Switch");
+                       remove_ctl(card, "PCM Playback Volume");
+               }
        } else {
-               strcpy(emu->card->mixername, "EMU APS");
+               if (emu->APS)
+                       strcpy(emu->card->mixername, "EMU APS");
+               else if (emu->audigy)
+                       strcpy(emu->card->mixername, "SB Audigy");
+               else
+                       strcpy(emu->card->mixername, "Emu10k1");
+       }
+
+       if (emu->audigy && emu->revision == 4) {
+               /* Audigy2 and Audigy2 EX */
+               /* use the conventional names */
+               rename_ctl(card, "Wave Playback Volume", "PCM Playback Volume");
+               rename_ctl(card, "Wave Playback Volume", "PCM Capture Volume");
+               rename_ctl(card, "Wave Master Playback Volume", "Master Playback Volume");
        }
 
        if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
@@ -455,6 +510,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
        if ((err = snd_ctl_add(card, kctl)))
                return err;
 
+       /* intiailize the routing and volume table for each pcm playback stream */
        for (pcm = 0; pcm < 32; pcm++) {
                emu10k1_pcm_mixer_t *mix;
                int v;
@@ -474,21 +530,25 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
                mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
        }
        
-       if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
-               return -ENOMEM;
-       if ((err = snd_ctl_add(card, kctl)))
-               return err;
-       if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
-               return -ENOMEM;
-       if ((err = snd_ctl_add(card, kctl)))
-               return err;
+       if (! emu->APS) { /* FIXME: APS has these controls? */
+               /* sb live! and audigy */
+               if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
+                       return -ENOMEM;
+               if ((err = snd_ctl_add(card, kctl)))
+                       return err;
+               if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
+                       return -ENOMEM;
+               if ((err = snd_ctl_add(card, kctl)))
+                       return err;
+       }
 
        if (emu->audigy) {
                if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
                        return -ENOMEM;
                if ((err = snd_ctl_add(card, kctl)))
                        return err;
-       } else {
+       } else if (! emu->APS) {
+               /* sb live! */
                if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
                        return -ENOMEM;
                if ((err = snd_ctl_add(card, kctl)))
index b89c385003e05076f0cc886f11676d53cf0992ad..17595a41d7c3883b3575debf116855b318f3800e 100644 (file)
@@ -55,15 +55,13 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                if (status & IPR_CHANNELLOOP) {
                        int voice;
                        int voice_max = status & IPR_CHANNELNUMBERMASK;
-                       int voice_max_l;
                        u32 val;
                        emu10k1_voice_t *pvoice = emu->voices;
 
                        val = snd_emu10k1_ptr_read(emu, CLIPL, 0);
-                       voice_max_l = voice_max;
-                       if (voice_max_l >= 0x20)
-                               voice_max_l = 0x1f;
-                       for (voice = 0; voice <= voice_max_l; voice++) {
+                       for (voice = 0; voice <= voice_max; voice++) {
+                               if (voice == 0x20)
+                                       val = snd_emu10k1_ptr_read(emu, CLIPH, 0);
                                if (val & 1) {
                                        if (pvoice->use && pvoice->interrupt != NULL) {
                                                pvoice->interrupt(emu, pvoice);
@@ -75,21 +73,6 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                val >>= 1;
                                pvoice++;
                        }
-                       if (voice_max > 0x1f) {
-                               val = snd_emu10k1_ptr_read(emu, CLIPH, 0);
-                               for (; voice <= voice_max; voice++) {
-                                       if(val & 1) {
-                                               if (pvoice->use && pvoice->interrupt != NULL) {
-                                                       pvoice->interrupt(emu, pvoice);
-                                                       snd_emu10k1_voice_intr_ack(emu, voice);
-                                               } else {
-                                                       snd_emu10k1_voice_intr_disable(emu, voice);
-                                               }
-                                       }
-                                       val >>= 1;
-                                       pvoice++;
-                               }
-                       }
                        status &= ~IPR_CHANNELLOOP;
                }
                status &= ~IPR_CHANNELNUMBERMASK;
@@ -150,9 +133,27 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        status &= ~IPR_FXDSP;
                }
                if (status) {
-                       snd_printd(KERN_WARNING "emu10k1: unhandled interrupt: 0x%08x\n", status);
+                       unsigned int bits;
+                       snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+                       //make sure any interrupts we don't handle are disabled:
+                       bits = INTE_FXDSPENABLE |
+                               INTE_PCIERRORENABLE |
+                               INTE_VOLINCRENABLE |
+                               INTE_VOLDECRENABLE |
+                               INTE_MUTEENABLE |
+                               INTE_MICBUFENABLE |
+                               INTE_ADCBUFENABLE |
+                               INTE_EFXBUFENABLE |
+                               INTE_GPSPDIFENABLE |
+                               INTE_CDSPDIFENABLE |
+                               INTE_INTERVALTIMERENB |
+                               INTE_MIDITXENABLE |
+                               INTE_MIDIRXENABLE;
+                       if (emu->audigy)
+                               bits |= INTE_A_MIDITXENABLE2 | INTE_A_MIDIRXENABLE2;
+                       snd_emu10k1_intr_disable(emu, bits);
                }
-               outl(orig_status, emu->port + IPR); /* ack */
+               outl(orig_status, emu->port + IPR); /* ack all */
        }
        return IRQ_RETVAL(handled);
 }
index 6a58d534fc38a6876d23d6cb077ed3935d45202e..d82c4f50f418941e32600238e4e13554f71f90b1 100644 (file)
@@ -1002,7 +1002,7 @@ static int snd_intel8x0_pcm_open(snd_pcm_substream_t * substream, ichdev_t *ichd
        snd_pcm_runtime_t *runtime = substream->runtime;
        static unsigned int i, rates[] = {
                /* ATTENTION: these values depend on the definition in pcm.h! */
-               5512, 8000, 11025, 16000, 22050, 32000, 44100, 480000
+               5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000
        };
        int err;
 
@@ -1558,6 +1558,7 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
        { 0x1028, 0x0126, "Dell Optiplex GX260", AC97_TUNE_HP_ONLY },
        { 0x1734, 0x0088, "Fujitsu-Siemens D1522", AC97_TUNE_HP_ONLY },
        { 0x10f1, 0x2665, "Fujitsu-Siemens Celcius", AC97_TUNE_HP_ONLY },
+       { 0x110a, 0x0056, "Fujitsu-Siemens Scenic", AC97_TUNE_HP_ONLY },
        { 0x8086, 0x4d44, "Intel D850EMV2", AC97_TUNE_HP_ONLY },
        /* { 0x4144, 0x5360, "AMD64 Motherboard", AC97_TUNE_HP_ONLY }, */ /* FIXME: this seems invalid */
        { 0x1043, 0x80b0, "ASUS P4PE Mobo", AC97_TUNE_SWAP_SURROUND },
index 40fee06f48099239e7aba4b192898f24311fcdc9..5fd2443dfae16a92845243f42cb8eb99404b6853 100644 (file)
@@ -1535,9 +1535,14 @@ static snd_pcm_uframes_t
 snd_m3_pcm_pointer(snd_pcm_substream_t * subs)
 {
        m3_t *chip = snd_pcm_substream_chip(subs);
+       unsigned int ptr;
        m3_dma_t *s = (m3_dma_t*)subs->runtime->private_data;
        snd_assert(s != NULL, return 0);
-       return bytes_to_frames(subs->runtime, snd_m3_get_pointer(chip, s, subs));
+
+       spin_lock(&chip->reg_lock);
+       ptr = snd_m3_get_pointer(chip, s, subs);
+       spin_unlock(&chip->reg_lock);
+       return bytes_to_frames(subs->runtime, ptr);
 }
 
 
index e29ca6521f6ddd58a4f2c8c28c94b8b145739eff..4f0ce4d16d7dfb4245f1a81cc18bfd3d3fb26b98 100644 (file)
@@ -886,7 +886,7 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
                snd_ac97_set_rate(chip->ac97, AC97_PCM_LFE_DAC_RATE, runtime->rate);
                snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
        }
-       if (chip->chip_type == TYPE_VIA8233A)
+       if (chip->revision == VIA_REV_8233A)
                rbits = 0;
        else
                rbits = (0xfffff / 48000) * runtime->rate + ((0xfffff % 48000) * runtime->rate) / 48000;
@@ -928,7 +928,7 @@ static int snd_via8233_multi_prepare(snd_pcm_substream_t *substream)
        fmt = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? VIA_REG_MULTPLAY_FMT_16BIT : VIA_REG_MULTPLAY_FMT_8BIT;
        fmt |= runtime->channels << 4;
        outb(fmt, VIADEV_REG(viadev, OFS_MULTPLAY_FORMAT));
-       if (chip->chip_type == TYPE_VIA8233A)
+       if (chip->revision == VIA_REV_8233A)
                slots = 0;
        else {
                /* set sample number to slot 3, 4, 7, 8, 6, 9 (for VIA8233/C,8235) */
@@ -1108,7 +1108,7 @@ static int snd_via8233_multi_open(snd_pcm_substream_t * substream)
        if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0)
                return err;
        substream->runtime->hw.channels_max = 6;
-       if (chip->chip_type == TYPE_VIA8233A)
+       if (chip->revision == VIA_REV_8233A)
                snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels);
        return 0;
 }
index 114a624e52835ba92ab2a38677916df1516e4c79..f2d5fba37be6c89950fbef6bd5ba8899e24879e8 100644 (file)
@@ -66,15 +66,11 @@ static void snd_sf_clear(snd_sf_list_t *sflist);
 static int
 lock_preset(snd_sf_list_t *sflist, int nonblock)
 {
-       unsigned long flags;
-       spin_lock_irqsave(&sflist->lock, flags);
-       if (sflist->sf_locked && nonblock) {
-               spin_unlock_irqrestore(&sflist->lock, flags);
-               return -EBUSY;
-       }
-       spin_unlock_irqrestore(&sflist->lock, flags);
-       down(&sflist->presets_mutex);
-       sflist->sf_locked = 1;
+       if (nonblock) {
+               if (down_trylock(&sflist->presets_mutex))
+                       return -EBUSY;
+       } else 
+               down(&sflist->presets_mutex);
        return 0;
 }
 
@@ -86,7 +82,6 @@ static void
 unlock_preset(snd_sf_list_t *sflist)
 {
        up(&sflist->presets_mutex);
-       sflist->sf_locked = 0;
 }
 
 
@@ -1356,7 +1351,6 @@ snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
 
        init_MUTEX(&sflist->presets_mutex);
        spin_lock_init(&sflist->lock);
-       sflist->sf_locked = 0;
        sflist->memhdr = hdr;
 
        if (callback)
@@ -1403,7 +1397,7 @@ snd_soundfont_remove_samples(snd_sf_list_t *sflist)
 
 /*
  * Remove unlocked samples.
- * The soundcard should be silet before calling this function.
+ * The soundcard should be silent before calling this function.
  */
 int
 snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
index c14d5519e6667281cd599219618d3d58b13da132..55ab455950c0633c01184cd384e700010db2b8af 100644 (file)
@@ -2297,6 +2297,14 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
                         */
                        fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE;
                }
+
+               /* workaround for M-Audio Audiophile USB */
+               if (dev->descriptor.idVendor == 0x0763 &&
+                   dev->descriptor.idProduct == 0x2003) {
+                       /* doesn't set the sample rate attribute, but supports it */
+                       fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
+               }
+
                /*
                 * plantronics headset and Griffin iMic have set adaptive-in
                 * although it's really not...