2002-10-01 17:04:12

by Jaroslav Kysela

[permalink] [raw]
Subject: [PATCH] 2nd ALSA update [9/12] - 2002/09/11

You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


[email protected], 2002-10-01 15:33:54+02:00, [email protected]
ALSA update 2002/09/11 :
- AC'97 codec
- added support/detection for MC'97 (modem codecs)
- improved/updated register bit constants
- AD1980 codec ID with patch code
- added eMicro and Philips UCB1400 codecs
- PCM Scatter-Gather support
- added a function snd_pcm_sgbuf_get_addr()
- rewritten PCI DMA allocation
- ENS1371 - fixed IEC958 control index when AC'97 codec has S/PDIF capability, too
- intel8x0
- don't break when second codec cannot be initialized
- via82xx
- improved sg buffer handling
- added "Input Source Select" control for via8233
- fixed the registers for via8233
- fixed the detection of via8233 chip
- clean up the configuration of bd arrays
- USB Audio
- added the missing initialization of curframesize field (fixes capture)


include/sound/ac97_codec.h | 56 ++++++++-
include/sound/pcm_sgbuf.h | 7 +
include/sound/version.h | 2
sound/core/Makefile | 14 +-
sound/core/isadma.c | 4
sound/core/memory.c | 41 +++---
sound/drivers/dummy.c | 2
sound/pci/ac97/ac97_codec.c | 223 +++++++++++++++++++++++--------------
sound/pci/ac97/ac97_patch.c | 13 ++
sound/pci/ac97/ac97_patch.h | 1
sound/pci/ens1370.c | 5
sound/pci/intel8x0.c | 7 -
sound/pci/maestro3.c | 3
sound/pci/via82xx.c | 260 ++++++++++++++++++++++++--------------------
sound/usb/usbaudio.c | 1
15 files changed, 400 insertions(+), 239 deletions(-)


diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
--- a/include/sound/ac97_codec.h Tue Oct 1 17:08:58 2002
+++ b/include/sound/ac97_codec.h Tue Oct 1 17:08:58 2002
@@ -54,7 +54,7 @@
#define AC97_POWERDOWN 0x26 /* Powerdown control / status */
/* range 0x28-0x3a - AUDIO AC'97 2.0 extensions */
#define AC97_EXTENDED_ID 0x28 /* Extended Audio ID */
-#define AC97_EXTENDED_STATUS 0x2a /* Extended Audio Status */
+#define AC97_EXTENDED_STATUS 0x2a /* Extended Audio Status and Control */
#define AC97_PCM_FRONT_DAC_RATE 0x2c /* PCM Front DAC Rate */
#define AC97_PCM_SURR_DAC_RATE 0x2e /* PCM Surround DAC Rate */
#define AC97_PCM_LFE_DAC_RATE 0x30 /* PCM LFE DAC Rate */
@@ -64,10 +64,40 @@
#define AC97_SURROUND_MASTER 0x38 /* Surround (Rear) Master Volume */
#define AC97_SPDIF 0x3a /* S/PDIF control */
/* range 0x3c-0x58 - MODEM */
+#define AC97_EXTENDED_MID 0x3c /* Extended Modem ID */
+#define AC97_EXTENDED_MSTATUS 0x3e /* Extended Modem Status and Control */
+#define AC97_LINE1_RATE 0x40 /* Line1 DAC/ADC Rate */
+#define AC97_LINE2_RATE 0x42 /* Line2 DAC/ADC Rate */
+#define AC97_HANDSET_RATE 0x44 /* Handset DAC/ADC Rate */
+#define AC97_LINE1_LEVEL 0x46 /* Line1 DAC/ADC Level */
+#define AC97_LINE2_LEVEL 0x48 /* Line2 DAC/ADC Level */
+#define AC97_HANDSET_LEVEL 0x4a /* Handset DAC/ADC Level */
+#define AC97_GPIO_CFG 0x4c /* GPIO Configuration */
+#define AC97_GPIO_POLARITY 0x4e /* GPIO Pin Polarity/Type, 0=low, 1=high active */
+#define AC97_GPIO_STICKY 0x50 /* GPIO Pin Sticky, 0=not, 1=sticky */
+#define AC97_GPIO_WAKEUP 0x52 /* GPIO Pin Wakeup, 0=no int, 1=yes int */
+#define AC97_GPIO_STATUS 0x54 /* GPIO Pin Status, slot 12 */
+#define AC97_MISC_AFE 0x56 /* Miscellaneous Modem AFE Status and Control */
/* range 0x5a-0x7b - Vendor Specific */
#define AC97_VENDOR_ID1 0x7c /* Vendor ID1 */
#define AC97_VENDOR_ID2 0x7e /* Vendor ID2 / revision */

+/* basic capabilities (reset register) */
+#define AC97_BC_DEDICATED_MIC 0x0001 /* Dedicated Mic PCM In Channel */
+#define AC97_BC_RESERVED1 0x0002 /* Reserved (was Modem Line Codec support) */
+#define AC97_BC_BASS_TREBLE 0x0004 /* Bass & Treble Control */
+#define AC97_BC_SIM_STEREO 0x0008 /* Simulated stereo */
+#define AC97_BC_HEADPHONE 0x0010 /* Headphone Out Support */
+#define AC97_BC_LOUDNESS 0x0020 /* Loudness (bass boost) Supporqt */
+#define AC97_BC_16BIT_DAC 0x0000 /* 16-bit DAC resolution */
+#define AC97_BC_18BIT_DAC 0x0040 /* 18-bit DAC resolution */
+#define AC97_BC_20BIT_DAC 0x0080 /* 20-bit DAC resolution */
+#define AC97_BC_DAC_MASK 0x00c0
+#define AC97_BC_16BIT_ADC 0x0000 /* 16-bit ADC resolution */
+#define AC97_BC_18BIT_ADC 0x0100 /* 18-bit ADC resolution */
+#define AC97_BC_20BIT_ADC 0x0200 /* 20-bit ADC resolution */
+#define AC97_BC_ADC_MASK 0x0300
+
/* extended audio ID bit defines */
#define AC97_EI_VRA 0x0001 /* Variable bit rate supported */
#define AC97_EI_DRA 0x0002 /* Double rate supported */
@@ -80,8 +110,8 @@
#define AC97_EI_LDAC 0x0100 /* PCM LFE DAC available */
#define AC97_EI_AMAP 0x0200 /* indicates optional slot/DAC mapping based on codec ID */
#define AC97_EI_REV_MASK 0x0c00 /* AC'97 revision mask */
-#define AC97_EI_REV_22 0x0100 /* AC'97 revision 2.2 */
-#define AC97_EI_REV_SHIFT 8
+#define AC97_EI_REV_22 0x0400 /* AC'97 revision 2.2 */
+#define AC97_EI_REV_SHIFT 10
#define AC97_EI_ADDR_MASK 0xc000 /* physical codec ID (address) */
#define AC97_EI_ADDR_SHIFT 14

@@ -112,14 +142,25 @@
#define AC97_SC_COPY 0x0004 /* Copyright status */
#define AC97_SC_PRE 0x0008 /* Preemphasis status */
#define AC97_SC_CC_MASK 0x07f0 /* Category Code mask */
+#define AC97_SC_CC_SHIFT 4
#define AC97_SC_L 0x0800 /* Generation Level status */
-#define AC97_SC_SPSR_MASK 0xcfff /* S/PDIF Sample Rate bits */
+#define AC97_SC_SPSR_MASK 0x3000 /* S/PDIF Sample Rate bits */
+#define AC97_SC_SPSR_SHIFT 12
#define AC97_SC_SPSR_44K 0x0000 /* Use 44.1kHz Sample rate */
#define AC97_SC_SPSR_48K 0x2000 /* Use 48kHz Sample rate */
#define AC97_SC_SPSR_32K 0x3000 /* Use 32kHz Sample rate */
#define AC97_SC_DRS 0x4000 /* Double Rate S/PDIF */
#define AC97_SC_V 0x8000 /* Validity status */

+/* extended modem ID bit defines */
+#define AC97_MEI_LINE1 0x0001 /* Line1 present */
+#define AC97_MEI_LINE2 0x0002 /* Line2 present */
+#define AC97_MEI_HEADSET 0x0004 /* Headset present */
+#define AC97_MEI_CID1 0x0008 /* caller ID decode for Line1 is supported */
+#define AC97_MEI_CID2 0x0010 /* caller ID decode for Line2 is supported */
+#define AC97_MEI_ADDR_MASK 0xc000 /* physical codec ID (address) */
+#define AC97_MEI_ADDR_SHIFT 14
+
/* specific - SigmaTel */
#define AC97_SIGMATEL_ANALOG 0x6c /* Analog Special */
#define AC97_SIGMATEL_DAC2INVERT 0x6e
@@ -154,8 +195,10 @@
#define AC97_CXR_SPDIF_AC3 0x2

/* ac97->scaps */
-#define AC97_SCAP_SURROUND_DAC (1<<0) /* surround L&R DACs are present */
-#define AC97_SCAP_CENTER_LFE_DAC (1<<1) /* center and LFE DACs are present */
+#define AC97_SCAP_AUDIO (1<<0) /* audio AC'97 codec */
+#define AC97_SCAP_MODEM (1<<1) /* modem AC'97 codec */
+#define AC97_SCAP_SURROUND_DAC (1<<2) /* surround L&R DACs are present */
+#define AC97_SCAP_CENTER_LFE_DAC (1<<3) /* center and LFE DACs are present */

/* ac97->flags */
#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */
@@ -195,6 +238,7 @@
unsigned int id; /* identification of codec */
unsigned short caps; /* capabilities (register 0) */
unsigned short ext_id; /* extended feature identification (register 28) */
+ unsigned short ext_mid; /* extended modem ID (register 3C) */
unsigned int scaps; /* driver capabilities */
unsigned int flags; /* specific code */
unsigned int clock; /* AC'97 clock (usually 48000Hz) */
diff -Nru a/include/sound/pcm_sgbuf.h b/include/sound/pcm_sgbuf.h
--- a/include/sound/pcm_sgbuf.h Tue Oct 1 17:08:58 2002
+++ b/include/sound/pcm_sgbuf.h Tue Oct 1 17:08:58 2002
@@ -45,6 +45,13 @@
return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
}

