summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@suse.cz>2003-09-25 20:23:48 +0200
committerJaroslav Kysela <perex@suse.cz>2003-09-25 20:23:48 +0200
commitdf8dbda8182d22c1848dc127c47e72c5319cd83b (patch)
tree3782f90598def7c208a23c9ccae11871888a9513
parente1af761fbc988ecb04ae7e8c76062f137915f331 (diff)
parent5f29cff974c4cf79854a1706fe8ec57d24b9498a (diff)
Merged ALSA with the latest Linux code.
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt21
-rw-r--r--Documentation/sound/alsa/OSS-Emulation.txt9
-rw-r--r--include/sound/ac97_codec.h41
-rw-r--r--include/sound/asound.h3
-rw-r--r--include/sound/emu10k1.h2
-rw-r--r--include/sound/pcm_oss.h4
-rw-r--r--sound/core/hwdep.c23
-rw-r--r--sound/core/info.c18
-rw-r--r--sound/core/ioctl32/pcm32.c1
-rw-r--r--sound/core/memalloc.c1
-rw-r--r--sound/core/oss/pcm_oss.c82
-rw-r--r--sound/core/oss/pcm_plugin.c1
-rw-r--r--sound/core/oss/pcm_plugin.h4
-rw-r--r--sound/core/pcm_native.c10
-rw-r--r--sound/core/sound.c1
-rw-r--r--sound/drivers/dummy.c1
-rw-r--r--sound/i2c/other/ak4xxx-adda.c28
-rw-r--r--sound/isa/cs423x/cs4236.c2
-rw-r--r--sound/isa/cs423x/pc98.c2
-rw-r--r--sound/pci/Kconfig14
-rw-r--r--sound/pci/ac97/ac97_codec.c270
-rw-r--r--sound/pci/ac97/ac97_local.h2
-rw-r--r--sound/pci/ac97/ac97_patch.c70
-rw-r--r--sound/pci/ac97/ac97_proc.c26
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c12
-rw-r--r--sound/pci/cs46xx/dsp_spos.c6
-rw-r--r--sound/pci/emu10k1/emu10k1.c5
-rw-r--r--sound/pci/emu10k1/emufx.c34
-rw-r--r--sound/pci/emu10k1/emupcm.c5
-rw-r--r--sound/pci/es1968.c68
-rw-r--r--sound/pci/ice1712/aureon.c4
-rw-r--r--sound/pci/ice1712/ice1724.c39
-rw-r--r--sound/pci/ice1712/revo.c5
-rw-r--r--sound/pci/intel8x0.c56
-rw-r--r--sound/pci/trident/trident_main.c61
-rw-r--r--sound/pci/via82xx.c73
-rw-r--r--sound/pcmcia/vx/vx_entry.c2
-rw-r--r--sound/ppc/daca.c8
-rw-r--r--sound/ppc/pmac.c2
-rw-r--r--sound/ppc/tumbler.c64
-rw-r--r--sound/usb/usbaudio.c16
-rw-r--r--sound/usb/usbmixer.c3
-rw-r--r--sound/usb/usbquirks.h13
43 files changed, 768 insertions, 344 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index d3b5d2793175..948cc234d41f 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -449,7 +449,8 @@ Module parameters
pcm_substreams_c - capture channels (1-8, default=0)
clock - clock (0 = auto-detection)
use_pm - support the power-management (0 = off, 1 = on,
- 2 = auto)
+ 2 = auto (default))
+ enable_mpu - enable MPU401 (0 = off, 1 = on, 2 = auto (default))
Module supports up to 8 cards and autoprobe.
@@ -992,7 +993,7 @@ Module parameters
[VIA686A/686B only]
ac97_clock - AC'97 codec clock base (default 48000Hz)
dxs_support - support DXS channels,
- 0 = auto (default), 1 = enable, 2 = disable,
+ 0 = auto (defalut), 1 = enable, 2 = disable,
3 = 48k only
[VIA8233/C,8235 only]
@@ -1005,13 +1006,15 @@ Module parameters
assigned under 15. You might also upgrade your BIOS.
Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound)
- channels as the first PCM. With this device, up to 4
- streams can be played at the same time. On some motherboards,
- these channels don't work properly due to the bug of BIOS.
- If you experience that the playback on this PCM is noisy,
- try to specify dxs_support option to 2 or 3. In most cases
- dxs_support=3 would suffice, so you can keep the multi-play
- capability.
+ channels as the first PCM. On these channels, up to 4
+ streams can be played at the same time.
+ As default (dxs_support = 0), 48k fixed rate is chosen since
+ the output is often noisy except for 48k on some mother
+ boards due to the bug of BIOS.
+ Please try once dxs_support=1 and if it works on other
+ sample rates, please let us know the PCI subsystem
+ vendor/device id's (output of "lspci -nv").
+ If it doesn't work, use dxs_support=3 or dxs_support=2.
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
additonally. The mpu_port option is for VIA686 chips only.
diff --git a/Documentation/sound/alsa/OSS-Emulation.txt b/Documentation/sound/alsa/OSS-Emulation.txt
index 9837b8bbffd6..489a37948de8 100644
--- a/Documentation/sound/alsa/OSS-Emulation.txt
+++ b/Documentation/sound/alsa/OSS-Emulation.txt
@@ -152,6 +152,9 @@ available:
direct don't use plugins
block force block open mode
non-block force non-block open mode
+ whole-frag write only whole fragments (optimization affecting
+ playback only)
+ no-silence do not fill silence ahead to avoid clicks
The disable option is useful when one stream direction (playback or
capture) is not handled correctly by the application although the
@@ -185,6 +188,12 @@ for OSS devices, define like the following:
options snd-pcm-oss nonblock_open=1
+The whole-frag and no-silence commands have been added recently.
+Both commands are for optimization use only. The former command
+specifies to invoke the write transfer only when the whole fragment is
+filled. The latter stops writing the silence data ahead
+automatically. Both are disabled as default.
+
You can check the currently defined configuration by reading the proc
file. The read image can be sent to the proc file again, hence you
can save the current configuration
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index e41e774307ee..b73755aa7f3b 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -214,10 +214,46 @@
#define AC97_CXR_SPDIF_AC3 0x2
/* specific - ALC */
+#define AC97_ALC650_SPDIF_INPUT_STATUS1 0x60
+/* S/PDIF input status 1 bit defines */
+#define AC97_ALC650_PRO 0x0001 /* Professional status */
+#define AC97_ALC650_NAUDIO 0x0002 /* Non audio stream */
+#define AC97_ALC650_COPY 0x0004 /* Copyright status */
+#define AC97_ALC650_PRE 0x0038 /* Preemphasis status */
+#define AC97_ALC650_PRE_SHIFT 3
+#define AC97_ALC650_MODE 0x00C0 /* Preemphasis status */
+#define AC97_ALC650_MODE_SHIFT 6
+#define AC97_ALC650_CC_MASK 0x7f00 /* Category Code mask */
+#define AC97_ALC650_CC_SHIFT 8
+#define AC97_ALC650_L 0x8000 /* Generation Level status */
+
+#define AC97_ALC650_SPDIF_INPUT_STATUS2 0x62
+/* S/PDIF input status 2 bit defines */
+#define AC97_ALC650_SOUCE_MASK 0x000f /* Source number */
+#define AC97_ALC650_CHANNEL_MASK 0x00f0 /* Channel number */
+#define AC97_ALC650_CHANNEL_SHIFT 4
+#define AC97_ALC650_SPSR_MASK 0x0f00 /* S/PDIF Sample Rate bits */
+#define AC97_ALC650_SPSR_SHIFT 8
+#define AC97_ALC650_SPSR_44K 0x0000 /* Use 44.1kHz Sample rate */
+#define AC97_ALC650_SPSR_48K 0x0200 /* Use 48kHz Sample rate */
+#define AC97_ALC650_SPSR_32K 0x0300 /* Use 32kHz Sample rate */
+#define AC97_ALC650_CLOCK_ACCURACY 0x3000 /* Clock accuracy */
+#define AC97_ALC650_CLOCK_SHIFT 12
+#define AC97_ALC650_CLOCK_LOCK 0x4000 /* Clock locked status */
+#define AC97_ALC650_V 0x8000 /* Validity status */
+
#define AC97_ALC650_SURR_DAC_VOL 0x64
#define AC97_ALC650_LFE_DAC_VOL 0x66
-#define AC97_ALC650_MULTICH 0x6a
-#define AC97_ALC650_CLOCK 0x7a
+#define AC97_ALC650_UNKNOWN1 0x68
+#define AC97_ALC650_MULTICH 0x6a
+#define AC97_ALC650_UNKNOWN2 0x6c
+#define AC97_ALC650_REVISION 0x6e
+#define AC97_ALC650_UNKNOWN3 0x70
+#define AC97_ALC650_UNKNOWN4 0x72
+#define AC97_ALC650_MISC 0x74
+#define AC97_ALC650_GPIO_SETUP 0x76
+#define AC97_ALC650_GPIO_STATUS 0x78
+#define AC97_ALC650_CLOCK 0x7a
/* specific - Yamaha YMF753 */
#define AC97_YMF753_DIT_CTRL2 0x66 /* DIT Control 2 */
@@ -248,6 +284,7 @@
#define AC97_AD_MULTI (1<<1) /* Analog Devices - multi codecs */
#define AC97_CS_SPDIF (1<<2) /* Cirrus Logic uses funky SPDIF */
#define AC97_CX_SPDIF (1<<3) /* Conexant's spdif interface */
+#define AC97_STEREO_MUTES (1<<4) /* has stereo mute bits */
/* rates indexes */
#define AC97_RATES_FRONT_DAC 0
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 99547ab3e252..b68826ba1904 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -106,9 +106,10 @@ enum sndrv_hwdep_iface {
SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
+ SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
/* Don't forget to change the following: */
- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_MIXART,
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USX2Y,
};
struct sndrv_hwdep_info {
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 1fbd9f3fa82b..78078e874480 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1152,6 +1152,8 @@ int snd_emu10k1_proc_init(emu10k1_t * emu);
#define FXBUS_MIDI_RIGHT 0x05
#define FXBUS_PCM_CENTER 0x06
#define FXBUS_PCM_LFE 0x07
+#define FXBUS_PT_LEFT 20
+#define FXBUS_PT_RIGHT 21
#define FXBUS_MIDI_REVERB 0x0c
#define FXBUS_MIDI_CHORUS 0x0d
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index ca4922049423..631c9faf7dcf 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -51,11 +51,11 @@ typedef struct _snd_pcm_oss_runtime {
unsigned int subdivision; /* requested subdivision */
size_t period_bytes; /* requested period size */
unsigned int periods;
- size_t buffer_bytes; /* requested period size */
+ size_t buffer_bytes; /* requested buffer size */
size_t bytes; /* total # bytes processed */
size_t mmap_bytes;
char *buffer; /* vmallocated period */
- size_t buffer_used; /* used length from buffer */
+ size_t buffer_used; /* used length from period buffer */
snd_pcm_plugin_t *plugin_first;
snd_pcm_plugin_t *plugin_last;
unsigned int prev_hw_ptr_interrupt;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index f7191fc7c776..6594e8606103 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -97,14 +97,19 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
cardnum %= SNDRV_CARDS;
device %= SNDRV_MINOR_HWDEPS;
hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device];
+ if (hw == NULL)
+ return -ENODEV;
- snd_assert(hw != NULL, return -ENODEV);
if (!hw->ops.open)
return -ENXIO;
#ifdef CONFIG_SND_OSSEMUL
if (major == SOUND_MAJOR && hw->oss_type < 0)
return -ENXIO;
#endif
+
+ if (!try_module_get(hw->card->module))
+ return -EFAULT;
+
init_waitqueue_entry(&wait, current);
add_wait_queue(&hw->open_wait, &wait);
down(&hw->open_mutex);
@@ -133,10 +138,18 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
set_current_state(TASK_RUNNING);
remove_wait_queue(&hw->open_wait, &wait);
if (err >= 0) {
- file->private_data = hw;
- hw->used++;
+ err = snd_card_file_add(hw->card, file);
+ if (err >= 0) {
+ file->private_data = hw;
+ hw->used++;
+ } else {
+ if (hw->ops.release)
+ hw->ops.release(hw, file);
+ }
}
up(&hw->open_mutex);
+ if (err < 0)
+ module_put(hw->card->module);
return err;
}
@@ -151,8 +164,10 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
}
if (hw->used > 0)
hw->used--;
+ snd_card_file_remove(hw->card, file);
up(&hw->open_mutex);
- return -ENXIO;
+ module_put(hw->card->module);
+ return err;
}
static unsigned int snd_hwdep_poll(struct file * file, poll_table * wait)
diff --git a/sound/core/info.c b/sound/core/info.c
index b3df8eace959..25c2aab50548 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -180,7 +180,7 @@ static ssize_t snd_info_entry_read(struct file *file, char *buffer,
snd_info_private_data_t *data;
struct snd_info_entry *entry;
snd_info_buffer_t *buf;
- long size = 0, size1;
+ long size = 0;
data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
snd_assert(data != NULL, return -ENXIO);
@@ -192,10 +192,7 @@ static ssize_t snd_info_entry_read(struct file *file, char *buffer,
return -EIO;
if (file->f_pos >= (long)buf->size)
return 0;
- size = buf->size < count ? buf->size : count;
- size1 = buf->size - file->f_pos;
- if (size1 < size)
- size = size1;
+ size = min(count, buf->size - file->f_pos);
if (copy_to_user(buffer, buf->buffer + file->f_pos, size))
return -EFAULT;
file->f_pos += size;
@@ -205,8 +202,6 @@ static ssize_t snd_info_entry_read(struct file *file, char *buffer,
return entry->c.ops->read(entry,
data->file_private_data,
file, buffer, count);
- if (size > 0)
- file->f_pos += size;
break;
}
return size;
@@ -218,7 +213,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char *buffer,
snd_info_private_data_t *data;
struct snd_info_entry *entry;
snd_info_buffer_t *buf;
- long size = 0, size1;
+ long size = 0;
data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
snd_assert(data != NULL, return -ENXIO);
@@ -232,10 +227,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char *buffer,
return -EINVAL;
if (file->f_pos >= (long)buf->len)
return -ENOMEM;
- size = buf->len < count ? buf->len : count;
- size1 = buf->len - file->f_pos;
- if (size1 < size)
- size = size1;
+ size = min(count, buf->len - file->f_pos);
if (copy_from_user(buf->buffer + file->f_pos, buffer, size))
return -EFAULT;
if ((long)buf->size < file->f_pos + size)
@@ -247,8 +239,6 @@ static ssize_t snd_info_entry_write(struct file *file, const char *buffer,
return entry->c.ops->write(entry,
data->file_private_data,
file, buffer, count);
- if (size > 0)
- file->f_pos += size;
break;
}
return size;
diff --git a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c
index 0701b8229bf0..e259f49cc04b 100644
--- a/sound/core/ioctl32/pcm32.c
+++ b/sound/core/ioctl32/pcm32.c
@@ -421,6 +421,7 @@ enum {
struct ioctl32_mapper pcm_mappers[] = {
MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION),
MAP_COMPAT(SNDRV_PCM_IOCTL_INFO),
+ MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
{ SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
{ SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
{ SNDRV_PCM_IOCTL_HW_REFINE_OLD32, AP(pcm_hw_refine_old) },
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 0a17b04c3bf6..351951e3814a 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -22,7 +22,6 @@
*/
#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index e5272ee9527b..dc64f350656b 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -27,7 +27,6 @@
#endif
#include <sound/driver.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
@@ -938,46 +937,68 @@ static int snd_pcm_oss_post(snd_pcm_oss_file_t *pcm_oss_file)
return 0;
}
+static int snd_pcm_oss_sync1(snd_pcm_substream_t *substream, size_t size)
+{
+ snd_pcm_runtime_t *runtime;
+ ssize_t result = 0;
+ wait_queue_t wait;
+
+ runtime = substream->runtime;
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&runtime->sleep, &wait);
+ while (1) {
+ result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
+ if (result > 0) {
+ runtime->oss.buffer_used = 0;
+ result = 0;
+ break;
+ }
+ if (result != 0 && result != -EAGAIN)
+ break;
+ result = 0;
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ result = -ERESTARTSYS;
+ break;
+ }
+ set_current_state(TASK_RUNNING);
+ }
+ remove_wait_queue(&runtime->sleep, &wait);
+ return result;
+}
+
static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
{
int err = 0;
unsigned int saved_f_flags;
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- ssize_t result;
- wait_queue_t wait;
+ size_t size;
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream != NULL) {
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
-
runtime = substream->runtime;
if (runtime->oss.buffer_used > 0) {
snd_pcm_format_set_silence(runtime->format,
runtime->oss.buffer + runtime->oss.buffer_used,
bytes_to_samples(runtime, runtime->oss.period_bytes - runtime->oss.buffer_used));
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&runtime->sleep, &wait);
- while (1) {
- result = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
- if (result > 0) {
- runtime->oss.buffer_used = 0;
- break;
- }
- if (result != 0 && result != -EAGAIN)
- break;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- if (signal_pending(current)) {
- result = -ERESTARTSYS;
- break;
- }
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&runtime->sleep, &wait);
- if (result < 0)
- return result;
+ err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
+ if (err < 0)
+ return err;
+ }
+ size = runtime->control->appl_ptr % runtime->period_size;
+ if (size > 0) {
+ size = runtime->period_size - size;
+ size *= runtime->channels;
+ snd_pcm_format_set_silence(runtime->format,
+ runtime->oss.buffer,
+ size);
+ err = snd_pcm_oss_sync1(substream, samples_to_bytes(runtime, size));
+ if (err < 0)
+ return err;
}
saved_f_flags = substream->ffile->f_flags;
substream->ffile->f_flags &= ~O_NONBLOCK;
@@ -1395,6 +1416,10 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str
}
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+ if (err == -EPIPE || err == -ESTRPIPE) {
+ err = 0;
+ delay = 0;
+ }
} else {
err = snd_pcm_oss_capture_position_fixup(substream, &delay);
}
@@ -1455,7 +1480,12 @@ static int snd_pcm_oss_get_space(snd_pcm_oss_file_t *pcm_oss_file, int stream, s
} else {
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);
- avail = runtime->buffer_size - avail;
+ if (err == -EPIPE || err == -ESTRPIPE) {
+ avail = runtime->buffer_size;
+ err = 0;
+ } else {
+ avail = runtime->buffer_size - avail;
+ }
} else {
err = snd_pcm_oss_capture_position_fixup(substream, &avail);
}
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 098e652eec59..6b519fbcad01 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -646,6 +646,7 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug,
nchannels = format->channels;
snd_assert(plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || format->channels <= 1, return -ENXIO);
for (channel = 0; channel < nchannels; channel++, v++) {
+ v->frames = count;
v->enabled = 1;
v->wanted = (stream == SNDRV_PCM_STREAM_CAPTURE);
v->area.addr = buf;
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 94db5495ea2d..342ec09640d2 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -243,9 +243,9 @@ void zero_channel(snd_pcm_plugin_t *plugin,
size_t samples);
#ifdef PLUGIN_DEBUG
-#define pdprintf( args... ) printk( "plugin: " ##args)
+#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args)
#else
-#define pdprintf( args... ) { ; }
+#define pdprintf( fmt, args... )
#endif
#endif /* __PCM_PLUGIN_H */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index bc2e16a4f6a3..4093a54cff63 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -20,7 +20,6 @@
*/
#include <sound/driver.h>
-#include <linux/version.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/slab.h>
@@ -2791,7 +2790,8 @@ static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, uns
return NOPAGE_OOM;
runtime = substream->runtime;
page = virt_to_page(runtime->status);
- get_page(page);
+ if (!PageReserved(page))
+ get_page(page);
return page;
}
@@ -2828,7 +2828,8 @@ static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, un
return NOPAGE_OOM;
runtime = substream->runtime;
page = virt_to_page(runtime->control);
- get_page(page);
+ if (!PageReserved(page))
+ get_page(page);
return page;
}
@@ -2893,7 +2894,8 @@ static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig
vaddr = runtime->dma_area + offset;
page = virt_to_page(vaddr);
}
- get_page(page);
+ if (!PageReserved(page))
+ get_page(page);
return page;
}
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 3d8b50d9d04b..34d5b88dbcdb 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -20,7 +20,6 @@
*/
#include <sound/driver.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 991d593f127b..2fe3e78eb8d0 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -19,7 +19,6 @@
*/
#include <sound/driver.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 981ae60848b5..92174ded630f 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -84,12 +84,14 @@ void snd_akm4xxx_reset(akm4xxx_t *ak, int state)
/* FIXME: needed for ak4529? */
break;
case SND_AK4355:
- snd_akm4xxx_write(ak, 0, 0x01, state ? 0x02 : 0x01);
- if (state)
+ if (state) {
+ snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
return;
- for (reg = 0x00; reg < 0x0a; reg++)
+ }
+ for (reg = 0x00; reg < 0x0b; reg++)
if (reg != 0x01)
snd_akm4xxx_write(ak, 0, reg, snd_akm4xxx_get(ak, 0, reg));
+ snd_akm4xxx_write(ak, 0, 0x01, 0x01); /* un-reset, unmute */
break;
case SND_AK4381:
for (chip = 0; chip < ak->num_dacs/2; chip++) {
@@ -151,8 +153,8 @@ void snd_akm4xxx_init(akm4xxx_t *ak)
static unsigned char inits_ak4355[] = {
0x01, 0x02, /* 1: reset and soft-mute */
0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */
- // 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */
- 0x02, 0x2e,
+ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */
+ // 0x02, 0x2e, /* quad speed */
0x03, 0x01, /* 3: de-emphasis off */
0x04, 0x00, /* 4: LOUT1 volume muted */
0x05, 0x00, /* 5: ROUT1 volume muted */
@@ -166,8 +168,8 @@ void snd_akm4xxx_init(akm4xxx_t *ak)
};
static unsigned char inits_ak4381[] = {
0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */
- // 0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */
- 0x01, 0x12,
+ 0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */
+ // 0x01, 0x12, /* quad speed */
0x02, 0x00, /* 2: DZF disabled */
0x03, 0x00, /* 3: LATT 0 */
0x04, 0x00, /* 4: RATT 0 */
@@ -340,7 +342,7 @@ static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
int snd_akm4xxx_build_controls(akm4xxx_t *ak)
{
- unsigned int idx;
+ unsigned int idx, num_emphs;
int err;
for (idx = 0; idx < ak->num_dacs; ++idx) {
@@ -382,7 +384,7 @@ int snd_akm4xxx_build_controls(akm4xxx_t *ak)
snd_kcontrol_t ctl;
memset(&ctl, 0, sizeof(ctl));
strcpy(ctl.id.name, "ADC Volume");
- ctl.id.index = idx;
+ ctl.id.index = idx + ak->idx_offset * 2;
ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
ctl.count = 1;
ctl.info = snd_akm4xxx_volume_info;
@@ -394,7 +396,7 @@ int snd_akm4xxx_build_controls(akm4xxx_t *ak)
return err;
memset(&ctl, 0, sizeof(ctl));
strcpy(ctl.id.name, "IPGA Analog Capture Volume");
- ctl.id.index = idx;
+ ctl.id.index = idx + ak->idx_offset * 2;
ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
ctl.count = 1;
ctl.info = snd_akm4xxx_ipga_gain_info;
@@ -405,7 +407,11 @@ int snd_akm4xxx_build_controls(akm4xxx_t *ak)
if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
return err;
}
- for (idx = 0; idx < ak->num_dacs/2; idx++) {
+ if (ak->type == SND_AK4355)
+ num_emphs = 1;
+ else
+ num_emphs = ak->num_dacs / 2;
+ for (idx = 0; idx < num_emphs; idx++) {
snd_kcontrol_t ctl;
memset(&ctl, 0, sizeof(ctl));
strcpy(ctl.id.name, "Deemphasis");
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 31786001367e..6a85c98c5405 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -525,7 +525,7 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
chip->port,
irq[dev],
dma1[dev]);
- if (dma1[dev] >= 0)
+ if (dma2[dev] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/isa/cs423x/pc98.c b/sound/isa/cs423x/pc98.c
index ae627f74aad6..0d7787bc4767 100644
--- a/sound/isa/cs423x/pc98.c
+++ b/sound/isa/cs423x/pc98.c
@@ -400,7 +400,7 @@ static int __init snd_card_pc98_probe(int dev)
chip->port,
irq[dev],
dma1[dev]);
- if (dma1[dev] >= 0)
+ if (dma2[dev] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 770febfeb23a..39d4f1853439 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -17,7 +17,7 @@ config SND_AZT3328
config SND_CS46XX
tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
- depends on SND && SOUND_GAMEPORT
+ depends on SND && GAMEPORT
help
Say 'Y' or 'M' to include support for Cirrus Logic CS4610 / CS4612 /
CS4614 / CS4615 / CS4622 / CS4624 / CS4630 / CS4280 chips.
@@ -30,7 +30,7 @@ config SND_CS46XX_NEW_DSP
config SND_CS4281
tristate "Cirrus Logic (Sound Fusion) CS4281"
- depends on SND && SOUND_GAMEPORT
+ depends on SND && GAMEPORT
help
Say 'Y' or 'M' to include support for Cirrus Logic CS4281.
@@ -83,7 +83,7 @@ config SND_HDSP
config SND_TRIDENT
tristate "Trident 4D-Wave DX/NX; SiS 7018"
- depends on SND && SOUND_GAMEPORT
+ depends on SND && GAMEPORT
help
Say 'Y' or 'M' to include support for Trident 4D-Wave DX/NX and
SiS 7018 soundcards.
@@ -110,20 +110,20 @@ config SND_CMIPCI
config SND_ENS1370
tristate "(Creative) Ensoniq AudioPCI 1370"
- depends on SND && SOUND_GAMEPORT
+ depends on SND && GAMEPORT
help
Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1370.
config SND_ENS1371
tristate "(Creative) Ensoniq AudioPCI 1371/1373"
- depends on SND && SOUND_GAMEPORT
+ depends on SND && GAMEPORT
help
Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1371 and
Sound Blaster PCI 64 or 128 soundcards.
config SND_ES1938
tristate "ESS ES1938/1946/1969 (Solo-1)"
- depends on SND && SOUND_GAMEPORT
+ depends on SND && GAMEPORT
help
Say 'Y' or 'M' to include support for ESS Solo-1 (ES1938, ES1946, ES1969)
soundcard.
@@ -173,7 +173,7 @@ config SND_INTEL8X0
config SND_SONICVIBES
tristate "S3 SonicVibes"
- depends on SND && SOUND_GAMEPORT
+ depends on SND && GAMEPORT
help
Say 'Y' or 'M' to include support for S3 SonicVibes based soundcards.
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index c857cca5d22f..780bff32137e 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -64,7 +64,7 @@ static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
{ 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL },
{ 0x41445300, 0xffffff00, "Analog Devices", NULL, NULL },
{ 0x414c4300, 0xffffff00, "Realtek", NULL, NULL },
-{ 0x414c4700, 0xffffff00, "Avance Logic", NULL, NULL },
+{ 0x414c4700, 0xffffff00, "Realtek", NULL, NULL },
{ 0x434d4900, 0xffffff00, "C-Media Electronics", NULL, NULL },
{ 0x43525900, 0xffffff00, "Cirrus Logic", NULL, NULL },
{ 0x43585400, 0xffffff00, "Conexant", NULL, NULL },
@@ -109,6 +109,9 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4320, 0xfffffff0, "RL5383", NULL, NULL },
{ 0x414c4710, 0xfffffff0, "ALC200/200P", NULL, NULL },
{ 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL },
+{ 0x414c4721, 0xfffffff0, "ALC650D", patch_alc650, NULL },
+{ 0x414c4722, 0xfffffff0, "ALC650E", patch_alc650, NULL },
+{ 0x414c4723, 0xfffffff0, "ALC650F", patch_alc650, NULL },
{ 0x414c4730, 0xffffffff, "ALC101", NULL, NULL },
{ 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL },
{ 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL },
@@ -545,7 +548,7 @@ int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontr
#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_double, \
.get = snd_ac97_get_double, .put = snd_ac97_put_double, \
- .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) }
+ .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
static int snd_ac97_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
@@ -599,16 +602,6 @@ static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
(val1 << shift_left) | (val2 << shift_right));
}
-static const snd_kcontrol_new_t snd_ac97_controls_master[2] = {
-AC97_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1),
-AC97_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1)
-};
-
-static const snd_kcontrol_new_t snd_ac97_controls_headphone[2] = {
-AC97_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),
-AC97_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)
-};
-
static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {
AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
@@ -635,43 +628,17 @@ AC97_SINGLE("Mic Playback Volume", AC97_MIC, 0, 15, 1),
AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0)
};
-static const snd_kcontrol_new_t snd_ac97_controls_line[2] = {
-AC97_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1),
-AC97_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1)
-};
-
-static const snd_kcontrol_new_t snd_ac97_controls_cd[2] = {
-AC97_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1),
-AC97_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1)
-};
-
-static const snd_kcontrol_new_t snd_ac97_controls_video[2] = {
-AC97_SINGLE("Video Playback Switch", AC97_VIDEO, 15, 1, 1),
-AC97_DOUBLE("Video Playback Volume", AC97_VIDEO, 8, 0, 31, 1)
-};
-
-static const snd_kcontrol_new_t snd_ac97_controls_aux[2] = {
-AC97_SINGLE("Aux Playback Switch", AC97_AUX, 15, 1, 1),
-AC97_DOUBLE("Aux Playback Volume", AC97_AUX, 8, 0, 31, 1)
-};
-
-static const snd_kcontrol_new_t snd_ac97_controls_pcm[2] = {
-AC97_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1),
-AC97_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1)
-};
-
-static const snd_kcontrol_new_t snd_ac97_controls_capture[3] = {
-{
+static const snd_kcontrol_new_t snd_ac97_control_capture_src = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.info = snd_ac97_info_mux,
.get = snd_ac97_get_mux,
.put = snd_ac97_put_mux,
-},
-AC97_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1),
-AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0)
};
+static const snd_kcontrol_new_t snd_ac97_control_capture_vol =
+AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0);
+
static const snd_kcontrol_new_t snd_ac97_controls_mic_capture[2] = {
AC97_SINGLE("Mic Capture Switch", AC97_REC_GAIN_MIC, 15, 1, 1),
AC97_SINGLE("Mic Capture Volume", AC97_REC_GAIN_MIC, 0, 15, 0)
@@ -717,11 +684,6 @@ AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
};
-static const snd_kcontrol_new_t snd_ac97_sigmatel_surround[2] = {
-AC97_SINGLE("Sigmatel Surround Playback Switch", AC97_HEADPHONE, 15, 1, 1),
-AC97_DOUBLE("Sigmatel Surround Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)
-};
-
static const snd_kcontrol_new_t snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);
@@ -899,17 +861,23 @@ const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
},
};
-#define AD18XX_PCM_BITS(xname, codec, shift, mask) \
+#define AD18XX_PCM_BITS(xname, codec, lshift, rshift, mask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \
.get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \
- .private_value = codec | (shift << 8) | (mask << 16) }
+ .private_value = (codec) | ((lshift) << 8) | ((rshift) << 12) | ((mask) << 24) }
static int snd_ac97_ad18xx_pcm_info_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
- int mask = (kcontrol->private_value >> 16) & 0xff;
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ int mask = (kcontrol->private_value >> 16) & 0x0f;
+ int lshift = (kcontrol->private_value >> 8) & 0x0f;
+ int rshift = (kcontrol->private_value >> 12) & 0x0f;
uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
+ if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES))
+ uinfo->count = 2;
+ else
+ uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask;
return 0;
@@ -919,10 +887,13 @@ static int snd_ac97_ad18xx_pcm_get_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3;
- int shift = (kcontrol->private_value >> 8) & 0xff;
+ int lshift = (kcontrol->private_value >> 8) & 0x0f;
+ int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff;
- ucontrol->value.integer.value[0] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> shift) & mask);
+ ucontrol->value.integer.value[0] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> lshift) & mask);
+ if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES))
+ ucontrol->value.integer.value[1] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> rshift) & mask);
return 0;
}
@@ -930,12 +901,18 @@ static int snd_ac97_ad18xx_pcm_put_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3;
- int shift = (kcontrol->private_value >> 8) & 0xff;
+ int lshift = (kcontrol->private_value >> 8) & 0x0f;
+ int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff;
- unsigned short val;
+ unsigned short val, valmask;
- val = mask - (ucontrol->value.integer.value[0] & mask);
- return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, mask << shift, val << shift);
+ val = (mask - (ucontrol->value.integer.value[0] & mask)) << lshift;
+ valmask = mask << lshift;
+ if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES)) {
+ val |= (mask - (ucontrol->value.integer.value[1] & mask)) << rshift;
+ valmask |= mask << rshift;
+ }
+ return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, valmask, val);
}
#define AD18XX_PCM_VOLUME(xname, codec) \
@@ -976,22 +953,23 @@ static int snd_ac97_ad18xx_pcm_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele
}
static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_pcm[2] = {
-AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 1),
+AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 7, 1),
AD18XX_PCM_VOLUME("PCM Playback Volume", 0)
};
static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_surround[2] = {
-AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 1),
+AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 7, 1),
AD18XX_PCM_VOLUME("Surround Playback Volume", 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_center[2] = {
-AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 1),
-AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 31)
+AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 15, 1),
+AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 8, 31)
};
-static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[1] = {
-AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31)
+static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[2] = {
+AD18XX_PCM_BITS("LFE Playback Switch", 2, 7, 7, 1),
+AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 0, 31)
};
/*
@@ -1144,11 +1122,79 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97
return snd_ctl_new1(&template, ac97);
}
+/*
+ * create mute switch(es) for normal stereo controls
+ */
+static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac97)
+{
+ snd_kcontrol_t *kctl;
+ int stereo = 0;
+
+ if (ac97->flags & AC97_STEREO_MUTES) {
+ /* check whether both mute bits work */
+ unsigned short val, val1;
+ val = snd_ac97_read(ac97, reg);
+ val1 = val | 0x8080;
+ snd_ac97_write(ac97, reg, val1);
+ if (val1 == snd_ac97_read(ac97, reg))
+ stereo = 1;
+ snd_ac97_write(ac97, reg, val);
+ }
+ if (stereo) {
+ snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
+ tmp.index = ac97->num;
+ kctl = snd_ctl_new1(&tmp, ac97);
+ } else {
+ snd_kcontrol_new_t tmp = AC97_SINGLE(name, reg, 15, 1, 1);
+ tmp.index = ac97->num;
+ kctl = snd_ctl_new1(&tmp, ac97);
+ }
+ return snd_ctl_add(card, kctl);
+}
+
+/*
+ * create volumes for normal stereo controls
+ */
+static int snd_ac97_cvol_new(snd_card_t *card, char *name, int reg, unsigned int max, ac97_t *ac97)
+{
+ int err;
+ snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 8, 0, (unsigned int)max, 1);
+ tmp.index = ac97->num;
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&tmp, ac97))) < 0)
+ return err;
+ snd_ac97_write_cache(ac97, reg,
+ ((ac97->flags & AC97_STEREO_MUTES) ? 0x8080 : 0x8000) |
+ (unsigned short)max | ((unsigned short)max << 8));
+ return 0;
+}
+
+/*
+ * create mute-switch and volumes for normal stereo controls
+ */
+static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, int check_res, ac97_t *ac97)
+{
+ int err;
+ char name[44];
+ unsigned char max;
+
+ sprintf(name, "%s Switch", pfx);
+ if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0)
+ return err;
+ sprintf(name, "%s Volume", pfx);
+ if (check_res)
+ snd_ac97_change_volume_params1(ac97, reg, &max);
+ else
+ max = 31; /* 5bit */
+ if ((err = snd_ac97_cvol_new(card, name, reg, max, ac97)) < 0)
+ return err;
+ return 0;
+}
+
+
static int snd_ac97_mixer_build(ac97_t * ac97)
{
snd_card_t *card = ac97->card;
snd_kcontrol_t *kctl;
- const snd_kcontrol_new_t *knew;
int err;
unsigned int idx;
unsigned char max;
@@ -1156,14 +1202,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
/* build master controls */
/* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */
if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) {
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_master[0], ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_master[1], ac97))) < 0)
+ if ((err = snd_ac97_cmix_new(card, "Master Playback", AC97_MASTER, 1, ac97)) < 0)
return err;
- snd_ac97_change_volume_params1(ac97, AC97_MASTER, &max);
- kctl->private_value &= ~(0xff << 16);
- kctl->private_value |= (int)max << 16;
- snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000 | max | (max << 8));
}
ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;
@@ -1206,15 +1246,11 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
/* build headphone controls */
if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == AC97_ID_STAC9708) {
- knew = ac97->id == AC97_ID_STAC9708 ? snd_ac97_sigmatel_surround : snd_ac97_controls_headphone;
- if ((err = snd_ctl_add(card, snd_ac97_cnew(knew, ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(knew + 1, ac97))) < 0)
+ const char *name = ac97->id == AC97_ID_STAC9708 ?
+ "Sigmatel Surround Playback" :
+ "Headphone Playback";
+ if ((err = snd_ac97_cmix_new(card, name, AC97_HEADPHONE, 1, ac97)) < 0)
return err;
- snd_ac97_change_volume_params1(ac97, AC97_HEADPHONE, &max);
- kctl->private_value &= ~(0xff << 16);
- kctl->private_value |= (int)max << 16;
- snd_ac97_write_cache(ac97, AC97_HEADPHONE, 0x8000 | max | (max << 8));
}
/* build master mono controls */
@@ -1276,70 +1312,73 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
/* build Line controls */
- for (idx = 0; idx < 2; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_line[idx], ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_LINE, 0x9f1f);
+ if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0)
+ return err;
/* build CD controls */
- for (idx = 0; idx < 2; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_cd[idx], ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_CD, 0x9f1f);
+ if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, 0, ac97)) < 0)
+ return err;
/* build Video controls */
if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {
- for (idx = 0; idx < 2; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_video[idx], ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_VIDEO, 0x9f1f);
+ if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, 0, ac97)) < 0)
+ return err;
}
/* build Aux controls */
if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {
- for (idx = 0; idx < 2; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_aux[idx], ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_AUX, 0x9f1f);
+ if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, 0, ac97)) < 0)
+ return err;
}
/* build PCM controls */
if (ac97->flags & AC97_AD_MULTI) {
+ unsigned short init_val;
+ if (ac97->flags & AC97_STEREO_MUTES)
+ init_val = 0x9f9f;
+ else
+ init_val = 0x9f1f;
for (idx = 0; idx < 2; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0)
return err;
- ac97->spec.ad18xx.pcmreg[0] = 0x9f1f;
+ ac97->spec.ad18xx.pcmreg[0] = init_val;
if (ac97->scaps & AC97_SCAP_SURROUND_DAC) {
for (idx = 0; idx < 2; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0)
return err;
- ac97->spec.ad18xx.pcmreg[1] = 0x9f1f;
+ ac97->spec.ad18xx.pcmreg[1] = init_val;
}
if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) {
for (idx = 0; idx < 2; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0)
return err;
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[0], ac97))) < 0)
- return err;
- ac97->spec.ad18xx.pcmreg[2] = 0x9f1f;
+ for (idx = 0; idx < 2; idx++)
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0)
+ return err;
+ ac97->spec.ad18xx.pcmreg[2] = init_val;
}
+ snd_ac97_write_cache(ac97, AC97_PCM, init_val);
} else {
- unsigned int pcm_ctrls = 2;
+ if ((err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97)) < 0)
+ return err;
/* FIXME: C-Media chips have no PCM volume!! */
if (/*ac97->id == 0x434d4941 ||*/
ac97->id == 0x434d4942 ||
ac97->id == 0x434d4961)
- pcm_ctrls = 1;
- for (idx = 0; idx < pcm_ctrls; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pcm[idx], ac97))) < 0)
+ snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
+ else {
+ if ((err = snd_ac97_cvol_new(card, "PCM Playback Volume", AC97_PCM, 31, ac97)) < 0)
return err;
+ }
}
- snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
/* build Capture controls */
- for (idx = 0; idx < 3; idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_capture[idx], ac97))) < 0)
- return err;
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
+ return err;
+ if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
+ return err;
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
+ return err;
snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);
@@ -1598,6 +1637,7 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
ac97_t *ac97;
char name[64];
unsigned long end_time;
+ unsigned int reg;
static snd_device_ops_t ops = {
.dev_free = snd_ac97_dev_free,
};
@@ -1641,6 +1681,20 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
snd_ac97_free(ac97);
return -EIO;
}
+ /* AC97 audio codec chip revision detection. */
+ /* Currently only Realtek ALC650 detection implemented. */
+ switch(ac97->id & 0xfffffff0) {
+ case 0x414c4720: /* ALC650 */
+ reg = snd_ac97_read(ac97, AC97_ALC650_REVISION);
+ if (((reg & 0x3f) >= 0) && ((reg & 0x3f) < 3))
+ ac97->id = 0x414c4720; /* Old version */
+ else if (((reg & 0x3f) >= 3) && ((reg & 0x3f) < 0x10))
+ ac97->id = 0x414c4721; /* D version */
+ else if ((reg&0x30) == 0x10)
+ ac97->id = 0x414c4722; /* E version */
+ else if ((reg&0x30) == 0x20)
+ ac97->id = 0x414c4723; /* F version */
+ }
/* test for AC'97 */
if (! (ac97->scaps & AC97_SCAP_AUDIO)) {
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
index dce4a9ba9133..9a8b7d013188 100644
--- a/sound/pci/ac97/ac97_local.h
+++ b/sound/pci/ac97/ac97_local.h
@@ -25,7 +25,7 @@
#define AC97_SINGLE(xname, reg, shift, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
.get = snd_ac97_get_single, .put = snd_ac97_put_single, \
- .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
+ .private_value = (reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) }
/* ac97_codec.c */
extern const char *snd_ac97_stereo_enhancements[];
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index ac63b96095d1..af81810afc6c 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -695,6 +695,28 @@ int patch_ad1886(ac97_t * ac97)
return 0;
}
+/* MISC bits */
+#define AC97_AD198X_MBC 0x0003 /* mic boost */
+#define AC97_AD198X_MBC_20 0x0000 /* +20dB */
+#define AC97_AD198X_MBC_10 0x0001 /* +10dB */
+#define AC97_AD198X_MBC_30 0x0002 /* +30dB */
+#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
+#define AC97_AD198X_VREFH 0x0008 /* 2.25V, 3.7V */
+#define AC97_AD198X_VREF_0 0x000c /* 0V */
+#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
+#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
+#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
+#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
+#define AC97_AD198X_DMIX0 0x0100 /* downmix mode: 0 = 6-to-4, 1 = 6-to-2 downmix */
+#define AC97_AD198X_DMIX1 0x0300 /* downmix mode: 1 = enabled */
+#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
+#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
+#define AC97_AD198X_LODIS 0x1000 /* LINE_OUT disable */
+#define AC97_AD198X_MSPLT 0x2000 /* mute split */
+#define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */
+#define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
+
+
static int snd_ac97_ad1980_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[2] = { "AC-Link", "A/D Converter" };
@@ -754,8 +776,13 @@ int patch_ad1980(ac97_t * ac97)
ac97->build_ops = &patch_ad1980_build_ops;
/* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
/* it seems that most vendors connect line-out connector to headphone out of AC'97 */
+ /* Stereo mutes enabled */
misc = snd_ac97_read(ac97, AC97_AD_MISC);
- snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 0x0420);
+ snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
+ AC97_AD198X_LOSEL |
+ AC97_AD198X_HPSEL |
+ AC97_AD198X_MSPLT);
+ ac97->flags |= AC97_STEREO_MUTES;
return 0;
}
@@ -768,7 +795,17 @@ int patch_ad1985(ac97_t * ac97)
misc = snd_ac97_read(ac97, AC97_AD_MISC);
/* switch front/surround line-out/hp-out */
/* center/LFE, surround in High-Z mode */
- snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 0x1c28);
+ /* AD-compatible mode */
+ /* Stereo mutes enabled */
+ snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
+ AC97_AD198X_VREFD |
+ AC97_AD198X_LOSEL |
+ AC97_AD198X_HPSEL |
+ AC97_AD198X_CLDIS |
+ AC97_AD198X_LODIS |
+ AC97_AD198X_MSPLT |
+ AC97_AD198X_AC97NC);
+ ac97->flags |= AC97_STEREO_MUTES;
return 0;
}
@@ -863,19 +900,24 @@ int patch_alc650(ac97_t * ac97)
unsigned short val;
int spdif = 0;
- /* FIXME: set the below 1 if we can detect the chip rev.E correctly.
- * this is used for switching mic and center/lfe, which needs
- * resetting GPIO0 level on the older revision.
- */
ac97->build_ops = &patch_alc650_ops;
- ac97->spec.dev_flags = 0;
+
+ /* revision E or F */
+ /* FIXME: what about revision D ? */
+ ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
+ ac97->id == 0x414c4723);
/* check spdif (should be only on rev.E) */
- val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
- if (val & AC97_EA_SPCV)
- spdif = 1;
+ if (ac97->spec.dev_flags) {
+ val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
+ if (val & AC97_EA_SPCV)
+ spdif = 1;
+ }
if (spdif) {
+ /* enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W */
+ snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
+ snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
/* enable spdif in */
snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
snd_ac97_read(ac97, AC97_ALC650_CLOCK) | 0x03);
@@ -891,18 +933,18 @@ int patch_alc650(ac97_t * ac97)
int mic_off;
mic_off = snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10);
/* GPIO0 direction */
- val = snd_ac97_read(ac97, 0x76);
+ val = snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP);
if (mic_off)
val &= ~0x01;
else
val |= 0x01;
- snd_ac97_write_cache(ac97, 0x76, val);
- val = snd_ac97_read(ac97, 0x78);
+ snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP, val);
+ val = snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS);
if (mic_off)
val &= ~0x100;
else
val = val | 0x100;
- snd_ac97_write_cache(ac97, 0x78, val);
+ snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, val);
}
/* full DAC volume */
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index 4619cc1f25ac..0a985ad57c1f 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -151,7 +151,7 @@ static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, in
snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",
val & AC97_SC_PRO ? " PRO" : " Consumer",
val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
- val & AC97_SC_COPY ? " Copyright" : "",
+ val & AC97_SC_COPY ? "" : " Copyright",
val & AC97_SC_PRE ? " Preemph50/15" : "",
(val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
(val & AC97_SC_L) >> 11,
@@ -164,8 +164,32 @@ static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, in
(ac97->flags & AC97_CS_SPDIF) ?
(val & AC97_SC_V ? " Enabled" : "") :
(val & AC97_SC_V ? " Validity" : ""));
+ /* ALC650 specific*/
+ if ((ac97->id & 0xfffffff0) == 0x414c4720 &&
+ (snd_ac97_read(ac97, AC97_ALC650_CLOCK) & 0x01)) {
+ val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
+ if (val & AC97_ALC650_CLOCK_LOCK) {
+ val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS1);
+ snd_iprintf(buffer, "SPDIF In Status :%s%s%s%s Category=0x%x Generation=%i",
+ val & AC97_ALC650_PRO ? " PRO" : " Consumer",
+ val & AC97_ALC650_NAUDIO ? " Non-audio" : " PCM",
+ val & AC97_ALC650_COPY ? "" : " Copyright",
+ val & AC97_ALC650_PRE ? " Preemph50/15" : "",
+ (val & AC97_ALC650_CC_MASK) >> AC97_ALC650_CC_SHIFT,
+ (val & AC97_ALC650_L) >> 15);
+ val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
+ snd_iprintf(buffer, "%s Accuracy=%i%s%s\n",
+ spdif_rates[(val & AC97_ALC650_SPSR_MASK) >> AC97_ALC650_SPSR_SHIFT],
+ (val & AC97_ALC650_CLOCK_ACCURACY) >> AC97_ALC650_CLOCK_SHIFT,
+ (val & AC97_ALC650_CLOCK_LOCK ? " Locked" : " Unlocked"),
+ (val & AC97_ALC650_V ? " Validity?" : ""));
+ } else {
+ snd_iprintf(buffer, "SPDIF In Status : Not Locked\n");
+ }
+ }
}
+
__modem:
mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
if (mext == 0)
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index f48464c28de3..db0a73f95621 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -2111,9 +2111,9 @@ static int snd_cs46xx_spdif_default_put(snd_kcontrol_t * kcontrol,
int change;
down (&chip->spos_mutex);
- val = _wrap_all_bits(((u32)ucontrol->value.iec958.status[0] << 24)) |
- _wrap_all_bits(((u32)ucontrol->value.iec958.status[2] << 16)) |
- _wrap_all_bits( (u32)ucontrol->value.iec958.status[3]) |
+ val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
+ ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |
+ ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
/* left and right validity bit */
(1 << 13) | (1 << 12);
@@ -2164,9 +2164,9 @@ static int snd_cs46xx_spdif_stream_put(snd_kcontrol_t * kcontrol,
int change;
down (&chip->spos_mutex);
- val = _wrap_all_bits(((u32)ucontrol->value.iec958.status[0] << 24)) |
- _wrap_all_bits(((u32)ucontrol->value.iec958.status[1] << 16)) |
- _wrap_all_bits( (u32)ucontrol->value.iec958.status[3]) |
+ val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
+ ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |
+ ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
/* left and right validity bit */
(1 << 13) | (1 << 12);
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index d58e6eeb1068..e2092c13bc7a 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -267,9 +267,9 @@ dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip)
default channel status */
ins->spdif_csuv_default =
ins->spdif_csuv_stream =
- /* byte 0 */ (_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF & 0xff)) << 24) |
- /* byte 1 */ (_wrap_all_bits( ((SNDRV_PCM_DEFAULT_CON_SPDIF >> 16) & 0xff)) << 16) |
- /* byte 3 */ _wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF >> 24) & 0xff) |
+ /* byte 0 */ ((unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF & 0xff)) << 24) |
+ /* byte 1 */ ((unsigned int)_wrap_all_bits( ((SNDRV_PCM_DEFAULT_CON_SPDIF >> 8) & 0xff)) << 16) |
+ /* byte 3 */ (unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF >> 24) & 0xff) |
/* left and right validity bits */ (1 << 13) | (1 << 12);
return ins;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 4bf067461036..6deea6359ddc 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -170,7 +170,10 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
}
#endif
- if (emu->audigy) {
+ if (emu->audigy && (emu->revision == 4) ) {
+ strcpy(card->driver, "Audigy2");
+ strcpy(card->shortname, "Sound Blaster Audigy2");
+ } else if (emu->audigy) {
strcpy(card->driver, "Audigy");
strcpy(card->shortname, "Sound Blaster Audigy");
} else if (emu->APS) {
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index c038e776f6c9..d66b6ec44dae 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -667,7 +667,7 @@ static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t
pcm->hw_io = ptr;
pcm->hw_ready -= frames;
pcm->sw_io += frames;
- if (pcm->sw_io > runtime->buffer_size)
+ if (pcm->sw_io >= runtime->buffer_size)
pcm->sw_io -= runtime->buffer_size;
snd_emu10k1_fx8010_playback_transfer(substream);
return pcm->sw_io;
@@ -1235,6 +1235,7 @@ static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_contr
*/
#define A_GPR_ACCU 0xd6
+#define A_GPR_COND 0xd7
static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
{
@@ -1502,13 +1503,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
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);
- A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
- A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
+ }
/* analog speakers */
if (emu->revision == 4) { /* audigy2 */
@@ -1523,6 +1518,29 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* headphone */
A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
+ /* digital outputs */
+// A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
+
+ /* IEC958 Optical Raw Playback Switch */
+ icode->gpr_map[gpr++] = 0x1008;
+ icode->gpr_map[gpr++] = 0xffff0000;
+ for (z = 0; z < 2; z++) {
+ A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000);
+ A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001);
+ A_OP(icode, &ptr, iACC3, A_GPR(tmp + 2), A_C_00000000, A_C_00010000, A_GPR(tmp + 2));
+ A_OP(icode, &ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_GPR(gpr - 1), A_C_00000000);
+ A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z);
+ A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
+ A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
+ A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
+ }
+ snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "IEC958 Optical Raw Playback Switch", gpr, 0);
+ gpr += 2;
+
+ A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
+ A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
+ A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
+
/* ADC buffer */
A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture);
A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 3e309c3dcd8a..c92c58a74f6d 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -666,8 +666,11 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * subs
#else /* EMU10K1 Open Source code from Creative */
if (ptr < epcm->ccca_start_addr)
ptr += runtime->buffer_size - epcm->ccca_start_addr;
- else
+ else {
ptr -= epcm->ccca_start_addr;
+ if (ptr >= runtime->buffer_size)
+ ptr -= runtime->buffer_size;
+ }
#endif
// printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size);
return ptr;
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index e0dd0b644bf7..e4155a7a7362 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -130,6 +130,7 @@ static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 };
static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 };
static int clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
+static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
@@ -155,6 +156,9 @@ MODULE_PARM_SYNTAX(clock, SNDRV_ENABLED);
MODULE_PARM(use_pm, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(use_pm, "Toggle power-management. (0 = off, 1 = on, 2 = auto)");
MODULE_PARM_SYNTAX(use_pm, SNDRV_ENABLED ",allows:{{0,1,2}},skill:advanced");
+MODULE_PARM(enable_mpu, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(enable_mpu, "Enable MPU401. (0 = off, 1 = on, 2 = auto)");
+MODULE_PARM_SYNTAX(enable_mpu, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
/* PCI Dev ID's */
@@ -2377,7 +2381,9 @@ static void snd_es1968_chip_init(es1968_t *chip)
static void snd_es1968_start_irq(es1968_t *chip)
{
unsigned short w;
- w = ESM_HIRQ_DSIE | ESM_HIRQ_MPU401 | ESM_HIRQ_HW_VOLUME;
+ w = ESM_HIRQ_DSIE | ESM_HIRQ_HW_VOLUME;
+ if (chip->rmidi)
+ w |= ESM_HIRQ_MPU401;
outw(w, chip->io_port + ESM_PORT_HOST_IRQ);
}
@@ -2491,18 +2497,22 @@ static int snd_es1968_dev_free(snd_device_t *device)
return snd_es1968_free(chip);
}
-struct pm_whitelist {
+struct ess_device_list {
unsigned short type; /* chip type */
unsigned short vendor; /* subsystem vendor id */
};
-static struct pm_whitelist whitelist[] __devinitdata = {
+static struct ess_device_list pm_whitelist[] __devinitdata = {
{ TYPE_MAESTRO2E, 0x1028 },
{ TYPE_MAESTRO2E, 0x103c },
{ TYPE_MAESTRO2E, 0x1179 },
{ TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */
};
+static struct ess_device_list mpu_blacklist[] __devinitdata = {
+ { TYPE_MAESTRO2, 0x125d },
+};
+
static int __devinit snd_es1968_create(snd_card_t * card,
struct pci_dev *pci,
int total_bufsize,
@@ -2578,9 +2588,9 @@ static int __devinit snd_es1968_create(snd_card_t * card,
/* disable power-management if not on the whitelist */
unsigned short vend;
pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend);
- for (i = 0; i < (int)ARRAY_SIZE(whitelist); i++) {
- if (chip->type == whitelist[i].type &&
- vend == whitelist[i].vendor) {
+ for (i = 0; i < (int)ARRAY_SIZE(pm_whitelist); i++) {
+ if (chip->type == pm_whitelist[i].type &&
+ vend == pm_whitelist[i].vendor) {
do_pm = 1;
break;
}
@@ -2726,10 +2736,24 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
return err;
}
- if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
- chip->io_port + ESM_MPU401_PORT, 1,
- chip->irq, 0, &chip->rmidi)) < 0) {
- printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n");
+ if (enable_mpu[dev] == 2) {
+ /* check the black list */
+ unsigned short vend;
+ pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend);
+ for (i = 0; i < ARRAY_SIZE(mpu_blacklist); i++) {
+ if (chip->type == mpu_blacklist[i].type &&
+ vend == mpu_blacklist[i].vendor) {
+ enable_mpu[dev] = 0;
+ break;
+ }
+ }
+ }
+ if (enable_mpu[dev]) {
+ if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
+ chip->io_port + ESM_MPU401_PORT, 1,
+ chip->irq, 0, &chip->rmidi)) < 0) {
+ printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n");
+ }
}
/* card switches */
@@ -2778,16 +2802,6 @@ static struct pci_driver driver = {
#endif
};
-#if 0 // do we really need this?
-static int snd_es1968_notifier(struct notifier_block *nb, unsigned long event, void *buf)
-{
- pci_unregister_driver(&driver);
- return NOTIFY_OK;
-}
-
-static struct notifier_block snd_es1968_nb = {snd_es1968_notifier, NULL, 0};
-#endif
-
static int __init alsa_card_es1968_init(void)
{
int err;
@@ -2798,14 +2812,6 @@ static int __init alsa_card_es1968_init(void)
#endif
return err;
}
-#if 0 // do we really need this?
- /* If this driver is not shutdown cleanly at reboot, it can
- leave the speaking emitting an annoying noise, so we catch
- shutdown events. */
- if (register_reboot_notifier(&snd_es1968_nb)) {
- printk(KERN_ERR "reboot notifier registration failed; may make noise at shutdown.\n");
- }
-#endif
return 0;
}
@@ -2827,7 +2833,8 @@ module_exit(alsa_card_es1968_exit)
pcm_substreams_p,
pcm_substreams_c,
clock,
- use_pm
+ use_pm,
+ enable_mpu
*/
static int __init alsa_card_es1968_setup(char *str)
@@ -2843,7 +2850,8 @@ static int __init alsa_card_es1968_setup(char *str)
get_option(&str,&pcm_substreams_p[nr_dev]) == 2 &&
get_option(&str,&pcm_substreams_c[nr_dev]) == 2 &&
get_option(&str,&clock[nr_dev]) == 2 &&
- get_option(&str,&use_pm[nr_dev]) == 2);
+ get_option(&str,&use_pm[nr_dev]) == 2 &&
+ get_option(&str,&enable_mpu[nr_dev]) == 2);
nr_dev++;
return 1;
}
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index c5ab6c0662b7..ac470690be93 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -457,7 +457,7 @@ static unsigned char aureon51_eeprom[] __devinitdata = {
0x12, /* SYSCONF: clock 512, mpu401, spdif-in/ADC, 3DACs */
0x80, /* ACLINK: I2S */
0xf8, /* I2S: vol, 96k, 24bit, 192k */
- 0xc2, /* SPDIF: out-en, out-int, spdif-in */
+ 0xc3, /* SPDIF: out-en, out-int, spdif-in */
0xff, /* GPIO_DIR */
0xff, /* GPIO_DIR1 */
0xbf, /* GPIO_DIR2 */
@@ -473,7 +473,7 @@ static unsigned char aureon71_eeprom[] __devinitdata = {
0x13, /* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
0x80, /* ACLINK: I2S */
0xf8, /* I2S: vol, 96k, 24bit, 192k */
- 0xc2, /* SPDIF: out-en, out-int, spdif-in */
+ 0xc3, /* SPDIF: out-en, out-int, spdif-in */
0xff, /* GPIO_DIR */
0xff, /* GPIO_DIR1 */
0xbf, /* GPIO_DIR2 */
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 0fc548dff5f0..efc03aa94de7 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -382,11 +382,6 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
return;
}
- if (rate == ice->cur_rate) {
- spin_unlock_irqrestore(&ice->reg_lock, flags);
- return;
- }
-
switch (rate) {
case 8000: val = 6; break;
case 9600: val = 3; break;
@@ -409,6 +404,11 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
break;
}
outb(val, ICEMT1724(ice, RATE));
+ if (rate == ice->cur_rate) {
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+ return;
+ }
+
ice->cur_rate = rate;
/* check MT02 */
@@ -482,8 +482,6 @@ static int snd_vt1724_playback_pro_prepare(snd_pcm_substream_t * substream)
return 0;
}
-#define CHECK_INVALID_PTR
-
static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * substream)
{
ice1712_t *ice = snd_pcm_substream_chip(substream);
@@ -491,20 +489,28 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * s
if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & VT1724_PDMA0_START))
return 0;
+#if 0 /* read PLAYBACK_ADDR */
ptr = inl(ICEMT1724(ice, PLAYBACK_ADDR));
-#ifdef CHECK_INVALID_PTR
if (ptr < substream->runtime->dma_addr) {
snd_printd("ice1724: invalid negative ptr\n");
return 0;
}
-#endif
ptr -= substream->runtime->dma_addr;
ptr = bytes_to_frames(substream->runtime, ptr);
-#ifdef CHECK_INVALID_PTR
if (ptr >= substream->runtime->buffer_size) {
snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->period_size);
return 0;
}
+#else /* read PLAYBACK_SIZE */
+ ptr = inl(ICEMT1724(ice, PLAYBACK_SIZE)) & 0xffffff;
+ ptr = (ptr + 1) << 2;
+ ptr = bytes_to_frames(substream->runtime, ptr);
+ if (ptr <= substream->runtime->buffer_size)
+ ptr = substream->runtime->buffer_size - ptr;
+ else {
+ snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
+ ptr = 0;
+ }
#endif
return ptr;
}
@@ -536,9 +542,22 @@ static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream,
if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start))
return 0;
+#if 0 /* use ADDR register */
ptr = inl(ice->profi_port + reg->addr);
ptr -= substream->runtime->dma_addr;
return bytes_to_frames(substream->runtime, ptr);
+#else /* use SIZE register */
+ ptr = inw(ice->profi_port + reg->size);
+ ptr = (ptr + 1) << 2;
+ ptr = bytes_to_frames(substream->runtime, ptr);
+ if (ptr <= substream->runtime->buffer_size)
+ ptr = substream->runtime->buffer_size - ptr;
+ else {
+ snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
+ ptr = 0;
+ }
+ return ptr;
+#endif
}
const static struct vt1724_pcm_reg vt1724_capture_pro_reg = {
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 0d6365cad7f0..c99e14d37724 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -69,7 +69,8 @@ static void revo_set_rate_val(akm4xxx_t *ak, unsigned int rate)
tmp = snd_akm4xxx_get(ak, 0, reg);
tmp &= ~(0x03 << shift);
tmp |= dfs << shift;
- snd_akm4xxx_write(ak, 0, reg, tmp);
+ // snd_akm4xxx_write(ak, 0, reg, tmp);
+ snd_akm4xxx_set(ak, 0, reg, tmp); /* the value is written in reset(0) */
snd_akm4xxx_reset(ak, 0);
}
@@ -134,7 +135,7 @@ static int __devinit revo_init(ice1712_t *ice)
}
/* second stage of initialization, analog parts and others */
- ak = ice->akm = kmalloc(sizeof(akm4xxx_t) * 2, GFP_KERNEL);
+ ak = ice->akm = snd_kcalloc(sizeof(akm4xxx_t) * 2, GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 2;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 81ede0fe5fd5..e0226de635d1 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -360,6 +360,7 @@ typedef struct {
int frags;
int lvi;
int lvi_frag;
+ int civ;
int ack;
int ack_reload;
unsigned int ack_bit;
@@ -710,6 +711,7 @@ static void snd_intel8x0_setup_periods(intel8x0_t *chip, ichdev_t *ichdev)
ichdev->frags = ichdev->size / ichdev->fragsize;
}
iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi = ICH_REG_LVI_MASK);
+ ichdev->civ = 0;
iputbyte(chip, port + ICH_REG_OFF_CIV, 0);
ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags;
ichdev->position = 0;
@@ -728,19 +730,39 @@ static void snd_intel8x0_setup_periods(intel8x0_t *chip, ichdev_t *ichdev)
static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
{
unsigned long port = ichdev->reg_offset;
+ int civ, i, step;
int ack = 0;
- ichdev->position += ichdev->fragsize1;
+ civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
+ if (civ == ichdev->civ) {
+ // snd_printd("civ same %d\n", civ);
+ step = 1;
+ ichdev->civ++;
+ ichdev->civ &= ICH_REG_LVI_MASK;
+ } else {
+ step = civ - ichdev->civ;
+ if (step < 0)
+ step += ICH_REG_LVI_MASK + 1;
+ // if (step != 1)
+ // snd_printd("step = %d, %d -> %d\n", step, ichdev->civ, civ);
+ ichdev->civ = civ;
+ }
+
+ ichdev->position += step * ichdev->fragsize1;
ichdev->position %= ichdev->size;
- ichdev->lvi++;
+ ichdev->lvi += step;
ichdev->lvi &= ICH_REG_LVI_MASK;
iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
- ichdev->lvi_frag++;
- ichdev->lvi_frag %= ichdev->frags;
- ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
+ for (i = 0; i < step; i++) {
+ ichdev->lvi_frag++;
+ ichdev->lvi_frag %= ichdev->frags;
+ ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
// printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR));
- if ((ack = (--ichdev->ack == 0)) != 0)
- ichdev->ack = ichdev->ack_reload;
+ if (--ichdev->ack == 0) {
+ ichdev->ack = ichdev->ack_reload;
+ ack = 1;
+ }
+ }
if (ack && ichdev->substream) {
spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(ichdev->substream);
@@ -1534,7 +1556,7 @@ static struct _ac97_rate_regs nforce_ac97_rate_regs[] __devinitdata = {
{ NVD_PCMOUT, { AC97_PCM_FRONT_DAC_RATE, AC97_PCM_SURR_DAC_RATE, AC97_PCM_LFE_DAC_RATE }, AC97_RATES_FRONT_DAC },
{ NVD_PCMIN, { AC97_PCM_LR_ADC_RATE, 0, 0 }, AC97_RATES_ADC },
{ NVD_MIC, { AC97_PCM_MIC_ADC_RATE, 0, 0 }, AC97_RATES_MIC_ADC },
- { NVD_SPBAR, { AC97_SPDIF, AC97_PCM_FRONT_DAC_RATE, 0 }, AC97_RATES_SPDIF },
+ { NVD_SPBAR, { AC97_SPDIF, AC97_PCM_FRONT_DAC_RATE, 0 }, -1 }, /* spdif is 48k only */
};
static struct _ac97_rate_regs ali_ac97_rate_regs[] __devinitdata = {
@@ -1558,11 +1580,23 @@ static struct _ac97_rate_regs ali_ac97_rate_regs[] __devinitdata = {
static struct ac97_quirk ac97_quirks[] __devinitdata = {
{
.vendor = 0x1028,
+ .device = 0x00d8,
+ .name = "Dell Precision 530",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .vendor = 0x1028,
.device = 0x0126,
.name = "Dell Optiplex GX260",
.type = AC97_TUNE_HP_ONLY
},
{
+ .vendor = 0x1028,
+ .device = 0x0157,
+ .name = "Dell Dimension 8300",
+ .type = AC97_TUNE_SWAP_SURROUND
+ },
+ {
.vendor = 0x1043,
.device =0x80b0,
.name = "ASUS P4PE Mobo",
@@ -1648,6 +1682,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.name = "Intel ICH5/AD1985 (discrete)",
.type = AC97_TUNE_HP_ONLY
},
+ {
+ .vendor = 0x103c,
+ .device = 0x00c3,
+ .name = "Hewlett-Packard onboard",
+ .type = AC97_TUNE_HP_ONLY
+ },
{ } /* terminator */
};
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index a8e991a25702..072f4cba9295 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -2958,10 +2958,12 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
ac97_t _ac97;
snd_card_t * card = trident->card;
snd_kcontrol_t *kctl;
- snd_ctl_elem_value_t uctl;
+ snd_ctl_elem_value_t *uctl;
int idx, err, retries = 2;
- memset(&uctl, 0, sizeof(uctl));
+ uctl = (snd_ctl_elem_value_t *)snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+ if (!uctl)
+ return -ENOMEM;
memset(&_ac97, 0, sizeof(_ac97));
_ac97.write = snd_trident_codec_write;
@@ -2973,12 +2975,12 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
if ((err = snd_ac97_mixer(trident->card, &_ac97, &trident->ac97)) < 0) {
if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
if ((err = snd_trident_sis_reset(trident)) < 0)
- return err;
+ goto __out;
if (retries-- > 0)
goto __again;
- return -EIO;
+ err = -EIO;
}
- return err;
+ goto __out;
}
/* secondary codec? */
@@ -3002,11 +3004,11 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident))) < 0)
- return err;
- kctl->put(kctl, &uctl);
+ goto __out;
+ kctl->put(kctl, uctl);
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident))) < 0)
- return err;
- kctl->put(kctl, &uctl);
+ goto __out;
+ kctl->put(kctl, uctl);
outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
} else {
outl(trident->musicvol_wavevol = 0xffff0000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
@@ -3019,59 +3021,68 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
tmix->voice = NULL;
}
if ((trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident)) == NULL)
- return -ENOMEM;
+ goto __nomem;
if ((err = snd_ctl_add(card, trident->ctl_vol)))
- return err;
+ goto __out;
if ((trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident)) == NULL)
- return -ENOMEM;
+ goto __nomem;
if ((err = snd_ctl_add(card, trident->ctl_pan)))
- return err;
+ goto __out;
if ((trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident)) == NULL)
- return -ENOMEM;
+ goto __nomem;
if ((err = snd_ctl_add(card, trident->ctl_rvol)))
- return err;
+ goto __out;
if ((trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident)) == NULL)
- return -ENOMEM;
+ goto __nomem;
if ((err = snd_ctl_add(card, trident->ctl_cvol)))
- return err;
+ goto __out;
if (trident->device == TRIDENT_DEVICE_ID_NX) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident))) < 0)
- return err;
- kctl->put(kctl, &uctl);
+ goto __out;
+ kctl->put(kctl, uctl);
}
if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_control, trident))) < 0)
- return err;
+ goto __out;
if (trident->ac97->ext_id & AC97_EI_SPDIF)
kctl->id.index++;
if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF))
kctl->id.index++;
idx = kctl->id.index;
- kctl->put(kctl, &uctl);
+ kctl->put(kctl, uctl);
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_default, trident))) < 0)
- return err;
+ goto __out;
kctl->id.index = idx;
kctl->id.device = pcm_spdif_device;
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident))) < 0)
- return err;
+ goto __out;
kctl->id.index = idx;
kctl->id.device = pcm_spdif_device;
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident))) < 0)
- return err;
+ goto __out;
kctl->id.index = idx;
kctl->id.device = pcm_spdif_device;
trident->spdif_pcm_ctl = kctl;
}
- return 0;
+ err = 0;
+ goto __out;
+
+ __nomem:
+ err = -ENOMEM;
+
+ __out:
+ kfree(uctl);
+
+ return err;
}
/*
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 180653006efb..13f4ee0a68b8 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -286,6 +286,15 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
/*
*/
+#define VIA_DXS_AUTO 0
+#define VIA_DXS_ENABLE 1
+#define VIA_DXS_DISABLE 2
+#define VIA_DXS_48K 3
+
+
+/*
+ */
+
typedef struct _snd_via82xx via82xx_t;
typedef struct via_dev viadev_t;
#define chip_t via82xx_t
@@ -1033,7 +1042,8 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
ratep = &chip->rates[viadev->direction];
spin_lock_irqsave(&ratep->lock, flags);
ratep->used++;
- if (chip->dxs_fixed) {
+ if (chip->dxs_fixed && viadev->reg_offset < 0x40) {
+ /* fixed DXS playback rate */
runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
} else if (! ratep->rate) {
@@ -1944,6 +1954,50 @@ static struct via823x_info via823x_cards[] __devinitdata = {
{ VIA_REV_8235, "VIA 8235", TYPE_VIA8233 },
};
+/*
+ * auto detection of DXS channel supports.
+ */
+struct dxs_whitelist {
+ unsigned short vendor;
+ unsigned short device;
+ unsigned short mask;
+ short action; /* new dxs_support value */
+};
+
+static int __devinit check_dxs_list(struct pci_dev *pci)
+{
+ static struct dxs_whitelist whitelist[] = {
+ { .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K },
+ { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
+ { } /* terminator */
+ };
+ struct dxs_whitelist *w;
+ unsigned short subsystem_vendor;
+ unsigned short subsystem_device;
+
+ pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+ pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
+
+ for (w = whitelist; w->vendor; w++) {
+ if (w->vendor != subsystem_vendor)
+ continue;
+ if (w->mask) {
+ if ((w->mask & subsystem_device) == w->device)
+ return w->action;
+ } else {
+ if (subsystem_device == w->device)
+ return w->action;
+ }
+ }
+
+ /*
+ * not detected, try 48k rate only to be sure.
+ */
+ printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n");
+ printk(KERN_INFO " Please try dxs_support=1 option and report if it works on your machine.\n");
+ return VIA_DXS_48K;
+};
+
static int __devinit snd_via82xx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -1984,13 +2038,16 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
break;
}
}
+ if (dxs_support[dev] == VIA_DXS_AUTO)
+ dxs_support[dev] = check_dxs_list(pci);
/* force to use VIA8233 or 8233A model according to
* dxs_support module option
*/
- if (dxs_support[dev] == 1)
- chip_type = TYPE_VIA8233;
- else if (dxs_support[dev] == 2)
+ if (dxs_support[dev] == VIA_DXS_DISABLE)
chip_type = TYPE_VIA8233A;
+ else
+ chip_type = TYPE_VIA8233;
+
if (chip_type == TYPE_VIA8233A)
strcpy(card->driver, "VIA8233A");
else
@@ -2015,10 +2072,11 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
if (chip_type == TYPE_VIA8233A) {
if ((err = snd_via8233a_pcm_new(chip)) < 0)
goto __error;
+ chip->dxs_fixed = 1; /* use 48k for DXS #3 */
} else {
if ((err = snd_via8233_pcm_new(chip)) < 0)
goto __error;
- if (dxs_support[dev] == 3)
+ if (dxs_support[dev] == VIA_DXS_48K)
chip->dxs_fixed = 1;
}
if ((err = snd_via8233_init_misc(chip, dev)) < 0)
@@ -2083,7 +2141,7 @@ module_exit(alsa_card_via82xx_exit)
#ifndef MODULE
/* format is: snd-via82xx=enable,index,id,
- mpu_port,ac97_clock */
+ mpu_port,ac97_clock,dxs_support */
static int __init alsa_card_via82xx_setup(char *str)
{
@@ -2095,7 +2153,8 @@ static int __init alsa_card_via82xx_setup(char *str)
get_option(&str,&index[nr_dev]) == 2 &&
get_id(&str,&id[nr_dev]) == 2 &&
get_option(&str,(int *)&mpu_port[nr_dev]) == 2 &&
- get_option(&str,&ac97_clock[nr_dev]) == 2);
+ get_option(&str,&ac97_clock[nr_dev]) == 2 &&
+ get_option(&str,&dxs_support[nr_dev]) == 2);
nr_dev++;
return 1;
}
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
index 293ebbb5a28e..cd6d880bd072 100644
--- a/sound/pcmcia/vx/vx_entry.c
+++ b/sound/pcmcia/vx/vx_entry.c
@@ -34,7 +34,7 @@ static void vxpocket_config(dev_link_t *link);
static int vxpocket_event(event_t event, int priority, event_callback_args_t *args);
-static void vxpocket_release(dev_link_t* link)
+static void vxpocket_release(dev_link_t *link)
{
if (link->state & DEV_CONFIG) {
/* release cs resources */
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index 5ffac4516e7b..d0dd7f49eb98 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -74,14 +74,14 @@ static int daca_set_volume(pmac_daca_t *mix)
if (! mix->i2c.client)
return -ENODEV;
- if (mix->right_vol > DACA_VOL_MAX)
+ if (mix->left_vol > DACA_VOL_MAX)
data[0] = DACA_VOL_MAX;
else
- data[0] = mix->right_vol;
- if (mix->left_vol > DACA_VOL_MAX)
+ data[0] = mix->left_vol;
+ if (mix->right_vol > DACA_VOL_MAX)
data[1] = DACA_VOL_MAX;
else
- data[1] = mix->left_vol;
+ data[1] = mix->right_vol;
data[1] |= mix->deemphasis ? 0x40 : 0;
if (snd_pmac_keywest_write(&mix->i2c, DACA_REG_AVOL, 2, data) < 0) {
snd_printk("failed to set volume \n");
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index c547c44d56b1..a74a34cc4e55 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -923,8 +923,6 @@ static int __init snd_pmac_detect(pmac_t *chip)
}
if (device_is_compatible(sound, "snapper")) {
chip->model = PMAC_SNAPPER;
- chip->can_capture = 0; /* no capture */
- chip->can_duplex = 0;
// chip->can_byte_swap = 0; /* FIXME: check this */
chip->num_freqs = 2;
chip->freq_table = tumbler_freqs;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 2d34aa2ecce3..385b95e484c6 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -42,7 +42,7 @@
#define TAS_I2C_ADDR 0x34
/* registers */
-#define TAS_REG_MCS 0x01
+#define TAS_REG_MCS 0x01 /* main control */
#define TAS_REG_DRC 0x02
#define TAS_REG_VOL 0x04
#define TAS_REG_TREBLE 0x05
@@ -56,6 +56,8 @@
/* tas3004 */
#define TAS_REG_LMIX TAS_REG_INPUT1
#define TAS_REG_RMIX TAS_REG_INPUT2
+#define TAS_REG_MCS2 0x43 /* main control 2 */
+#define TAS_REG_ACS 0x40 /* analog control */
/* mono volumes for tas3001c/tas3004 */
enum {
@@ -98,21 +100,48 @@ typedef struct pmac_tumbler_t {
/*
*/
+static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs)
+{
+ while (*regs > 0) {
+ int err, count = 10;
+ do {
+ err = snd_pmac_keywest_write_byte(i2c, regs[0], regs[1]);
+ if (err >= 0)
+ break;
+ mdelay(10);
+ } while (count--);
+ if (err < 0)
+ return -ENXIO;
+ regs += 2;
+ }
+ return 0;
+}
+
+
static int tumbler_init_client(pmac_keywest_t *i2c)
{
- int err, count = 10;
- do {
+ static unsigned int regs[] = {
/* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */
- err = snd_pmac_keywest_write_byte(i2c, TAS_REG_MCS,
- (1<<6)+(2<<4)+(2<<2)+0);
- if (err >= 0)
- return err;
- mdelay(10);
- } while (count--);
- return -ENXIO;
+ TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0,
+ 0, /* terminator */
+ };
+ return send_init_client(i2c, regs);
}
-
+static int snapper_init_client(pmac_keywest_t *i2c)
+{
+ static unsigned int regs[] = {
+ /* normal operation, SCLK=64fps, i2s output, 16bit width */
+ TAS_REG_MCS, (1<<6)|(2<<4)|0,
+ /* normal operation, all-pass mode */
+ TAS_REG_MCS2, (1<<1),
+ /* normal output, no deemphasis, A input, power-up */
+ TAS_REG_ACS, 0,
+ 0, /* terminator */
+ };
+ return send_init_client(i2c, regs);
+}
+
/*
* gpio access
*/
@@ -882,8 +911,8 @@ static void tumbler_resume(pmac_t *chip)
snd_assert(mix, return);
tumbler_reset_audio(chip);
- if (mix->i2c.client) {
- if (tumbler_init_client(&mix->i2c) < 0)
+ if (mix->i2c.client && mix->i2c.init_client) {
+ if (mix->i2c.init_client(&mix->i2c) < 0)
printk(KERN_ERR "tumbler_init_client error\n");
} else
printk(KERN_ERR "tumbler: i2c is not initialized\n");
@@ -976,6 +1005,9 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
chip->mixer_data = mix;
chip->mixer_free = tumbler_cleanup;
+ if ((err = tumbler_init(chip)) < 0)
+ return err;
+
/* set up TAS */
tas_node = find_devices("deq");
if (tas_node == NULL)
@@ -987,11 +1019,12 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
else
mix->i2c.addr = TAS_I2C_ADDR;
- mix->i2c.init_client = tumbler_init_client;
if (chip->model == PMAC_TUMBLER) {
+ mix->i2c.init_client = tumbler_init_client;
mix->i2c.name = "TAS3001c";
chipname = "Tumbler";
} else {
+ mix->i2c.init_client = snapper_init_client;
mix->i2c.name = "TAS3004";
chipname = "Snapper";
}
@@ -1022,9 +1055,6 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
return err;
- if ((err = tumbler_init(chip)) < 0)
- return err;
-
#ifdef CONFIG_PMAC_PBOOK
chip->resume = tumbler_resume;
#endif
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c9a74d3e56bf..292f271b9a25 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1095,12 +1095,16 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
subs->fill_max = 0;
/* we need a sync pipe in async OUT or adaptive IN mode */
+ /* check the number of EP, since some devices have broken
+ * descriptors which fool us. if it has only one EP,
+ * assume it as adaptive-out or sync-in.
+ */
attr = fmt->ep_attr & EP_ATTR_MASK;
- if ((is_playback && attr == EP_ATTR_ASYNC) ||
- (! is_playback && attr == EP_ATTR_ADAPTIVE)) {
- /* check endpoint */
- if (altsd->bNumEndpoints < 2 ||
- get_endpoint(alts, 1)->bmAttributes != 0x01 ||
+ if (((is_playback && attr == EP_ATTR_ASYNC) ||
+ (! is_playback && attr == EP_ATTR_ADAPTIVE)) &&
+ altsd->bNumEndpoints >= 2) {
+ /* check sync-pipe endpoint */
+ if (get_endpoint(alts, 1)->bmAttributes != 0x01 ||
get_endpoint(alts, 1)->bSynchAddress != 0) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
@@ -2002,7 +2006,7 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
/* check the format byte size */
switch (fmt[5]) {
case 1:
- pcm_format = SNDRV_PCM_FORMAT_U8;
+ pcm_format = SNDRV_PCM_FORMAT_S8;
break;
case 2:
pcm_format = SNDRV_PCM_FORMAT_S16_LE;
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 0d63caf275ed..f8ead93d0b0b 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -1358,6 +1358,9 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
return -EINVAL;
}
+ if (num_ins == 1) /* only one ? nonsense! */
+ return 0;
+
if (check_ignored_ctl(state, unitid, 0))
return 0;
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index a6d0fc44c9c6..9352b479fa8a 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -755,6 +755,19 @@
}
}
},
+{
+ USB_DEVICE_VENDOR_SPEC(0x0763, 0x2008),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "M-Audio",
+ .product_name = "Ozone",
+ .ifnum = 3,
+ .type = QUIRK_MIDI_MIDIMAN,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ }
+},
/* Mark of the Unicorn devices */
{