+/*
+ * return the physical address at the corresponding offset
+ */
+static inline dma_addr_t snd_pcm_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t offset)
+{
+ return sgbuf->table[offset >> PAGE_SHIFT].addr + offset % PAGE_SIZE;
+}

int snd_pcm_sgbuf_init(snd_pcm_substream_t *substream, struct pci_dev *pci, int tblsize);
int snd_pcm_sgbuf_delete(snd_pcm_substream_t *substream);
diff -Nru a/include/sound/version.h b/include/sound/version.h
--- a/include/sound/version.h Tue Oct 1 17:08:58 2002
+++ b/include/sound/version.h Tue Oct 1 17:08:58 2002
@@ -1,3 +1,3 @@
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc3"
-#define CONFIG_SND_DATE " (Fri Sep 06 15:06:56 2002 UTC)"
+#define CONFIG_SND_DATE " (Wed Sep 11 18:36:14 2002 UTC)"
diff -Nru a/sound/core/Makefile b/sound/core/Makefile
--- a/sound/core/Makefile Tue Oct 1 17:08:58 2002
+++ b/sound/core/Makefile Tue Oct 1 17:08:58 2002
@@ -3,17 +3,23 @@
# Copyright (c) 1999,2001 by Jaroslav Kysela <[email protected]>
#

-export-objs := sound.o pcm.o pcm_lib.o rawmidi.o timer.o hwdep.o \
- pcm_sgbuf.o
+export-objs := sound.o pcm.o pcm_lib.o rawmidi.o timer.o hwdep.o

-snd-objs := sound.o init.o isadma.o memory.o info.o control.o misc.o \
+snd-objs := sound.o init.o memory.o info.o control.o misc.o \
device.o wrappers.o
+ifeq ($(CONFIG_ISA),y)
+snd-objs += isadma.o
+endif
ifeq ($(CONFIG_SND_OSSEMUL),y)
snd-objs += sound_oss.o info_oss.o
endif

snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
- pcm_memory.o pcm_sgbuf.o
+ pcm_memory.o
+ifeq ($(CONFIG_PCI),y)
+snd-pcm-objs += pcm_sgbuf.o
+export-objs += pcm_sgbuf.o
+endif

snd-rawmidi-objs := rawmidi.o
snd-timer-objs := timer.o
diff -Nru a/sound/core/isadma.c b/sound/core/isadma.c
--- a/sound/core/isadma.c Tue Oct 1 17:08:58 2002
+++ b/sound/core/isadma.c Tue Oct 1 17:08:58 2002
@@ -30,8 +30,6 @@
#include <sound/core.h>
#include <asm/dma.h>

-#ifdef CONFIG_ISA
-
/*
*
*/
@@ -78,5 +76,3 @@
release_dma_lock(flags);
return result;
}
-
-#endif /* CONFIG_ISA */
diff -Nru a/sound/core/memory.c b/sound/core/memory.c
--- a/sound/core/memory.c Tue Oct 1 17:08:58 2002
+++ b/sound/core/memory.c Tue Oct 1 17:08:58 2002
@@ -545,35 +545,36 @@
*
* since pci_alloc_consistent always tries GFP_DMA when the requested
* pci memory region is below 32bit, it happens quite often that even
- * 2 order or pages cannot be allocated.
+ * 2 order of pages cannot be allocated.
*
- * so in the following, GFP_DMA is used only when the first allocation
- * doesn't match the requested region.
+ * so in the following, we allocate at first without dma_mask, so that
+ * allocation will be done without GFP_DMA. if the area doesn't match
+ * with the requested region, then realloate with the original dma_mask
+ * again.
*/
-#ifdef __i386__
-#define get_phys_addr(x) virt_to_phys(x)
-#else /* ppc and x86-64 */
-#define get_phys_addr(x) virt_to_bus(x)
-#endif
+
+#undef pci_alloc_consistent
+
void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
void *ret;
- int gfp = GFP_ATOMIC;
+ u64 dma_mask;
+ unsigned long rmask;

if (hwdev == NULL)
- gfp |= GFP_DMA;
- ret = (void *)__get_free_pages(gfp, get_order(size));
- if (ret) {
- if (hwdev && ((get_phys_addr(ret) + size - 1) & ~hwdev->dma_mask)) {
- free_pages((unsigned long)ret, get_order(size));
- ret = (void *)__get_free_pages(gfp | GFP_DMA, get_order(size));
- }
- }
- if (ret) {
- memset(ret, 0, size);
- *dma_handle = get_phys_addr(ret);
+ return pci_alloc_consistent(hwdev, size, dma_handle);
+ dma_mask = hwdev->dma_mask;
+ rmask = ~((unsigned long)dma_mask);
+ hwdev->dma_mask = 0xffffffff; /* do without masking */
+ ret = pci_alloc_consistent(hwdev, size, dma_handle);
+ if (ret && ((*dma_handle + size - 1) & rmask)) {
+ pci_free_consistent(hwdev, size, ret, *dma_handle);
+ ret = 0;
}
+ hwdev->dma_mask = dma_mask; /* restore */
+ if (! ret)
+ ret = pci_alloc_consistent(hwdev, size, dma_handle);
return ret;
}
#endif /* hack */
diff -Nru a/sound/drivers/dummy.c b/sound/drivers/dummy.c
--- a/sound/drivers/dummy.c Tue Oct 1 17:08:58 2002
+++ b/sound/drivers/dummy.c Tue Oct 1 17:08:58 2002
@@ -446,7 +446,7 @@
left = ucontrol->value.integer.value[0] % 101;
right = ucontrol->value.integer.value[1] % 101;
spin_lock_irqsave(&dummy->mixer_lock, flags);
- change = dummy->mixer_volume[addr][0] != left &&
+ change = dummy->mixer_volume[addr][0] != left ||
dummy->mixer_volume[addr][1] != right;
dummy->mixer_volume[addr][0] = left;
dummy->mixer_volume[addr][1] = right;
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c Tue Oct 1 17:08:58 2002
+++ b/sound/pci/ac97/ac97_codec.c Tue Oct 1 17:08:58 2002
@@ -68,11 +68,13 @@
{ 0x434d4900, 0xffffff00, "C-Media Electronics", NULL },
{ 0x43525900, 0xffffff00, "Cirrus Logic", NULL },
{ 0x43585400, 0xffffff00, "Conexant", NULL },
+{ 0x454d4300, 0xffffff00, "eMicro", NULL },
{ 0x45838300, 0xffffff00, "ESS Technology", NULL },
{ 0x48525300, 0xffffff00, "Intersil", NULL },
{ 0x49434500, 0xffffff00, "ICEnsemble", NULL },
{ 0x49544500, 0xffffff00, "ITE Tech.Inc", NULL },
{ 0x4e534300, 0xffffff00, "National Semiconductor", NULL },
+{ 0x50534300, 0xffffff00, "Philips", NULL },
{ 0x53494c00, 0xffffff00, "Silicon Laboratory", NULL },
{ 0x54524100, 0xffffff00, "TriTech", NULL },
{ 0x54584e00, 0xffffff00, "Texas Instruments", NULL },
@@ -97,6 +99,7 @@
{ 0x41445361, 0xffffffff, "AD1886", patch_ad1886 },
{ 0x41445362, 0xffffffff, "AD1887", patch_ad1881 },
{ 0x41445363, 0xffffffff, "AD1886A", patch_ad1881 },
+{ 0x41445370, 0xffffffff, "AD1980", patch_ad1980 },
{ 0x41445372, 0xffffffff, "AD1981A", patch_ad1881 },
{ 0x414c4300, 0xfffffff0, "RL5306", NULL },
{ 0x414c4310, 0xfffffff0, "RL5382", NULL },
@@ -117,6 +120,7 @@
{ 0x43525958, 0xfffffff8, "CS4205", patch_cirrus_spdif },
{ 0x43525960, 0xfffffff8, "CS4291", NULL },
{ 0x43585429, 0xffffffff, "Cx20468", patch_conexant },
+{ 0x454d4328, 0xffffffff, "28028", NULL }, // same as TR28028?
{ 0x45838308, 0xffffffff, "ESS1988", NULL },
{ 0x48525300, 0xffffff00, "HMP9701", NULL },
{ 0x49434501, 0xffffffff, "ICE1230", NULL },
@@ -124,6 +128,7 @@
{ 0x49544520, 0xffffffff, "IT2226E", NULL },
{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL }, // only guess --jk
{ 0x4e534331, 0xffffffff, "LM4549", NULL },
+{ 0x50534304, 0xffffffff, "UCB1400", NULL },
{ 0x53494c22, 0xffffffff, "Si3036", NULL },
{ 0x53494c23, 0xffffffff, "Si3038", NULL },
{ 0x54524102, 0xffffffff, "TR28022", NULL },
@@ -1503,57 +1508,83 @@
/* the REC_GAIN register is used for tests */
end_time = jiffies + HZ;
do {
+ unsigned short ext_mid;
+
/* use preliminary reads to settle the communication */
snd_ac97_read(ac97, AC97_RESET);
snd_ac97_read(ac97, AC97_VENDOR_ID1);
snd_ac97_read(ac97, AC97_VENDOR_ID2);
- /* test if we can write to the PCM volume register */
+ /* modem? */
+ ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+ if (ext_mid != 0xffff && (ext_mid & 1) != 0)
+ goto __access_ok;
+ /* test if we can write to the record gain volume register */
snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
goto __access_ok;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/100);
} while (time_after_eq(end_time, jiffies));
- snd_printd("AC'97 %d:%d does not respond - RESET [REC_GAIN = 0x%x]\n", ac97->num, ac97->addr, err);
+ snd_printk("AC'97 %d:%d does not respond - RESET [REC_GAIN = 0x%x]\n", ac97->num, ac97->addr, err);
snd_ac97_free(ac97);
return -ENXIO;
}
__access_ok:
- ac97->caps = snd_ac97_read(ac97, AC97_RESET);
ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
- ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
- if (ac97->ext_id == 0xffff) /* invalid combination */
- ac97->ext_id = 0;
if (ac97->id == 0x00000000 || ac97->id == 0xffffffff) {
snd_printk("AC'97 %d:%d access is not valid [0x%x], removing mixer.\n", ac97->num, ac97->addr, ac97->id);
snd_ac97_free(ac97);
return -EIO;
}
+
+ /* test for AC'97 */
+ /* test if we can write to the record gain volume register */
+ snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06);
+ if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a06) {
+ ac97->scaps |= AC97_SCAP_AUDIO;
+ ac97->caps = snd_ac97_read(ac97, AC97_RESET);
+ ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
+ if (ac97->ext_id == 0xffff) /* invalid combination */
+ ac97->ext_id = 0;
+ }
+
+ /* test for MC'97 */
+ ac97->ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+ if (ac97->ext_mid == 0xffff) /* invalid combination */
+ ac97->ext_mid = 0;
+ if (ac97->ext_mid & 1)
+ ac97->scaps |= AC97_SCAP_MODEM;

if (ac97->reset) // FIXME: always skipping?
goto __ready_ok;

/* FIXME: add powerdown control */
/* nothing should be in powerdown mode */
- snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
- snd_ac97_write_cache_test(ac97, AC97_RESET, 0); /* reset to defaults */
- udelay(100);
- /* nothing should be in powerdown mode */
- snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
- snd_ac97_write_cache_test(ac97, AC97_GENERAL_PURPOSE, 0);
- end_time = jiffies + (HZ / 10);
- do {
- if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
- goto __ready_ok;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
- } while (time_after_eq(end_time, jiffies));
- snd_printk("AC'97 %d:%d analog subsections not ready\n", ac97->num, ac97->addr);
+ if (ac97->scaps & AC97_SCAP_AUDIO) {
+ snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
+ snd_ac97_write_cache_test(ac97, AC97_RESET, 0); /* reset to defaults */
+ udelay(100);
+ /* nothing should be in powerdown mode */
+ snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
+ snd_ac97_write_cache_test(ac97, AC97_GENERAL_PURPOSE, 0);
+ end_time = jiffies + (HZ / 10);
+ do {
+ if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
+ goto __ready_ok;
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/10);
+ } while (time_after_eq(end_time, jiffies));
+ snd_printk("AC'97 %d:%d analog subsections not ready\n", ac97->num, ac97->addr);
+ }
+
__ready_ok:
if (ac97->clock == 0)
ac97->clock = 48000; /* standard value */
- ac97->addr = (ac97->ext_id & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT;
+ if (ac97->scaps & AC97_SCAP_AUDIO)
+ ac97->addr = (ac97->ext_id & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT;
+ else
+ ac97->addr = (ac97->ext_mid & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT;
if (ac97->ext_id & 0x0189) /* L/R, MIC, SDAC, LDAC VRA support */
snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, ac97->ext_id & 0x0189);
if (ac97->ext_id & AC97_EI_VRA) { /* VRA support */
@@ -1595,9 +1626,17 @@
strcat(card->mixername, name);
}
}
- if ((err = snd_component_add(card, "AC97")) < 0) {
- snd_ac97_free(ac97);
- return err;
+ if (ac97->scaps & AC97_SCAP_AUDIO) {
+ if ((err = snd_component_add(card, "AC97a")) < 0) {
+ snd_ac97_free(ac97);
+ return err;
+ }
+ }
+ if (ac97->scaps & AC97_SCAP_MODEM) {
+ if ((err = snd_component_add(card, "AC97m")) < 0) {
+ snd_ac97_free(ac97);
+ return err;
+ }
}
if (snd_ac97_mixer_build(card, ac97) < 0) {
snd_ac97_free(ac97);
@@ -1620,7 +1659,7 @@
{
char name[64];
unsigned int id;
- unsigned short val, tmp, ext;
+ unsigned short val, tmp, ext, mext;
static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=res" };
static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" };
static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };
@@ -1631,24 +1670,24 @@
snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
val = snd_ac97_read(ac97, AC97_RESET);
snd_iprintf(buffer, "Capabilities :%s%s%s%s%s%s\n",
- val & 0x0001 ? " -dedicated MIC PCM IN channel-" : "",
- val & 0x0002 ? " -reserved1-" : "",
- val & 0x0004 ? " -bass & treble-" : "",
- val & 0x0008 ? " -simulated stereo-" : "",
- val & 0x0010 ? " -headphone out-" : "",
- val & 0x0020 ? " -loudness-" : "");
- tmp = ac97->caps & 0x00c0;
+ val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" : "",
+ val & AC97_BC_RESERVED1 ? " -reserved1-" : "",
+ val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",
+ val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",
+ val & AC97_BC_HEADPHONE ? " -headphone out-" : "",
+ val & AC97_BC_LOUDNESS ? " -loudness-" : "");
+ tmp = ac97->caps & AC97_BC_DAC_MASK;
snd_iprintf(buffer, "DAC resolution : %s%s%s%s\n",
- tmp == 0x0000 ? "16-bit" : "",
- tmp == 0x0040 ? "18-bit" : "",
- tmp == 0x0080 ? "20-bit" : "",
- tmp == 0x00c0 ? "???" : "");
- tmp = ac97->caps & 0x0300;
+ tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",
+ tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",
+ tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",
+ tmp == AC97_BC_DAC_MASK ? "???" : "");
+ tmp = ac97->caps & AC97_BC_ADC_MASK;
snd_iprintf(buffer, "ADC resolution : %s%s%s%s\n",
- tmp == 0x0000 ? "16-bit" : "",
- tmp == 0x0100 ? "18-bit" : "",
- tmp == 0x0200 ? "20-bit" : "",
- tmp == 0x0300 ? "???" : "");
+ tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",
+ tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",
+ tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",
+ tmp == AC97_BC_ADC_MASK ? "???" : "");
snd_iprintf(buffer, "3D enhancement : %s\n",
snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);
snd_iprintf(buffer, "\nCurrent setup\n");
@@ -1669,79 +1708,93 @@
val & 0x0200 ? "Mic" : "MIX",
val & 0x0100 ? "Mic2" : "Mic1",
val & 0x0080 ? "on" : "off");
- ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);

+ ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
if (ext == 0)
- return;
+ goto __modem;
+
snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n",
- (ext >> 14) & 3,
- (ext >> 10) & 3,
- ext & 0x0200 ? " AMAP" : "",
- ext & 0x0100 ? " LDAC" : "",
- ext & 0x0080 ? " SDAC" : "",
- ext & 0x0040 ? " CDAC" : "",
- (ext >> 4) & 3,
- ext & 0x0008 ? " VRM" : "",
- ext & 0x0004 ? " SPDIF" : "",
- ext & 0x0002 ? " DRA" : "",
- ext & 0x0001 ? " VRA" : "");
+ (ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,
+ (ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,
+ ext & AC97_EI_AMAP ? " AMAP" : "",
+ ext & AC97_EI_LDAC ? " LDAC" : "",
+ ext & AC97_EI_SDAC ? " SDAC" : "",
+ ext & AC97_EI_CDAC ? " CDAC" : "",
+ (ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,
+ ext & AC97_EI_VRM ? " VRM" : "",
+ ext & AC97_EI_SPDIF ? " SPDIF" : "",
+ ext & AC97_EI_DRA ? " DRA" : "",
+ ext & AC97_EI_VRA ? " VRA" : "");
val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
- val & 0x4000 ? " PRL" : "",
- val & 0x2000 ? " PRK" : "",
- val & 0x1000 ? " PRJ" : "",
- val & 0x0800 ? " PRI" : "",
- val & 0x0400 ? " SPCV" : "",
- val & 0x0200 ? " MADC" : "",
- val & 0x0100 ? " LDAC" : "",
- val & 0x0080 ? " SDAC" : "",
- val & 0x0040 ? " CDAC" : "",
- ext & 0x0004 ? spdif_slots[(val & 0x0030) >> 4] : "",
- val & 0x0008 ? " VRM" : "",
- val & 0x0004 ? " SPDIF" : "",
- val & 0x0002 ? " DRA" : "",
- val & 0x0001 ? " VRA" : "");
- if (ext & 1) { /* VRA */
+ val & AC97_EA_PRL ? " PRL" : "",
+ val & AC97_EA_PRK ? " PRK" : "",
+ val & AC97_EA_PRJ ? " PRJ" : "",
+ val & AC97_EA_PRI ? " PRI" : "",
+ val & AC97_EA_SPCV ? " SPCV" : "",
+ val & AC97_EA_MDAC ? " MADC" : "",
+ val & AC97_EA_LDAC ? " LDAC" : "",
+ val & AC97_EA_SDAC ? " SDAC" : "",
+ val & AC97_EA_CDAC ? " CDAC" : "",
+ ext & AC97_EI_SPDIF ? spdif_slots[(val & AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",
+ val & AC97_EA_VRM ? " VRM" : "",
+ val & AC97_EA_SPDIF ? " SPDIF" : "",
+ val & AC97_EA_DRA ? " DRA" : "",
+ val & AC97_EA_VRA ? " VRA" : "");
+ if (ext & AC97_EI_VRA) { /* VRA */
val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);
snd_iprintf(buffer, "PCM front DAC : %iHz\n", val);
- if (ext & 0x0080) {
+ if (ext & AC97_EI_SDAC) {
val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);
snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val);
}
- if (ext & 0x0100) {
+ if (ext & AC97_EI_LDAC) {
val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);
snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val);
}
val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);
snd_iprintf(buffer, "PCM ADC : %iHz\n", val);
}
- if (ext & 0x0008) {
+ if (ext & AC97_EI_VRM) {
val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val);
}
- if ((ext & 0x0004) || (ac97->flags & AC97_CS_SPDIF)) {
+ if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) {
if (ac97->flags & AC97_CS_SPDIF)
val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
else
val = snd_ac97_read(ac97, AC97_SPDIF);

snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",
- val & 0x0001 ? " PRO" : " Consumer",
- val & 0x0002 ? " Non-audio" : " PCM",
- val & 0x0004 ? " Copyright" : "",
- val & 0x0008 ? " Preemph50/15" : "",
- (val & 0x07f0) >> 4,
- (val & 0x0800) >> 11,
+ val & AC97_SC_PRO ? " PRO" : " Consumer",
+ val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
+ 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,
(ac97->flags & AC97_CS_SPDIF) ?
- spdif_rates_cs4205[(val & 0x3000) >> 12] :
- spdif_rates[(val & 0x3000) >> 12],
+ spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT] :
+ spdif_rates[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT],
(ac97->flags & AC97_CS_SPDIF) ?
- (val & 0x4000 ? " Validity" : "") :
- (val & 0x4000 ? " DRS" : ""),
+ (val & AC97_SC_DRS ? " Validity" : "") :
+ (val & AC97_SC_DRS ? " DRS" : ""),
(ac97->flags & AC97_CS_SPDIF) ?
- (val & 0x8000 ? " Enabled" : "") :
- (val & 0x8000 ? " Validity" : ""));
+ (val & AC97_SC_V ? " Enabled" : "") :
+ (val & AC97_SC_V ? " Validity" : ""));
}
+
+ __modem:
+ mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+ if (mext == 0)
+ return;
+
+ snd_iprintf(buffer, "Extended modem ID: codec=%i %s%s%s%s%s\n",
+ (mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,
+ mext & AC97_MEI_CID2 ? " CID2" : "",
+ mext & AC97_MEI_CID1 ? " CID1" : "",
+ mext & AC97_MEI_HEADSET ? " HSET" : "",
+ mext & AC97_MEI_LINE2 ? " LIN2" : "",
+ mext & AC97_MEI_LINE1 ? " LIN1" : "");
}

static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
diff -Nru a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
--- a/sound/pci/ac97/ac97_patch.c Tue Oct 1 17:08:58 2002
+++ b/sound/pci/ac97/ac97_patch.c Tue Oct 1 17:08:58 2002
@@ -31,6 +31,7 @@
#include <sound/ac97_codec.h>
#include <sound/asoundef.h>
#include <sound/initval.h>
+#include "ac97_patch.h"

/*
* Chip specific initialization
@@ -321,5 +322,17 @@
/* Presario700 workaround */
/* for Jack Sense/SPDIF Register misetting causing */
snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
+ return 0;
+}
+
+int patch_ad1980(ac97_t * ac97)
+{
+ unsigned short misc;
+
+ patch_ad1881(ac97);
+ /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
+ /* it seems that most vendors connect line-out connector to headphone out of AC'97 */
+ misc = snd_ac97_read(ac97, AC97_AD_MISC);
+ snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 0x0420);
return 0;
}
diff -Nru a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
--- a/sound/pci/ac97/ac97_patch.h Tue Oct 1 17:08:58 2002
+++ b/sound/pci/ac97/ac97_patch.h Tue Oct 1 17:08:58 2002
@@ -37,3 +37,4 @@
int patch_ad1881(ac97_t * ac97);
int patch_ad1885(ac97_t * ac97);
int patch_ad1886(ac97_t * ac97);
+int patch_ad1980(ac97_t * ac97);
diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c
--- a/sound/pci/ens1370.c Tue Oct 1 17:08:58 2002
+++ b/sound/pci/ens1370.c Tue Oct 1 17:08:58 2002
@@ -1319,7 +1319,10 @@
if (ensoniq->pci->vendor == es1371_spdif_present[idx].vid &&
ensoniq->pci->device == es1371_spdif_present[idx].did &&
ensoniq->rev == es1371_spdif_present[idx].rev) {
- snd_ctl_add(card, snd_ctl_new1(&snd_es1371_mixer_spdif, ensoniq));
+ snd_kcontrol_t *kctl = snd_ctl_new1(&snd_es1371_mixer_spdif, ensoniq);
+ if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
+ kctl->id.index = 1;
+ snd_ctl_add(card, kctl);
break;
}
return 0;
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c Tue Oct 1 17:08:58 2002
+++ b/sound/pci/intel8x0.c Tue Oct 1 17:08:58 2002
@@ -1580,8 +1580,11 @@
goto __skip_secondary;
for (i = 1; i < codecs; i++) {
ac97.num = i;
- if ((err = snd_ac97_mixer(chip->card, &ac97, &x97)) < 0)
- return err;
+ if ((err = snd_ac97_mixer(chip->card, &ac97, &x97)) < 0) {
+ snd_printk("Unable to initialize codec #%i [device = %i, GLOB_STA = 0x%x]\n", i, chip->device_type, glob_sta);
+ codecs = i;
+ break;
+ }
chip->ac97[i] = x97;
if (chip->device_type == DEVICE_INTEL_ICH4 && chip->ichd[ICHD_PCM2IN].ac97 == NULL)
chip->ichd[ICHD_PCM2IN].ac97 = x97;
diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c
--- a/sound/pci/maestro3.c Tue Oct 1 17:08:58 2002
+++ b/sound/pci/maestro3.c Tue Oct 1 17:08:58 2002
@@ -1,5 +1,5 @@
/*
- * Driver for ESS Maestro3/Allegro soundcards.
+ * Driver for ESS Maestro3/Allegro (ES1988) soundcards.
* Copyright (c) 2000 by Zach Brown <[email protected]>
* Takashi Iwai <[email protected]>
*
@@ -52,6 +52,7 @@
MODULE_LICENSE("GPL");
MODULE_CLASSES("{sound}");
MODULE_DEVICES("{{ESS,Maestro3 PCI},"
+ "{ESS,ES1988},"
"{ESS,Allegro PCI},"
"{ESS,Allegro-1 PCI},"
"{ESS,Canyon3D-2/LE PCI}}");
diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c
--- a/sound/pci/via82xx.c Tue Oct 1 17:08:58 2002
+++ b/sound/pci/via82xx.c Tue Oct 1 17:08:58 2002
@@ -124,7 +124,7 @@
#define VIA8233_REG_TYPE_16BIT 0x00200000 /* RW */
#define VIA8233_REG_TYPE_STEREO 0x00100000 /* RW */
#define VIA_REG_OFFSET_CURR_COUNT 0x0c /* dword - channel current count (24 bit) */
-#define VIA_REG_OFFSET_CURR_INDEX 0x0f /* byte - channel current index */
+#define VIA_REG_OFFSET_CURR_INDEX 0x0f /* byte - channel current index (for via8233 only) */

#define DEFINE_VIA_REGSET(name,val) \
enum {\
@@ -159,8 +159,8 @@
#define VIA_REG_SGD_SHADOW 0x84 /* dword */

/* multi-channel and capture registers for via8233 */
-DEFINE_VIA_REGSET(MULTPLAY, 0x20);
-DEFINE_VIA_REGSET(CAPTURE_8233, 0x10);
+DEFINE_VIA_REGSET(MULTPLAY, 0x40);
+DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);

/* via8233-specific registers */
#define VIA_REG_PLAYBACK_VOLUME_L 0x02 /* byte */
@@ -183,66 +183,83 @@
* pcm stream
*/

+struct snd_via_sg_table {
+ unsigned int offset;
+ unsigned int size;
+} ;
+
+#define VIA_TABLE_SIZE 255
+
typedef struct {
unsigned long reg_offset;
snd_pcm_substream_t *substream;
int running;
- unsigned int size;
- unsigned int fragsize;
- unsigned int frags;
- unsigned int lastptr;
- unsigned int lastcount;
- unsigned int page_per_frag;
- unsigned int curidx;
- unsigned int tbl_entries; /* number of descriptor table entries */
- unsigned int tbl_size; /* size of a table entry */
+ unsigned int tbl_entries; /* # descriptors */
u32 *table; /* physical address + flag */
dma_addr_t table_addr;
+ struct snd_via_sg_table *idx_table;
} viadev_t;


static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
struct pci_dev *pci)
{
- int i, size;
+ int i, idx, ofs, rest, fragsize;
+ snd_pcm_runtime_t *runtime = substream->runtime;
struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return -EINVAL);

- if (dev->table) {
- snd_free_pci_pages(pci, PAGE_ALIGN(dev->tbl_entries * 8), dev->table, dev->table_addr);
- dev->table = NULL;
- }
-
- /* allocate buffer descriptor lists */
- if (dev->fragsize < PAGE_SIZE) {
- dev->tbl_size = dev->fragsize;
- dev->tbl_entries = dev->frags;
- dev->page_per_frag = 1;
- } else {
- dev->tbl_size = PAGE_SIZE;
- dev->tbl_entries = sgbuf->pages;
- dev->page_per_frag = dev->fragsize >> PAGE_SHIFT;
- }
- /* the start of each lists must be aligned to 8 bytes,
- * but the kernel pages are much bigger, so we don't care
- */
- dev->table = (u32*)snd_malloc_pci_pages(pci, PAGE_ALIGN(dev->tbl_entries * 8), &dev->table_addr);
- if (! dev->table)
- return -ENOMEM;
-
- if (dev->tbl_size < PAGE_SIZE) {
- for (i = 0; i < dev->tbl_entries; i++)
- dev->table[i << 1] = cpu_to_le32((u32)sgbuf->table[0].addr + dev->fragsize * i);
- } else {
- for (i = 0; i < dev->tbl_entries; i++)
- dev->table[i << 1] = cpu_to_le32((u32)sgbuf->table[i].addr);
- }
- size = dev->size;
- for (i = 0; i < dev->tbl_entries - 1; i++) {
- dev->table[(i << 1) + 1] = cpu_to_le32(VIA_TBL_BIT_FLAG | dev->tbl_size);
- size -= dev->tbl_size;
+ if (! dev->table) {
+ /* the start of each lists must be aligned to 8 bytes,
+ * but the kernel pages are much bigger, so we don't care
+ */
+ dev->table = (u32*)snd_malloc_pci_pages(pci, PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8), &dev->table_addr);
+ if (! dev->table)
+ return -ENOMEM;
+ }
+ if (! dev->idx_table) {
+ dev->idx_table = kmalloc(sizeof(unsigned int) * VIA_TABLE_SIZE, GFP_KERNEL);
+ if (! dev->idx_table)
+ return -ENOMEM;
+ }
+
+ /* fill the entries */
+ fragsize = snd_pcm_lib_period_bytes(substream);
+ idx = 0;
+ ofs = 0;
+ for (i = 0; i < runtime->periods; i++) {
+ rest = fragsize;
+ /* fill descriptors for a period.
+ * a period can be split to several descriptors if it's
+ * over page boundary.
+ */
+ do {
+ int r;
+ unsigned int flag;
+ dev->table[idx << 1] = cpu_to_le32((u32)snd_pcm_sgbuf_get_addr(sgbuf, ofs));
+ r = PAGE_SIZE - (ofs % PAGE_SIZE);
+ if (rest < r)
+ r = rest;
+ rest -= r;
+ if (! rest) {
+ if (i == runtime->periods - 1)
+ flag = VIA_TBL_BIT_EOL; /* buffer boundary */
+ else
+ flag = VIA_TBL_BIT_FLAG; /* period boundary */
+ } else
+ flag = 0; /* period continues to the next */
+ // printk("via: tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest);
+ dev->table[(idx<<1) + 1] = cpu_to_le32(r | flag);
+ dev->idx_table[idx].offset = ofs;
+ dev->idx_table[idx].size = r;
+ ofs += r;
+ idx++;
+ if (idx >= VIA_TABLE_SIZE) {
+ snd_printk(KERN_ERR "via82xx: too much table size!\n");
+ return -EINVAL;
+ }
+ } while (rest > 0);
}
- dev->table[(dev->tbl_entries << 1) - 1] = cpu_to_le32(VIA_TBL_BIT_EOL | size);
-
+ dev->tbl_entries = idx;
return 0;
}

@@ -254,13 +271,17 @@
snd_free_pci_pages(pci, PAGE_ALIGN(dev->tbl_entries * 8), dev->table, dev->table_addr);
dev->table = NULL;
}
+ if (dev->idx_table) {
+ kfree(dev->idx_table);
+ dev->idx_table = NULL;
+ }
}


/*
*/

-enum { TYPE_VIA686, TYPE_VIA8233 };
+enum { TYPE_VIA686 = 1, TYPE_VIA8233 };

typedef struct _snd_via82xx via82xx_t;
#define chip_t via82xx_t
@@ -295,8 +316,8 @@
};

static struct pci_device_id snd_via82xx_ids[] __devinitdata = {
- { 0x1106, 0x3058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 686A */
- { 0x1106, 0x3059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* VT8233 */
+ { 0x1106, 0x3058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_VIA686, }, /* 686A */
+ { 0x1106, 0x3059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_VIA8233, }, /* VT8233 */
{ 0, }
};

@@ -456,21 +477,7 @@
{
snd_pcm_runtime_t *runtime = substream->runtime;
unsigned long port = chip->port + viadev->reg_offset;
- int v, err;
-
- viadev->size = snd_pcm_lib_buffer_bytes(substream);
- viadev->fragsize = snd_pcm_lib_period_bytes(substream);
- viadev->frags = runtime->periods;
- viadev->lastptr = ~0;
- viadev->lastcount = ~0;
- viadev->curidx = 0;
-
- /* the period size must be in power of 2 */
- v = ld2(viadev->fragsize);
- if (viadev->fragsize != (1 << v)) {
- snd_printd(KERN_ERR "invalid fragment size %d\n", viadev->fragsize);
- return -EINVAL;
- }
+ int err;

snd_via82xx_channel_reset(chip, viadev);

@@ -478,7 +485,6 @@
if (err < 0)
return err;

- runtime->dma_bytes = viadev->size;
outl((u32)viadev->table_addr, port + VIA_REG_OFFSET_TABLE_PTR);
switch (chip->chip_type) {
case TYPE_VIA686:
@@ -524,13 +530,9 @@
{
outb(VIA_REG_STAT_FLAG | VIA_REG_STAT_EOL, VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset);
if (viadev->substream && viadev->running) {
- viadev->curidx++;
- if (viadev->curidx >= viadev->page_per_frag) {
- viadev->curidx = 0;
- spin_unlock(&chip->reg_lock);
- snd_pcm_period_elapsed(viadev->substream);
- spin_lock(&chip->reg_lock);
- }
+ spin_unlock(&chip->reg_lock);
+ snd_pcm_period_elapsed(viadev->substream);
+ spin_lock(&chip->reg_lock);
}
}

@@ -613,10 +615,8 @@
snd_pcm_runtime_t *runtime = substream->runtime;

snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
- if (chip->chip_type == TYPE_VIA8233) {
- outb(VIA_REG_CAPTURE_CHANNEL_LINE, VIAREG(chip, CAPTURE_CHANNEL));
+ if (chip->chip_type == TYPE_VIA8233)
outb(VIA_REG_CAPTURE_FIFO_ENABLE, VIAREG(chip, CAPTURE_FIFO));
- }
return snd_via82xx_setup_periods(chip, &chip->capture, substream);
}

@@ -624,43 +624,33 @@
{
unsigned int val, ptr, count;

- ptr = inl(VIAREG(chip, OFFSET_CURR_PTR) + viadev->reg_offset)/* & 0xffffff*/;
+ snd_assert(viadev->tbl_entries, return 0);
+ if (!(inb(VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset) & VIA_REG_STAT_ACTIVE))
+ return 0;
+
+ count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset) & 0xffffff;
switch (chip->chip_type) {
case TYPE_VIA686:
- count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset);
- if (ptr == viadev->lastptr && count > viadev->lastcount)
- ptr += 8;
- if (!(inb(VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset) & VIA_REG_STAT_ACTIVE))
- return 0;
- snd_assert(viadev->tbl_entries, return 0);
- /* get index */
+ /* The via686a does not have the current index register,
+ * so we need to calculate the index from CURR_PTR.
+ */
+ ptr = inl(VIAREG(chip, OFFSET_CURR_PTR) + viadev->reg_offset);
if (ptr <= (unsigned int)viadev->table_addr)
val = 0;
- else
+ else /* CURR_PTR holds the address + 8 */
val = ((ptr - (unsigned int)viadev->table_addr) / 8 - 1) % viadev->tbl_entries;
- viadev->lastptr = ptr;
- viadev->lastcount = count;
break;

case TYPE_VIA8233:
default:
- count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset) & 0xffffff;
- /* The via686a does not have this current index register,
- * this register makes life easier for us here. */
+ /* ah, this register makes life easier for us here. */
val = inb(VIAREG(chip, OFFSET_CURR_INDEX) + viadev->reg_offset) % viadev->tbl_entries;
break;
}

/* convert to the linear position */
- if (val < viadev->tbl_entries - 1) {
- val *= viadev->tbl_size;
- val += viadev->tbl_size - count;
- } else {
- val *= viadev->tbl_size;
- val += (viadev->size % viadev->tbl_size) + 1 - count;
- }
- // printk("pointer: ptr = 0x%x (%i), count = 0x%x, val = 0x%x\n", ptr, count, val);
- return val;
+ return viadev->idx_table[val].offset +
+ viadev->idx_table[val].size - count;
}

static snd_pcm_uframes_t snd_via82xx_playback_pointer(snd_pcm_substream_t * substream)
@@ -691,7 +681,7 @@
.period_bytes_min = 32,
.period_bytes_max = 128 * 1024,
.periods_min = 2,
- .periods_max = 128,
+ .periods_max = VIA_TABLE_SIZE / 2,
.fifo_size = 0,
};

@@ -710,7 +700,7 @@
.period_bytes_min = 32,
.period_bytes_max = 128 * 1024,
.periods_min = 2,
- .periods_max = 128,
+ .periods_max = VIA_TABLE_SIZE / 2,
.fifo_size = 0,
};

@@ -739,18 +729,10 @@
runtime->hw.rate_min = 48000;
if ((err = snd_pcm_sgbuf_init(substream, chip->pci, 32)) < 0)
return err;
- if ((err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0)
- return err;
/* we may remove following constaint when we modify table entries
in interrupt */
-#if 0
- /* applying the following constraint together with the power-of-2 rule
- * above may result in too narrow space.
- * this one is not strictly necessary, so let's disable it.
- */
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
-#endif
if (chip->chip_type == TYPE_VIA8233) {
runtime->hw.channels_max = 6;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels);
@@ -771,12 +753,8 @@
runtime->hw.rate_min = 48000;
if ((err = snd_pcm_sgbuf_init(substream, chip->pci, 32)) < 0)
return err;
- if ((err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0)
- return err;
-#if 0
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
-#endif
return 0;
}

@@ -864,6 +842,52 @@
* Mixer part
*/

+static int snd_via8233_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ static char *texts[2] = {
+ "Line", "Mic"
+ };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item >= 2)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_via8233_capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.enumerated.item[0] = inb(VIAREG(chip, CAPTURE_CHANNEL)) & VIA_REG_CAPTURE_CHANNEL_MIC ? 1 : 0;
+ return 0;
+}
+
+static int snd_via8233_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+ u8 val, oval;
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ oval = inb(VIAREG(chip, CAPTURE_CHANNEL));
+ val = oval & ~VIA_REG_CAPTURE_CHANNEL_MIC;
+ if (ucontrol->value.enumerated.item[0])
+ val |= VIA_REG_CAPTURE_CHANNEL_MIC;
+ if (val != oval)
+ outb(val, VIAREG(chip, CAPTURE_CHANNEL));
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return val != oval;
+}
+
+static snd_kcontrol_new_t snd_via8233_capture_source __devinitdata = {
+ .name = "Input Source Select",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = snd_via8233_capture_source_info,
+ .get = snd_via8233_capture_source_get,
+ .put = snd_via8233_capture_source_put,
+};
+
static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
{
via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return);
@@ -1267,6 +1291,14 @@

/* card switches */
err = snd_ctl_add(card, snd_ctl_new1(&snd_via82xx_joystick_control, chip));
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ } else {
+ /* VIA8233 */
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_via8233_capture_source, chip));
if (err < 0) {
snd_card_free(card);
return err;
diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
--- a/sound/usb/usbaudio.c Tue Oct 1 17:08:58 2002
+++ b/sound/usb/usbaudio.c Tue Oct 1 17:08:58 2002
@@ -766,6 +766,7 @@
subs->curpacksize = subs->maxpacksize;
else
subs->curpacksize = maxsize;
+ subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);

/* allocate a temporary buffer for playback */
if (is_playback) {

===================================================================


This BitKeeper patch contains the following changesets:
1.652
## Wrapped with gzip_uu ##


begin 664 bkpatch23086
M'XL(`(JZF3T``\0[_7O:1M(_PU^Q==^FN,5&JV\Y=7($2$)C;!ZPT_?>[email protected]^/
MD%9&%Y"H)&*[I?>WOS.[[email protected]`A83MWO6M31-#,['SOS.[T:W(3L^BLMF01NZ]_
M3=Z'<7)6BU<Q.W5^A[^/PA#^WIJ%"];B,*WII];<#U;W)W&X"MSM[W6`']J)
M,R.?612?U>BIDO^2/"S966W4>W=ST1[5Z^?GI#[email protected]@DY/Z\G8?39GKOQ
MW^[email protected]^#[email protected]!$OO4"1?K''0M2Y(,_VK44"1-7U-=4HVU0UU*;94R5Y)5
M4U?KG-&_I4(4L*DD42JK*E76DF%:>KU+Z*FNR4226U1J2910[4Q1SC3U>TD^
MDR2R0XQ\3S5R(M7?D'\OQYVZ0]H7XS99+5T[802Q6I+5HI2<P2M"3DB[\ZUE
M$"=TF<-_P=][email protected]+9<ES$G\,"!>&)$!AV\L`&$AT.+C'-%?+*/P
M,W-;8CV71.S6CQ,6D:F?`'00)W:0Q#E\NTLM4Q)D2+]+[OQD1I;<LOA;@2$V
M\)TH)';@DN',G_O+F-QTWE!52BG$J4C#SH",'3N!=4_>@1YA^526`D&;>*M`
MB!8'[F3I+";Q[73E36Y9,@&0J'&<DHS87>0#P0"(]TEWT";V?!["&H";@O0N
MQU0Q*'SS_'[email protected]]U+,U$H9,HG!,_<-D]N9L!B2V5DYD=DW%KV.V_)8Z]M*<@
M5O+0!#<(4[)^D+"Y>2_EK+MA\&U"IA&S/PER,8,UW)2>8P=!"*\9(/J);\_]
MWYF;DOKLVZ9\?[]G+1+?$I#:`SV!?[D0>K<%[email protected]^4J(>-P%3F,C-D<'.(H
M%[email protected]!Q/Z`!TG[M`_`C<QLU"+P,CSLQ?YK#.G-D!N#('A\4]_W85V1G*
M%.P91?9#[email protected]>DO7+]L"`+(B_\.`8I-SK*J3BKR(OL!8M!;\`<F[[email protected]&
M:)YD%;'C^@=B8&P--ZFF?O+,?^IUR9;JKW:3P-H/G/G*92V1`7-O/)V):+=D
M2U947=+6BBHK,OQH*:ZD:ZIN6U/'D9]%C><K1=94>4TUS3#VF!%HJWB*_]FH
MQU,GQY0,F:K*FJJ:8JZIJS!/8K;M&9ZG:=IS""$+FK66=,70<A;XYP9UZ?BM
MA<UB\#4E105DA5H*/->RKAGJ6O,48,;19%6V("=ZI3R4$,IYH&M-L:A9Q8,;
M^;CYM-S58O%0QH1D4C"+-I48-6W#85,#@K&,B3)*&1>@3$W7-+G"&,B_[[email protected]&
M_YCP-)FQ(GP#5:F9JFJM76;(CFZ:UG1*+=4N^L9C]'*UR&O-D`SED&FR!%6B
M%572U+6C6(KC&>[email protected]]U)GU:S4B"4\R"M%5E7K`-*21/;-J*,F&M%DG2ZEAW3
M8Y[IV3+5[*EJ/(>.\`T02*=52G#"B+4&]B?F^7.VJP-86Y$5;2V[.BQM>X[!
M5-VP[%(.]NGD?B&O50-^.&2&C2'Y1K!O#4F3*`2[:EO,<VS+51U'8\H3'&.;
MWHYC6*;Y#$^=[7NJ*>MK4(SI0-$R-:CF:79YT%33VV)(5W1#WE?1;A[<DFA6
MM!7D-5U?&ZZL&;*E.J8L2TQW#Z;5/7)[email protected]!-'W0:/[;=A5TT%[email protected]#1K
MK<NF1V7F07*!'ZTB(U5T<J=1UK(A5\<NQURP11CM)33*$QIH=#HUP,[email protected])H:K
MJ'9Y5MVGL\T!;%C&8S;!?`C;[[[email protected]]UMJ6;(6QZ51V;[email protected]\AVBEG.B2
MM*[email protected];#`MBJ-_*[email protected]$66M6DQ7->HYC&IL*I?O<OMT<G\PU[!9&A;O4:I]
M")N6?[/_UI_OOU13,3X52S5X'T.EG39&ULY4J;R-T21RHO\E;<R/=A3&<_LS
M^?`0L[E-?MA9^55SN[>1#&#PC*IID]-^9CMSRK'Z3^ME3J$>%)%^14ZB._X'
M"KSA`2-_0;G8U0Q"ZWW^^;4+.T3`H(T`DKW_O>Y==GO=R?BZ?7TSKDGWLEUK
M?4=Z]]"LH-B\!";CQ$Y6,6^=.FG5_EVKWM=U0M4*@H-^%[email protected]@ZU`=<3=&J`
M78&6,Z*P$M1R1G9(7?0O>W0R:E_W:D!%E9#*!;REI-ONM-K=#AEA+UN&)F_0
MY`Q-/HSVOGW9'?>[email protected]'[email protected]?O8NT!$?9_/"_:9E<LG;_#,
M?4;+\3).<TR[C-5RW'?#_M6D\_8=5PTW*?Z")MAJHDJ1AE<7[5'_^N^(R'+$
MH0^=<#BWH2E^:%T_+%F32.?S\*Y)Z/G,OYT1&T+L\[[..,GQ=;_S`[email protected][!
M<>([GQZ0$K2P2"GF/Y03^:G]H7<S1"+R#I&?H(!:+041;)[email protected];_"UBIO4
M7S6UP`UZ:I/$<^BGJ;R'/.B/.Y/V6^YM&C?^P(\=-I_;`0O!Q86_`T!5\!D2
MH7H=\*9V[#N;]M\';AL10Z-F*>=X;_4WG0E$6[\#[email protected]$F)$C=R$:7N;[#
M,]8`R.)A2#[email protected]`9]0;]T8?>UTJ:'!UCF#Y"(\&&G=V)@KZ*`B`IPQI
M+BUEZTU[/)Y<CWIO+GJ"(%?K&SN.R0MR';'IG%6&/J"/^P,P26_4NQ+8/#S&
M_F(UYR*A-EA8AOB^U^X.WU]=BE4I=ZWWS':7LQ"@KO#X0G!=AGQQ==.][(W'
M'%<6*2=<N0$#KAM3Y'T:AC$(+&C\5DJ$ZF_ZUQ,(1,$YIT+U$]PNX$<P9AS.
M5Z61ALCF-K+(>M1\(K(L;2.;'%[email protected],$)-!>_R!XSI2A5B06_;%PH3S%+%2
M9"IMB_4XLA`K19:E;;$>1P:(7"SH`^N_U+NF0N1ZWU3A<W?SZD,0?)S(,L8R
MZ)XO)$[I(O;9QX*2R*?[*2#%&[_OO[VN4:G>IU!S%#9H2!*[email protected]
MXT/>`QP/QZ.,9R75='[email protected]<OA&!_/$>[email protected]("14OL3"_L&P+7F2[
M-VI0(.\3&H!4?&NK;>44L:\M,2N5Y-$,1:YMI1"QI1U"P8B%#6TK2V"\8MX[
MA-7I=S/6>&YP[/D<BC*0"C(3",C+.L&O'V>9"H2OH)7R+/)%)2WY<5KM;C<W
MGI,:;SE[@-1NSS<GW`T\5H:LLI\Z<QJI!57T6`H5'YI2,XE:M'=[.&G?=/M7
MM5J#_O"#=(P+\O.UG0/F?3\!O,%5MS<0>)3C"<]X%&]\,QI=W5QV>:I!;)EC
MQZLHPBJ77+P88<*!O2YBE4;DE#J]2TCRDXNW/:1%D);":3F``B;`S1)>EE+K
M4POKX-HJB/W;`#>%&:9U<//)PG=?UDI=OI&7[TJ'*W^_$<M[QT>[L&=VK`=;
ML)*.55842<>.%7(*]E^RL=M_Z=!Y55PCD1/ZE[1?-VD3A)^MQ%^PC&_B1>&"
M'ZKSBZ;.QS%)(L:@*Q(=]\&N*)?]2UHB!1.ILI5O.U>7;_OO)F/NG]<]<D0:
M/P'+8[8DT!12\TS1L2E$H<G-=>?XB/M`R>%;B?V_^*BO_HRC/[email protected]+--.^
MVRKVW8I<87?HN]7_;M\M681:9Y*"W(F^^ZVXVWE8XA7,M?W)CF<^Z=_9/ODA
M\>$AB+BL0`2:=^4,\[email protected]`GPOT239&9>X(\0;+Q]W?LBMJ=G[X_;I#L;FRJ,:
M:=CI8P,O3E<+KEIBJB]Q4]SH^YBOV#WN'B?A]!\Q(6>IXYV&R*?XG,S]*7R+
M[#M(8SY\PSB+X#F[<]GR-*QW+71Y_(@#-R5$=FCAA18\TN,X_+L7PB.]J<,W
MT*/`XQ=(HA)1ZK['?B.-_VEL='C<?#C>)?_]>:;\L`Y)[email protected])%C$ZT>JV&
MG&<+%@F"?G."`">(`L&-;<)=O13?\?4*89J[PL$P?=[A:G68[AVN2KJB:^9:
MD619XV&J[D6I4AZE?UF0/BNX5/B3!E<$9L,NS_<@A>X%4A#>[<2,CUTTR6(!
MXT8<,%?'3::[+TKO6*QW30J?!?MGA\V'[?^\H^UJ^^\=;7/[6VO),JDBTK3R
M5`>087^6_YHQCZ>Y`.4<:O!'[email protected]<XG7O`N'7_"QQLF>,J)11/474G(
MJV.^TX>1?^NC1V3C$YR2'P"D[>(M>L1\;%<[email protected],B/EH0_(6K`[DA6.3A<S!C7
M^S8FX"B3A1U_(NY#8"^P:IX_X*KVY]!WR;NWPTEWT.9TL#:$:A!TB.<Z"3IE
MQ))5%'"7Y#<.U2Z9F?.+#F%5DY_"\@>!7A0TX4)%"1(O[5L^(Y!-7Z3C(<P]
M!310-NP!FD:AB`>T&/,RUX87`MB=']PVR=T&A]@)\?PH3OBV%:Z27#=-Q$UF
M=H)D-A,H``>[email protected]=/.K(D%*5G8)E/+X:[email protected]+`[email protected]>(F&9/C6*`8U?EN!
M5M.3[C!HXJ^H6EP(V<HA<_MG?'%V;FT_X-(JL"V`M`;L+[_4OP;-0VXI\REL
M<#1=YBJ%APP5O:[F-%]N%[email protected](K<D$K\"[email protected];U'!Z&:\2$_4?8OG2%!NZ<GT%K
M_N^LR2GS`1=V#,1S?SOG^^OGDU=;*T?IFW\V&CM,'&<P2*&`!N#2O9?^\Y)`
M%^*&N3$0`"=.H/%`ALGYL_D%(S80\\4+TFA\MWE'[email protected](308_)":.GXF/S!
M=V9_XD$Q7KD"T&N2[W;72=F37J*&=;!AB9RYIE#*-!2Y:,CD5TCV."?T3#DW
MN;XP*5&9[;]H-J,TWU?-9DBZAI>9FJZ8HB';K\O-_W`_]N0=7Q(U>3;PMSV7
MQ<,&^%HQTG!F#+(_3EZ%\]6"9;GY&#,5SL9QE4S$R\ERE32.,=F*:9729%O0
MY9>D6U7E]:YXU`1'Z'Q(\>35`B2)4HY^QE.57W^6?B5?G9,Y\Q*R7F]Y4ND\
M0Z4__0O3%*5>]<@T!4ZJZ%"5JE0,C5*CZ%Q:5=.GF.3$U/[[UZWFF2R?J<;.
M=6OU:.>77>9J_YG+W.?P)B%O$%^*M,.;&%-]9NLL2Q"C(&A*29C,)<O(#Q(7
MRR#^+9WXQ!N;:^+9_CQ^;H=NGFDZE*<[#)<.TV)T\[email protected]]>DOB'%^"5;_
M`S9.55-=59&D9KZ)XO<CH<RC9JUV>7-Q0?YL`[email protected]+LX%[email protected]
M<0YC"\?S`$=X*Z)P%YW8+O=>1*74VF%[email protected])YM9JA+1:)+8AB=HQN1[Q
MUZ_Q.%[?Y5LMT$G5O\,[email protected]&I5AYWP"D^)J<0;<GQB2YX?Z;[FNW*MEH)#
M]L1DSHT&=9W;P&[email protected]?PS3Q#_"HK;GC]D?WZ`FL.?(7;?:UV&X*C3H"\
MP^)X$GYZF;*20(6`12C4N%`A$VPX&/JTV(:@+'<)%H_9WI/')O".LAFI;/S0
MM\8GM7DP-([[email protected]?4W[MDW+B]L"5;?4(\L<2#Z)(V3GT>]SN1=NW_)"[1O[G_]
M)3AJ$I3\Y%6P6F1?<0MI$A9%(#RL*F-=BD\-2B!878&_0[59S^7!A"/61Q7_
M:U+6<JMPK(ECPWZ\;9Q,!'09TY;TK"!L`+^'C)KA04%X?I[A\MI0"!T[[email protected]^
M^KQXI_`RA^``!U<`'1]OX-$UGNAHJ9^A'+NXF:_Q"[email protected]*W-Q_GVQ12:CNRZ
MK[:W(%2LM3^AI]BQT""WT`;ZF8&PR]_BZ0P65Y1*B6$,';('OZOA+JE8.*T#
MOJB!+QK;M`3:BZ(5A:7+?&N""MH6>GCU4V_4O?H)/8Q;Y4E8W/@<@\>Y&%H`
MEX>.SU[-Q2TEI"X7MJ6'!E0[G#(`0IC.L!N"7+::N^+_5B#+\(Y%;[email protected]\-0E
M4/]"WM_U+GNC]L5D>#,:7HU[&2X#7#QW!7O]P_<\',;XGC3>_Q][email protected]*O[
M(TN/C4HORIG"IDRZE[PT`N'+=JY$M(<L58+V)LXJBJ!#FD!!DK#&=7O\87)S
MV<?+LM'-\+K_YJ(GDG,,,KFK.>/,0H<)++92!O^$*@$/P!OX:F)[D&0F[+=&
M)EDS$^PX5U99/K6AP0_!1*MI+$JL++L"P]49]#@-0G!731P2XU-]BK/F08!T
M0/V[2>%%?N6>7[0>DU>O=G_E5Z?``9O'[`"YQ8;>H)[email protected]$`1Q+%,OA'H4"!1
M^[email protected]*R1IO)L(`[0O<-5P[,C%[email protected],0[2-(T3^`#PK?RMT*VW>^CK!ZVK0!06YH
MU/5!3GCR>!XGBR_CI$MU61&W`OQ9+%@@1S9)[email protected]@5\HEIU124&(D'I
M"RD-[[email protected]'G<AK<D1.W,V4$_S$IYPN>=<:L/G)$3DC1T=-8&R?5C[N
M).A$Z:03/8BT-=0DT*9BGBGA\TP'43<#30(S+LPR'43.AYH$[BR?9X*(/XB8
M#30)O'DZRY2BH`7!%.`)6WO\EK;[email protected]!N'U7&TSQXBLL>7(FCGN^//>%:8C!H
ME[,BO+D-;SX*GP\W(;P8_SD(G[&/X*]?OWZ2R-FPD!`9ARU`9'Y>>T!DG$%Z
[email protected]_%-%3N&?('+&?E%D$,:015`:/"@AZIY>FB&VEF*++B3=M'AKD;8>NF'P
MTUBJF_P+I`9L#YZ1KYLE.#A6M8>2SUHUTY9F>Y%!>\A]';]L=%6`NDB]B."7
M2JAQ!C4^!-7)H#J[4`5)X.5X,KZXNMZ79_.J2JJ/HP%?`I[5W/+Y,,XN?JN$
MZX[:'`J>E3`?4YB/&8SP`@NV/$P"AJ3B%T#;2C:]]F0XNN!H\-PB783YD,)\
M.`#S8PKSXP&[email protected]#SL?4XUT/E9"#3(##B!\*J&J7*:P8H7+[$)5N4RY
M0>.EZWL3'#^.?VX4!1RW2YUJ^Q5WJE^K>"EWK>(R5:ZU"U?N6L7U]ETK.V'8
M]4`H/+!'0`1^`&!([email protected]!`/&LE2*AT+%<`%B\X$98_RV`OMF#-%!:?I;P,4DA9
M)%'Q3"NI?9L=D_4Z*\6\N7V;;S`[email protected](V<1'<E![:,7-#[email protected](=?I1Y^Q36%
MT]+Q:L&B/;4"\"6O-3G\91B<\/[email protected]"YVKX=^&#X?(A\F]G2;G).".B
M[!A"Y;=8SC2I1;7M1%<@W"DXX];D:QG\!8>DM(D:4?B4##P-<=J%>YSP_PA*
MI7CBQ*HL:3\72.3SLCN+;[email protected]?E+B#V;BN#0$ARJTH;#`J'N2)1;'_$XP$\>
M4C_?,%$!#\\4E*^DRNE*2N5*(KOU`AN*3_>Q93Z6,071ATM`/L=+6C[GDVWL
M0&?QU#IAZXA$X*[email protected]:([>(GG94C$YPWF_U=WM4UI9$OXL_Z*$[=T01&9$48P
MJU5$,*&B:+F8VMS<K2F$T4S)B\M`HA6]O_WVTWW.S/`R!+B;3=V*E1F&\S;G
M=/?I/OUT<YN2+`-D:%0G\9F'<NI\M.FKS<#\@YG)E-.-<=M"%AM7FZP%M*^0
M/MW$"'E&.<N4L^:4T_AE+OJ.;N84972T;".U^KR^&7EM"EJAI!SW984AAG-]
M6$L&-";ZKF8$-,)GM?^\3TJE]EG94P&""0[1_(]RB"[I;+&LR&US^O?DZWBO
M),(ST6$23N0JSE!K7V]"N!JSA)[email protected]_9':KM^]:P8PS\8<?M>5^MU!8^>>C:
M<L5IRL*0#/%>T._Y?Z5?*],<[X'R=/=XE)5*V81S&-G2C-!90]>[QWX[*S-W
MI*S7YOP`0XE.&5!PBJ2CX/^Y-+ULLH%$HIZ5;$!R!MAVP=94[4QY8I/"7M6N
M_9/=L.*,I"&.1[WVNUT?9PW-P=VHJW%<<MJW;.L`'].?;KVR0A::]TH2.20R
M2+0H*W%(0>)[Z)KGLXI9#A)[email protected]!32RN`,`.2X)?O:UF/[email protected]+7O-.B[F+
MWD>_ZB^T8WUJ>U_\%HZ,-_V,>GMV\091A6/N)GHNG4I1=\@QDW>[email protected]>N5(
M33S65,WGCSRY<[email protected]#I.YO+)LSI1$7IF1,R57M.CZ7+#W2T7A%6N*5ZP$
M#.1/WP'BP0!Q7JG^;I6*1?%?!*V!_\#0QO=*,L,D4FTT/:M0+0MU6_"$%<;,
ML-\*1W?GNN&]<J?CW0WZ*B4C3$OG(-\@"[email protected];WZA.1DJ\9#9FQ+?$<@!%
MA/,W)1]:K37GV<D=Z&1ITRI$`NSEX$=E2EL00HOS?Q*SASE#/0LG$S,P6#_0
MZ*N`G<-AE)B.#0/^4U)<#;0O&[ZR_NUMX`VE"1I4VV!(:8_W!B:WEQ+8%;!9
MDM9I;OA-;%U6P6[D#]3!^MXV*%=[`Y9]FW58^/!T^2T:[email protected]=!/``#HB9I,PG3
M2#PQ:LFWP9U+7ZEM+B%P0JHG;:?7OZT;+P5_OWL\A!3_)%_#<[email protected]&R_+
M7J(=75=MZN]J_ZJ^7I^4OU,YDZ:YZ7].V+1D>SIM1\&RGNV#8KXX.RXA&4CV
MHUCJ1\+(`%#*)84?S)RJ58A\GR/,--^[email protected]"[email protected]%KXN.Z2S'(CEW^O(-1#'
M$;'I#/6<G0],F!/>,83EL+4<5BL6K=#;[email protected]>O'69W5Z=5%O[)DP3-B(U=V+
MZ\;>NTM<C-\=1DQ/X^(T.,4GAO&\;L#H<;*[email protected]'Z0A9X?Q"[email protected]`
MNQ!MA6,N)P!$(\P+!CWOE*!<X20)>(/OX5MTT0Q/A'J&GSQOYZ:LA*D<4,MP
MWH()J%9KSRGDJ"5+[V53`2&)G/?_R7B2:FMAQEMI=P':Y7N<-$D?80*W>72Q
M9+:X9=MQJ!VZFZW3)"G%5MXAM=CZF=%AT(KM0\LYS!D;;TY^4%%#[email protected]>AN[L
M]F]W;<'2#II8.(XE\@9^ORT1"[email protected]/.HH`@7<`/.-PL>.AP0`\)GL`C108Q
M)[email protected]<[email protected]"5+FMA#I_FD'@>C'AFY?=KLNS&(D4#?J9?L4KH>
M&;WY0[LTINLMG`_5!-(-$2/OP5+F=+2L`@8BTCF^[email protected]@"2IV>RRHZ,_^V`&
MNG]&UM7EFK8`%0Z#>1=.OYK5Q:.QD#+8`N1!E^1'@G(BPO$EW%]TQ$Z3]B6A
MB*Q.V]I\>`A(WV6T6!<!:#&*"LSJ?NT/[FF),8.F>Q/:.,)>1FIH<_#$S3\,
M);D`[EO$RT,S04[1,7VF)$=LS^^.NC$"'7[[email protected]\CXB^*AX529&DNE/%V
M>@H-WXW-M!R\C#,1SQ%36+.GWR;49-DJX$R6B9([E&DK'<#8XJBSXUG*/M3*
M[E7UK7MQ>HKD52>DNKBU>J7Z!])NW$(UN7D:(GI)8W="TI!CQ%2,?%6_UWE*
MBU/0$2>)PT&BU5/[email protected]=$_62.K\^:UR>E3\"+IN'&C%=Y*1\V;B^JKIH&,6<
M'[email protected]:6(6!G4-*X,M!Q77VR#@Q%AX/?$4E$EZH'J-Z+?8+#3*;\YD(=9H
MMV&,7"FG2DAG41P#3*&1X4W'I5D8^%[`05:_C,E!),&P`40CS2IAK-M^^U%N
MZ>UM<:'B0LHJVO<[email protected]!6"#$=P9=3MH'DG8U\SEA<)4L80TH:K;Z'OC6ZH
M4Z_9W3W6#]$#[email protected](F$([email protected]<[email protected]&9"[D][`Y8%W2(SV0],[email protected]&*CN
M*-"!DS()M`,4F30"QKP0F8Q$1MQ[`Y")!%PB,TAW1(W<^'=W\"P%?>"O)4=V
MB[[END"21D,!%G"T;V^G\99="4U#D!JWF**[C+!,^:SVMIX:7SD.^MQ6Q71&
M;[email protected];Y./W:,:C<;K5^<0XHKP'MZ8+A0LD<C3^CP=[+&%-8F_YM*DXFQ`P3
MI)7AL,_WU:MZ]6QR1%%'":,2[/2MK\-\-?WQ_!GBT/J^SE;@BN!Q>9U2(6&P
M2[#]J"'/1&+Z#KR<\OF#(JFI-/GL'DLS1.G^SH[,`DB2"L9H,AQ:G!'08C/<
M,9A.S$<&X1-!B4J1K%#XPU\#J=G'X1NH0-U`(-*.D8W(QX!^B7<8\3C.KG#W
M\]-HZ3]A!G[[35E_TGNT'D;NL.]VO'T[!>)+)YUMR$$&35E:PRRI<BC`24JF
M,)NQTXDH4H-GC.94X,6HAR<:JTE?[1[[email protected]:0SXW?B)SY\MY,+PD&E7&0-
M;TAM,K6].7.!3ZM>G+%LTKJAF32-SC<@W-EU3\_*;[FR7JR)RB\JK*TKY^*E
MH6GYO1'1IHZOZ,&-*E7W]I0YMB>!>`A)"D0S5(S-MA+=D6YDOC;;:3F>CV2A
MB,/TY&JFJ`BR):F=Z14=D,6*8<8JA;P&,[email protected]^5CM!'8B'-7[)*6.>=<,G:
MCSL[X>*!L(Z/)AC?K&7,;0$IX%:OKM2&WM8/X:<4>2G"!3V^[email protected]@4<BH5;_
M4#[C9R]Q/#E/V3$#Y2MV'FG42-X#(:@G*MJSX,1H/]*&:D?H[UG"[IY1Q1/?
MO)XE!1$2Q4*J8CN,,Y:+UR,5[9MJ?+SDW9V4.'@>,^$#UAM>,%[:9#'>$G`<
M:PC#LJR<@YV?S*=B!K_KX);K']U:9?P^QW^Q]C/J)0-91+<,4)ILJ[1H6Z)Y
M2&,?&CQ0J#;Y0HG1=GE!;$*Z,,BZDB\"TU0IV#AVK16H^#[@^P]^SQWU:(.X
M3VV)BXET?Q>?([email protected]_"1HMJ;U.\R'PVBFB")[B,[email protected]*AV
MH]'_[,^"!(F_7!IU8,57'-$,<2GHPZ`@\`;#<[email protected]^2<09:\2OF]&VS$
MI+IQGQFEM4G)W0F>-`UAP/K\5VV%RB?*N>631NU#-1W!4[`[email protected]"<)9V9
MG;#*>G)Q76\D=V0"^3!-^T"RUYQ])GPL;H,[email protected]*[7/SBS=F"HF^:^PV
MK?2(.M/S1"$RAI14E`J<?HN'>-FXBO8KF#G?>24JG_!"_!8<>RT7D>60OZ:B
M^MSOM,5[88[Y=TA?`_TZ>:1LH0OR/]0<"=[FW'2?,\;WH2/?NLU[FHV.?TNZ
M1C/PM>MK%"BRD;VLM%8H0$5V6-$WZV:&',G/+\U.*&1WJ+N$$CI1`J\X7K*4
MYY?DRUI6;WJD$Y+JLK8VH?GM*3NS7CFP6/C(9<$J#.BB"Q#TE8,":E8.#O(T
M/73A:2XZ1"Q.Y`D)]7FPD:M_><0-^+C!14ZGU#3P0^XS(?;#ZWA=+HNO1[CA
[email protected]?=!UE;`[4]I&TS^&1C/X,TWD"J0]H--\[][email protected];)[email protected]$C\R>RM?J]7KCZX
M)XTSMWI6/7>9V:OUZ_,JLB=7HN*&I:SH$><9R$)<>P/.B^(/<1Q]I&S-Y?/*
M8;NSP;AS"TE_),Y:#T^)S?6:B("2%Y_7VI^0/N/'^HLM#^ERBZX.=\S+H[_G
M%=*;-9Z#:;7&'3:'9RGS"8,TE1->!%D1(`DF)*BQ?T_>E>NP%>+B<N(['71C
MJ4/6XE>9%&2,^&<G92QU#*-Q\;0H<4A]^I]E?[CAN?[@KX!$\N3&EY&Z:!*5
M%II)*BM%^P+$_,^<>37$_]TU!/6CN>>C><NDFT/!5](_ZO5'PYL4O_AW!QY3
M)S`E.K?+G%F)THB8'L?H8FR5>MY7=QZ9*-<%/*;G#]O-85.$$C,LW<X\<J5=
M,NO?-ELS9%/MM'Q2I2GYHWK%I8C3-=',$:LH>><-YQ>D`BB'T<PM1P4RZR\@
M,\3^ESA7$0/L!H,)F!&0'!)?A[O9\75$K&(4F8,4H]SR=A^+ZQO#VDT#`6</
M5M!)Z3&'ROA/-B5Y5%;YA:AE&N)DJ(5G9`@NL4^E,.53*?W#OK7%C]#WD7NG
M,.X[6/;WQV*@$?DA,CE2Y]4S7HXL^^0.IK*MSIK9E;)T.'Q""6.!-O?X$(_D
MC`ZFL#Q,Z3.$C`I+/S1;][email protected],ZC(_W,CYAH)1]ZAXXQ"U-$OK_P6C5!P%,W(`
!````
`
end

-----
Jaroslav Kysela <[email protected]>
Linux Kernel Sound Maintainer
ALSA Project http://www.alsa-project.org
SuSE Linux http://www.suse.com