Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Sun, 29 Sep 2002 14:50:55 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Sun, 29 Sep 2002 14:50:06 -0400 Received: from gate.perex.cz ([194.212.165.105]:14096 "EHLO gate.perex.cz") by vger.kernel.org with ESMTP id ; Sun, 29 Sep 2002 14:48:28 -0400 Date: Sun, 29 Sep 2002 20:53:10 +0200 (CEST) From: Jaroslav Kysela X-X-Sender: To: Linus Torvalds cc: LKML Subject: [PATCH] ALSA update [8/10] - 2002/07/31 Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 42136 Lines: 1203 You can import this changeset into BK by piping this whole message to: '| bk receive [path to repository]' or apply the patch as usual. =================================================================== ChangeSet@1.605.2.19, 2002-09-26 11:55:55+02:00, perex@pnote.perex-int.cz ALSA 2002/07/31 update : - AC'97 codec - added reset callback to do reset and skip the standard procedure - added limited_regs flag to avoid to touch unexpected registers - Fixes for AD1981A and added a special patch for an intel motherboard - sequencer - check the possible infinite loop in priority queues - reset the timer at continue if not initialized yet - changed synchronize_irq() for new api with an argument - NM256 driver - fixes the lock up on NM256 ZX - VIA8233 - implementation of SG buffer include/sound/ac97_codec.h | 2 include/sound/version.h | 2 sound/core/seq/seq_prioq.c | 22 ++-- sound/core/seq/seq_prioq.h | 2 sound/core/seq/seq_timer.c | 4 sound/isa/dt019x.c | 2 sound/pci/ac97/ac97_codec.c | 39 +++++-- sound/pci/ac97/ac97_patch.c | 14 ++ sound/pci/ac97/ac97_patch.h | 1 sound/pci/ali5451/ali5451.c | 5 sound/pci/cs4281.c | 2 sound/pci/emu10k1/emumpu401.c | 4 sound/pci/emu10k1/emupcm.c | 6 + sound/pci/ens1370.c | 3 sound/pci/ice1712.c | 4 sound/pci/intel8x0.c | 3 sound/pci/maestro3.c | 2 sound/pci/nm256/nm256.c | 32 ++++-- sound/pci/via686.c | 21 ++-- sound/pci/via8233.c | 220 +++++++++++++++++++++++++++--------------- 20 files changed, 260 insertions(+), 130 deletions(-) diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h --- a/include/sound/ac97_codec.h Sun Sep 29 20:23:22 2002 +++ b/include/sound/ac97_codec.h Sun Sep 29 20:23:22 2002 @@ -152,6 +152,7 @@ typedef struct _snd_ac97 ac97_t; struct _snd_ac97 { + void (*reset) (ac97_t *ac97); void (*write) (ac97_t *ac97, unsigned short reg, unsigned short val); unsigned short (*read) (ac97_t *ac97, unsigned short reg); void (*wait) (ac97_t *ac97); @@ -178,6 +179,7 @@ unsigned int rates_mic_adc; unsigned int spdif_status; unsigned short regs[0x80]; /* register cache */ + unsigned int limited_regs; /* allow limited registers only */ bitmap_member(reg_accessed,0x80); /* bit flags */ union { /* vendor specific code */ struct { diff -Nru a/include/sound/version.h b/include/sound/version.h --- a/include/sound/version.h Sun Sep 29 20:23:22 2002 +++ b/include/sound/version.h Sun Sep 29 20:23:22 2002 @@ -1,3 +1,3 @@ /* include/version.h. Generated automatically by configure. */ #define CONFIG_SND_VERSION "0.9.0rc2" -#define CONFIG_SND_DATE " (Wed Jul 24 10:42:45 2002 UTC)" +#define CONFIG_SND_DATE " (Wed Jul 31 15:28:28 2002 UTC)" diff -Nru a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c --- a/sound/core/seq/seq_prioq.c Sun Sep 29 20:23:22 2002 +++ b/sound/core/seq/seq_prioq.c Sun Sep 29 20:23:22 2002 @@ -146,20 +146,15 @@ } /* enqueue cell to prioq */ -void snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell) +int snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell) { snd_seq_event_cell_t *cur, *prev; unsigned long flags; + int count; int prior; - if (f == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n"); - return; - } - if (cell == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL cell\n"); - return; - } + snd_assert(f, return -EINVAL); + snd_assert(cell, return -EINVAL); /* check flags */ prior = (cell->event.flags & SNDRV_SEQ_PRIORITY_MASK); @@ -177,7 +172,7 @@ cell->next = NULL; f->cells++; spin_unlock_irqrestore(&f->lock, flags); - return; + return 0; } } /* traverse list of elements to find the place where the new cell is @@ -186,6 +181,7 @@ prev = NULL; /* previous cell */ cur = f->head; /* cursor */ + count = 10000; /* FIXME: enough big, isn't it? */ while (cur != NULL) { /* compare timestamps */ int rel = compare_timestamp_rel(&cell->event, &cur->event); @@ -199,6 +195,11 @@ /* move cursor to next cell */ prev = cur; cur = cur->next; + if (! --count) { + spin_unlock_irqrestore(&f->lock, flags); + snd_printk(KERN_ERR "cannot find a pointer.. infinite loop?\n"); + return -EINVAL; + } } /* insert it before cursor */ @@ -212,6 +213,7 @@ f->tail = cell; f->cells++; spin_unlock_irqrestore(&f->lock, flags); + return 0; } /* dequeue cell from prioq */ diff -Nru a/sound/core/seq/seq_prioq.h b/sound/core/seq/seq_prioq.h --- a/sound/core/seq/seq_prioq.h Sun Sep 29 20:23:22 2002 +++ b/sound/core/seq/seq_prioq.h Sun Sep 29 20:23:22 2002 @@ -41,7 +41,7 @@ extern void snd_seq_prioq_delete(prioq_t **fifo); /* enqueue cell to prioq */ -extern void snd_seq_prioq_cell_in(prioq_t *f, snd_seq_event_cell_t *cell); +extern int snd_seq_prioq_cell_in(prioq_t *f, snd_seq_event_cell_t *cell); /* dequeue cell from prioq */ extern snd_seq_event_cell_t *snd_seq_prioq_cell_out(prioq_t *f); diff -Nru a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c --- a/sound/core/seq/seq_timer.c Sun Sep 29 20:23:22 2002 +++ b/sound/core/seq/seq_timer.c Sun Sep 29 20:23:22 2002 @@ -365,9 +365,11 @@ return; if (tmr->running) return; - if (! tmr->initialized) + if (! tmr->initialized) { + snd_seq_timer_reset(tmr); if (initialize_timer(tmr) < 0) return; + } snd_timer_start(tmr->timeri, tmr->ticks); tmr->running = 1; do_gettimeofday(&tmr->last_update); diff -Nru a/sound/isa/dt019x.c b/sound/isa/dt019x.c --- a/sound/isa/dt019x.c Sun Sep 29 20:23:22 2002 +++ b/sound/isa/dt019x.c Sun Sep 29 20:23:22 2002 @@ -168,7 +168,7 @@ snd_dma8[dev] = pdev->dma_resource[0].start; snd_irq[dev] = pdev->irq_resource[0].start; snd_printdd("dt019x: found audio interface: port=0x%lx, irq=0x%lx, dma=0x%lx\n", - snd_port[dev],snd_irq[dev],smd_dma8[dev]); + snd_port[dev],snd_irq[dev],snd_dma8[dev]); pdev = acard->devmpu; if (!pdev || pdev->prepare(pdev)<0) diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c --- a/sound/pci/ac97/ac97_codec.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/ac97/ac97_codec.c Sun Sep 29 20:23:22 2002 @@ -91,10 +91,10 @@ { 0x41445303, 0xffffffff, "AD1819", patch_ad1819 }, { 0x41445340, 0xffffffff, "AD1881", patch_ad1881 }, { 0x41445348, 0xffffffff, "AD1881A", patch_ad1881 }, -{ 0x41445360, 0xffffffff, "AD1885", patch_ad1881 }, +{ 0x41445360, 0xffffffff, "AD1885", patch_ad1885 }, { 0x41445361, 0xffffffff, "AD1886", patch_ad1886 }, { 0x41445362, 0xffffffff, "AD1887", patch_ad1881 }, -{ 0x41445372, 0xffffffff, "AD1981A", NULL }, +{ 0x41445372, 0xffffffff, "AD1981A", patch_ad1881 }, { 0x414c4300, 0xfffffff0, "RL5306", NULL }, { 0x414c4310, 0xfffffff0, "RL5382", NULL }, { 0x414c4320, 0xfffffff0, "RL5383", NULL }, @@ -240,12 +240,11 @@ set_bit(reg, ac97->reg_accessed); } -#ifndef CONFIG_SND_DEBUG -#define snd_ac97_write_cache_test snd_ac97_write_cache -#else static void snd_ac97_write_cache_test(ac97_t *ac97, unsigned short reg, unsigned short value) { - return snd_ac97_write_cache(ac97, reg, value); + if (ac97->limited_regs && ! test_bit(reg, ac97->reg_accessed)) + return; +#if 0 if (!snd_ac97_valid_reg(ac97, reg)) return; spin_lock(&ac97->reg_lock); @@ -254,8 +253,9 @@ if (value != ac97->regs[reg]) snd_printk("AC97 reg=%02x val=%04x real=%04x\n", reg, value, ac97->regs[reg]); spin_unlock(&ac97->reg_lock); -} #endif + snd_ac97_write_cache(ac97, reg, value); +} int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value) { @@ -911,6 +911,9 @@ { unsigned short val, mask = 0x8000; + if (ac97->limited_regs && ! test_bit(reg, ac97->reg_accessed)) + return 0; + switch (reg) { case AC97_MASTER_TONE: return ac97->caps & 0x04 ? 1 : 0; @@ -1461,6 +1464,12 @@ *ac97 = *_ac97; ac97->card = card; spin_lock_init(&ac97->reg_lock); + + if (ac97->reset) { + ac97->reset(ac97); + goto __access_ok; + } + snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */ if (ac97->wait) ac97->wait(ac97); @@ -1499,6 +1508,10 @@ snd_ac97_free(ac97); return -EIO; } + + 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); @@ -1540,6 +1553,7 @@ snd_ac97_determine_rates(ac97, AC97_PCM_LFE_DAC_RATE, &ac97->rates_lfe_dac); ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC; } + /* additional initializations */ if (ac97->init) ac97->init(ac97); snd_ac97_get_name(ac97, ac97->id, name); @@ -1738,7 +1752,10 @@ int reg, val; for (reg = 0; reg < 0x80; reg += 2) { - val = snd_ac97_read(ac97, reg); + if (ac97->limited_regs && ! test_bit(reg, ac97->reg_accessed)) + val = 0xffff; + else + val = snd_ac97_read(ac97, reg); snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val); } } @@ -1903,6 +1920,11 @@ { int i; + if (ac97->reset) { + ac97->reset(ac97); + goto __reset_ready; + } + snd_ac97_write(ac97, AC97_POWERDOWN, 0); snd_ac97_write(ac97, AC97_RESET, 0); udelay(100); @@ -1916,6 +1938,7 @@ break; mdelay(1); } +__reset_ready: if (ac97->init) ac97->init(ac97); diff -Nru a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c --- a/sound/pci/ac97/ac97_patch.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/ac97/ac97_patch.c Sun Sep 29 20:23:22 2002 @@ -300,6 +300,20 @@ return 0; } +int patch_ad1885(ac97_t * ac97) +{ + unsigned short jack; + + patch_ad1881(ac97); + /* This is required to deal with the Intel D815EEAL2 */ + /* i.e. Line out is actually headphone out from codec */ + + /* turn off jack sense bits D8 & D9 */ + jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF); + snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300); + return 0; +} + int patch_ad1886(ac97_t * ac97) { patch_ad1881(ac97); diff -Nru a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h --- a/sound/pci/ac97/ac97_patch.h Sun Sep 29 20:23:22 2002 +++ b/sound/pci/ac97/ac97_patch.h Sun Sep 29 20:23:22 2002 @@ -35,4 +35,5 @@ int patch_conexant(ac97_t * ac97); int patch_ad1819(ac97_t * ac97); int patch_ad1881(ac97_t * ac97); +int patch_ad1885(ac97_t * ac97); int patch_ad1886(ac97_t * ac97); diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c --- a/sound/pci/ali5451/ali5451.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/ali5451/ali5451.c Sun Sep 29 20:23:22 2002 @@ -1970,9 +1970,10 @@ static int snd_ali_free(ali_t * codec) { snd_ali_disable_address_interrupt(codec); - synchronize_irq(codec->irq); - if (codec->irq >=0) + if (codec->irq >= 0) { + synchronize_irq(codec->irq); free_irq(codec->irq, (void *)codec); + } if (codec->res_port) { release_resource(codec->res_port); kfree_nocheck(codec->res_port); diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c --- a/sound/pci/cs4281.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/cs4281.c Sun Sep 29 20:23:22 2002 @@ -1300,7 +1300,7 @@ } #endif snd_cs4281_proc_done(chip); - if(chip->irq >= 0) + if (chip->irq >= 0) synchronize_irq(chip->irq); /* Mask interrupts */ diff -Nru a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c --- a/sound/pci/emu10k1/emumpu401.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/emu10k1/emumpu401.c Sun Sep 29 20:23:22 2002 @@ -64,7 +64,7 @@ mpu401_read_data(emu, mpu); #ifdef CONFIG_SND_DEBUG if (timeout <= 0) - snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); + snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); #endif } @@ -143,7 +143,7 @@ } spin_unlock_irqrestore(&midi->input_lock, flags); if (!ok) - snd_printk("midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", + snd_printk(KERN_ERR "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", cmd, emu->port, mpu401_read_stat(emu, midi), mpu401_read_data(emu, midi)); diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c --- a/sound/pci/emu10k1/emupcm.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/emu10k1/emupcm.c Sun Sep 29 20:23:22 2002 @@ -968,11 +968,13 @@ { emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return); emu->pcm = NULL; + snd_pcm_lib_preallocate_free_for_all(pcm); } int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm) { snd_pcm_t *pcm; + snd_pcm_substream_t *substream; int err; if (rpcm) @@ -991,6 +993,10 @@ pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; strcpy(pcm->name, "EMU10K1"); emu->pcm = pcm; + + for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) + snd_pcm_lib_preallocate_pci_pages(emu->pci, substream, 64*1024, 64*1024); + return err; if (rpcm) *rpcm = pcm; diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c --- a/sound/pci/ens1370.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/ens1370.c Sun Sep 29 20:23:22 2002 @@ -1532,8 +1532,7 @@ outl(0, ES_REG(ensoniq, CONTROL)); /* switch everything off */ outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */ #endif - if(ensoniq->irq >= 0) - synchronize_irq(ensoniq->irq); + synchronize_irq(ensoniq->irq); pci_set_power_state(ensoniq->pci, 3); __hw_end: #ifdef CHIP1370 diff -Nru a/sound/pci/ice1712.c b/sound/pci/ice1712.c --- a/sound/pci/ice1712.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/ice1712.c Sun Sep 29 20:23:22 2002 @@ -4072,7 +4072,7 @@ /* --- */ __hw_end: snd_ice1712_proc_done(ice); - if (ice->irq) { + if (ice->irq >= 0) { synchronize_irq(ice->irq); free_irq(ice->irq, (void *) ice); } @@ -4146,7 +4146,7 @@ pci_write_config_word(ice->pci, 0x40, 0x807f); pci_write_config_word(ice->pci, 0x42, 0x0006); snd_ice1712_proc_init(ice); - synchronize_irq(ice->irq); + synchronize_irq(pci->irq); if ((ice->res_port = request_region(ice->port, 32, "ICE1712 - Controller")) == NULL) { snd_ice1712_free(ice); diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c --- a/sound/pci/intel8x0.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/intel8x0.c Sun Sep 29 20:23:22 2002 @@ -1104,8 +1104,7 @@ outb(ICH_RESETREGS, ICHREG(chip, PO_CR)); outb(ICH_RESETREGS, ICHREG(chip, MC_CR)); /* --- */ - if(chip->irq >= 0) - synchronize_irq(chip->irq); + synchronize_irq(chip->irq); __hw_end: if (chip->bdbars) snd_free_pci_pages(chip->pci, 3 * sizeof(u32) * ICH_MAX_FRAGS * 2, chip->bdbars, chip->bdbars_addr); diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c --- a/sound/pci/maestro3.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/maestro3.c Sun Sep 29 20:23:22 2002 @@ -2310,7 +2310,7 @@ vfree(chip->suspend_mem); #endif - if(chip->irq >= 0) + if (chip->irq >= 0) synchronize_irq(chip->irq); if (chip->iobase_res) { diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c --- a/sound/pci/nm256/nm256.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/nm256/nm256.c Sun Sep 29 20:23:22 2002 @@ -892,7 +892,7 @@ #endif }; -static int __init +static int __devinit snd_nm256_pcm(nm256_t *chip, int device) { snd_pcm_t *pcm; @@ -1188,21 +1188,31 @@ } /* create an ac97 mixer interface */ -static int __init +static int __devinit snd_nm256_mixer(nm256_t *chip) { ac97_t ac97; - int err; + int i; + /* looks like nm256 hangs up when unexpected registers are touched... */ + static int mixer_regs[] = { + AC97_MASTER, AC97_HEADPHONE, AC97_MASTER_MONO, + AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE, + AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL, + AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL, + AC97_EXTENDED_ID, AC97_EXTENDED_STATUS, + AC97_VENDOR_ID1, AC97_VENDOR_ID2, + -1 + }; memset(&ac97, 0, sizeof(ac97)); - ac97.init = snd_nm256_ac97_reset; + ac97.reset = snd_nm256_ac97_reset; ac97.write = snd_nm256_ac97_write; ac97.read = snd_nm256_ac97_read; + ac97.limited_regs = 1; + for (i = 0; mixer_regs[i] >= 0; i++) + set_bit(mixer_regs[i], ac97.reg_accessed); ac97.private_data = chip; - if ((err = snd_ac97_mixer(chip->card, &ac97, &chip->ac97)) < 0) - return err; - - return 0; + return snd_ac97_mixer(chip->card, &ac97, &chip->ac97); } /* @@ -1211,7 +1221,7 @@ * RAM. */ -static int __init +static int __devinit snd_nm256_peek_for_sig(nm256_t *chip) { /* The signature is located 1K below the end of video RAM. */ @@ -1346,7 +1356,7 @@ if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running) snd_nm256_capture_stop(chip); - if(chip->irq >= 0) + if (chip->irq >= 0) synchronize_irq(chip->irq); if (chip->cport) @@ -1374,7 +1384,7 @@ return snd_nm256_free(chip); } -static int __init +static int __devinit snd_nm256_create(snd_card_t *card, struct pci_dev *pci, int play_bufsize, int capt_bufsize, int force_load, diff -Nru a/sound/pci/via686.c b/sound/pci/via686.c --- a/sound/pci/via686.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/via686.c Sun Sep 29 20:23:22 2002 @@ -238,7 +238,7 @@ snd_card_t *card; snd_pcm_t *pcm; - snd_pcm_t *pcm_fm; + /*snd_pcm_t *pcm_fm;*/ viadev_t playback; viadev_t capture; /*viadev_t playback_fm;*/ @@ -564,8 +564,13 @@ val = 0; else val = ((ptr - (unsigned int)viadev->table_addr) / 8 - 1) % viadev->tbl_entries; - val *= viadev->tbl_size; - val += viadev->tbl_size - count; + 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; + } viadev->lastptr = ptr; viadev->lastcount = count; // printk("pointer: ptr = 0x%x (%i), count = 0x%x, val = 0x%x\n", ptr, count, val); @@ -632,10 +637,10 @@ chip->playback.substream = substream; runtime->hw = snd_via686a_playback; runtime->hw.rates = chip->ac97->rates_front_dac; - if ((err = snd_pcm_sgbuf_init(substream, chip->pci, 32)) < 0) - return err; if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000)) 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 @@ -658,10 +663,10 @@ chip->capture.substream = substream; runtime->hw = snd_via686a_capture; runtime->hw.rates = chip->ac97->rates_adc; - if ((err = snd_pcm_sgbuf_init(substream, chip->pci, 32)) < 0) - return err; if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000)) 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 @@ -1020,7 +1025,7 @@ if (ac97_clock >= 8000 && ac97_clock <= 48000) chip->ac97_clock = ac97_clock; pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision); - synchronize_irq(pci->irq); + synchronize_irq(chip->irq); /* initialize offsets */ chip->playback.reg_offset = VIA_REG_PLAYBACK_STATUS; diff -Nru a/sound/pci/via8233.c b/sound/pci/via8233.c --- a/sound/pci/via8233.c Sun Sep 29 20:23:22 2002 +++ b/sound/pci/via8233.c Sun Sep 29 20:23:22 2002 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -157,11 +159,8 @@ #define VIA_REG_AC97_DATA_MASK 0xffff #define VIA_REG_SGD_SHADOW 0x84 /* dword */ -/* - * - */ - -#define VIA_MAX_FRAGS 32 +#define VIA_TBL_BIT_FLAG 0x40000000 +#define VIA_TBL_BIT_EOL 0x80000000 /* * @@ -169,15 +168,78 @@ typedef struct { unsigned long reg_offset; - unsigned int *table; - dma_addr_t table_addr; snd_pcm_substream_t *substream; - dma_addr_t physbuf; + int running; unsigned int size; unsigned int fragsize; unsigned int frags; + 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 */ + u32 *table; /* physical address + flag */ + dma_addr_t table_addr; } viadev_t; +static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream, + struct pci_dev *pci) +{ + int i, size; + 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; + } + dev->table[(dev->tbl_entries << 1) - 1] = cpu_to_le32(VIA_TBL_BIT_EOL | size); + + return 0; +} + + +static void clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream, + struct pci_dev *pci) +{ + if (dev->table) { + snd_free_pci_pages(pci, PAGE_ALIGN(dev->tbl_entries * 8), dev->table, dev->table_addr); + dev->table = NULL; + } +} + + +/* + */ + typedef struct _snd_via8233 via8233_t; #define chip_t via8233_t @@ -200,9 +262,6 @@ spinlock_t reg_lock; snd_info_entry_t *proc_entry; - - void *tables; - dma_addr_t tables_addr; }; static struct pci_device_id snd_via8233_ids[] __devinitdata = { @@ -323,15 +382,19 @@ switch (cmd) { case SNDRV_PCM_TRIGGER_START: val = VIA_REG_CTRL_INT | VIA_REG_CTRL_START; + viadev->running = 1; break; case SNDRV_PCM_TRIGGER_STOP: val = VIA_REG_CTRL_TERMINATE; + viadev->running = 0; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: val = VIA_REG_CTRL_INT | VIA_REG_CTRL_PAUSE; + viadev->running = 1; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: val = VIA_REG_CTRL_INT; + viadev->running = 0; break; default: return -EINVAL; @@ -342,21 +405,33 @@ return 0; } -static void snd_via8233_setup_periods(via8233_t *chip, viadev_t *viadev, - snd_pcm_substream_t *substream) +static int snd_via8233_setup_periods(via8233_t *chip, viadev_t *viadev, + snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime = substream->runtime; - int idx, frags; - unsigned int *table = viadev->table; unsigned long port = chip->port + viadev->reg_offset; + int v, err; - viadev->physbuf = runtime->dma_addr; viadev->size = snd_pcm_lib_buffer_bytes(substream); viadev->fragsize = snd_pcm_lib_period_bytes(substream); viadev->frags = runtime->periods; + 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; + } snd_via8233_channel_reset(chip, viadev); - outl(viadev->table_addr, port + VIA_REG_OFFSET_TABLE_PTR); + + err = build_via_table(viadev, substream, chip->pci); + if (err < 0) + return err; + + runtime->dma_bytes = viadev->size; + outl((u32)viadev->table_addr, port + VIA_REG_OFFSET_TABLE_PTR); if (viadev->reg_offset == VIA_REG_MULTPLAY_STATUS) { unsigned int slots; int fmt = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? VIA_REG_MULTPLAY_FMT_16BIT : VIA_REG_MULTPLAY_FMT_8BIT; @@ -378,27 +453,7 @@ 0xff000000, /* STOP index is never reached */ port + VIA_REG_OFFSET_STOP_IDX); } - - if (viadev->size == viadev->fragsize) { - table[0] = cpu_to_le32(viadev->physbuf); - table[1] = cpu_to_le32(0xc0000000 | /* EOL + flag */ - viadev->fragsize); - } else { - frags = viadev->size / viadev->fragsize; - for (idx = 0; idx < frags - 1; idx++) { - table[(idx << 1) + 0] = cpu_to_le32(viadev->physbuf + (idx * viadev->fragsize)); - table[(idx << 1) + 1] = cpu_to_le32(0x40000000 | /* flag */ - viadev->fragsize); - } - table[((frags-1) << 1) + 0] = cpu_to_le32(viadev->physbuf + ((frags-1) * viadev->fragsize)); - table[((frags-1) << 1) + 1] = cpu_to_le32(0x80000000 | /* EOL */ - viadev->fragsize); - } -#if 0 - printk("%s: size = %d frags = %d fragsize = %d\n", __FUNCTION__, viadev->size, frags, viadev->fragsize); - for (idx=0; idx < frags; idx++) - printk(" address %x, count %x\n", table[idx*2], table[idx*2+1]); -#endif + return 0; } /* @@ -407,18 +462,28 @@ static inline void snd_via8233_update(via8233_t *chip, viadev_t *viadev) { - snd_pcm_period_elapsed(viadev->substream); 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); + } + } } static void snd_via8233_interrupt(int irq, void *dev_id, struct pt_regs *regs) { via8233_t *chip = snd_magic_cast(via8233_t, dev_id, return); + spin_lock(&chip->reg_lock); if (inb(chip->port + chip->playback.reg_offset) & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG)) snd_via8233_update(chip, &chip->playback); if (inb(chip->port + chip->capture.reg_offset) & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG)) snd_via8233_update(chip, &chip->capture); + spin_unlock(&chip->reg_lock); } /* @@ -443,12 +508,12 @@ static int snd_via8233_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + return snd_pcm_sgbuf_alloc(substream, params_buffer_bytes(hw_params)); } static int snd_via8233_hw_free(snd_pcm_substream_t * substream) { - return snd_pcm_lib_free_pages(substream); + return 0; } static int snd_via8233_playback_prepare(snd_pcm_substream_t * substream) @@ -457,7 +522,6 @@ snd_pcm_runtime_t *runtime = substream->runtime; snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate); - snd_via8233_setup_periods(chip, &chip->playback, substream); if (chip->playback.reg_offset != VIA_REG_MULTPLAY_STATUS) { unsigned int tmp; /* I don't understand this stuff but its from the documentation and this way it works */ @@ -466,7 +530,7 @@ tmp = inl(VIAREG(chip, PLAYBACK_STOP_IDX)) & ~0xfffff; outl(tmp | (0xffff * runtime->rate)/(48000/16), VIAREG(chip, PLAYBACK_STOP_IDX)); } - return 0; + return snd_via8233_setup_periods(chip, &chip->playback, substream); } static int snd_via8233_capture_prepare(snd_pcm_substream_t * substream) @@ -475,10 +539,9 @@ snd_pcm_runtime_t *runtime = substream->runtime; snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); - snd_via8233_setup_periods(chip, &chip->capture, substream); outb(VIA_REG_CAPTURE_CHANNEL_LINE, VIAREG(chip, CAPTURE_CHANNEL)); outb(VIA_REG_CAPTURE_FIFO_ENABLE, VIAREG(chip, CAPTURE_FIFO)); - return 0; + return snd_via8233_setup_periods(chip, &chip->capture, substream); } static inline unsigned int snd_via8233_cur_ptr(via8233_t *chip, viadev_t *viadev) @@ -488,9 +551,14 @@ 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. */ - val = inb(VIAREG(chip, OFFSET_CURR_INDEX) + viadev->reg_offset) % viadev->frags; - val *= viadev->fragsize; - val += viadev->fragsize - count; + val = inb(VIAREG(chip, OFFSET_CURR_INDEX) + viadev->reg_offset) % viadev->tbl_entries; + 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, count = 0x%x, val = 0x%x\n", ptr, count, val); return val; } @@ -522,8 +590,8 @@ buffer_bytes_max: 128 * 1024, period_bytes_min: 32, period_bytes_max: 128 * 1024, - periods_min: 1, - periods_max: VIA_MAX_FRAGS, + periods_min: 2, + periods_max: 1024, fifo_size: 0, }; @@ -541,8 +609,8 @@ buffer_bytes_max: 128 * 1024, period_bytes_min: 32, period_bytes_max: 128 * 1024, - periods_min: 1, - periods_max: VIA_MAX_FRAGS, + periods_min: 2, + periods_max: 1024, fifo_size: 0, }; @@ -569,8 +637,14 @@ runtime->hw.rates = chip->ac97->rates_front_dac; if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000)) 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 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels); return 0; } @@ -586,8 +660,14 @@ runtime->hw.rates = chip->ac97->rates_adc; if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000)) 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; } @@ -596,6 +676,8 @@ via8233_t *chip = snd_pcm_substream_chip(substream); snd_via8233_channel_reset(chip, &chip->playback); + clean_via_table(&chip->playback, substream, chip->pci); + snd_pcm_sgbuf_delete(substream); chip->playback.substream = NULL; /* disable DAC power */ snd_ac97_update_bits(chip->ac97, AC97_POWERDOWN, 0x0200, 0x0200); @@ -607,6 +689,8 @@ via8233_t *chip = snd_pcm_substream_chip(substream); snd_via8233_channel_reset(chip, &chip->capture); + clean_via_table(&chip->capture, substream, chip->pci); + snd_pcm_sgbuf_delete(substream); chip->capture.substream = NULL; /* disable ADC power */ snd_ac97_update_bits(chip->ac97, AC97_POWERDOWN, 0x0100, 0x0100); @@ -622,6 +706,9 @@ prepare: snd_via8233_playback_prepare, trigger: snd_via8233_playback_trigger, pointer: snd_via8233_playback_pointer, + copy: snd_pcm_sgbuf_ops_copy_playback, + silence: snd_pcm_sgbuf_ops_silence, + page: snd_pcm_sgbuf_ops_page, }; static snd_pcm_ops_t snd_via8233_capture_ops = { @@ -633,13 +720,15 @@ prepare: snd_via8233_capture_prepare, trigger: snd_via8233_capture_trigger, pointer: snd_via8233_capture_pointer, + copy: snd_pcm_sgbuf_ops_copy_capture, + silence: snd_pcm_sgbuf_ops_silence, + page: snd_pcm_sgbuf_ops_page, }; static void snd_via8233_pcm_free(snd_pcm_t *pcm) { via8233_t *chip = snd_magic_cast(via8233_t, pcm->private_data, return); chip->pcm = NULL; - snd_pcm_lib_preallocate_free_for_all(pcm); } static int __devinit snd_via8233_pcm(via8233_t *chip, int device, snd_pcm_t ** rpcm) @@ -662,8 +751,6 @@ strcpy(pcm->name, "VIA 8233"); chip->pcm = pcm; - snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 128*1024); - if (rpcm) *rpcm = NULL; return 0; @@ -758,14 +845,8 @@ snd_via8233_channel_reset(chip, &chip->playback); snd_via8233_channel_reset(chip, &chip->capture); /* --- */ + synchronize_irq(chip->irq); __end_hw: - if (chip->irq) - synchronize_irq(chip->irq); - if (chip->tables) - snd_free_pci_pages(chip->pci, - VIA_NUM_OF_DMA_CHANNELS * sizeof(unsigned int) * VIA_MAX_FRAGS * 2, - chip->tables, - chip->tables_addr); if (chip->res_port) { release_resource(chip->res_port); kfree_nocheck(chip->res_port); @@ -831,21 +912,6 @@ chip->capture.reg_offset = VIA_REG_CAPTURE_STATUS; - /* allocate buffer descriptor lists */ - /* the start of each lists must be aligned to 8 bytes */ - chip->tables = (unsigned int *)snd_malloc_pci_pages(pci, - VIA_NUM_OF_DMA_CHANNELS * sizeof(unsigned int) * VIA_MAX_FRAGS * 2, - &chip->tables_addr); - if (chip->tables == NULL) { - snd_via8233_free(chip); - return -ENOMEM; - } - /* tables must be aligned to 8 bytes, but the kernel pages - are much bigger, so we don't care */ - chip->playback.table = chip->tables; - chip->playback.table_addr = chip->tables_addr; - chip->capture.table = chip->playback.table + VIA_MAX_FRAGS * 2; - chip->capture.table_addr = chip->playback.table_addr + sizeof(unsigned int) * VIA_MAX_FRAGS * 2; if ((err = snd_via8233_chip_init(chip)) < 0) { snd_via8233_free(chip); return err; =================================================================== This BitKeeper patch contains the following changesets: 1.605.2.19 ## Wrapped with gzip_uu ## begin 664 bkpatch2542 M'XL(`!I%EST``^1<>W?:2++_&SY%)W,F"P[&:KV%$\\00S+L.+:/[63G[F2. MCI`:6\<@$4G$]@[Y[K>J6P(!$F"2NBJGA_(NYA%KR^^@/Y)8R35B6>Q*SI_@>>+\(0G@]NPA$[X&4.^K<'0S^8W._'X23P\O=5 M*'_N).X-^<2BN%6A367V)GD8LU;EHOOFW4G[HEI]^9(0$\8@E3M,-1]-9T:DL23+\3Z.&(FGZE.J2:DQ=ZE'J MJ)1YDJR:NEKEC/X\#L*$-?G]OA\DT)]E0I:L2Y9D:MJ46K(L53N$-G5):\I- M:A%)/I"L`UDGE+8T#?Z>2W)+DD@9RIA,O\F&IP..`CPXR,0RA)Y,Q"8.TS+]_2ZN\[[5-65'@SA^-APR).8D/ MY<(!N7Q#^I/!`(;D5T)-2=:KY_,%5MU_Y+]J57*DZE$&=?S%U2,6_-CU#]AH M0J5;BM?1>*)*M.FF:*8*M12X`II5Q9B:AF=(`UGW3V(:?`K(94^94UQ2-SIG:;JBY!)W3TJ@*X%2GU%!-=-21/,$!.?J.I0E0[&FCN0HC/7[LNO0`56<;=?A$MF4 M*95.J2S3`J9$+3>,@`#[B/^WN0HJ`)BLJ-J4*8:BZ+ILLKYA:0-WTT"54TY9 MH_I44U6I=/(6"*#^_%@@YRW)H%.`E4>5?A_4N00FU9HAVT1YSIHN6\;:-0D@ MT,V5Y8BPHKHUU0U-U4W#=23#\$QI*XFU2#%#E0(05_3U^L9EU*!RP#'SH&72-2ZSY,P-4NRIK(%%N?4 M-4W%L#S%<51C`,.T&T74,^I4DDUY1UEULRBKM*EJJAJ,F68.=%WS+,?2F2J9 M7T0Z$P\ZI9:^;B)'#HN3*%P15C"3H*M`90U@16LN3*)L@>&^E=)9ICG'%:P5 MJ]30*E@C-ZNK3S4,`3+&+&]@J0-IHU0O)SQ??(!6NJT).'9'1?:?I:$W,]`4 MSP$=K3FRX6PUB<64Y\:?K$(+:UD+8JH81;:?).F@;RRFJQH=P/K26%_>2M\L MD9P;#K*DFFO'"=PK+K@6VC*Z#S%+4OFHHGJ2HGJ*9[E;&0PGIC#E82"`` M3>YLEQN,Z'U_9;NUW/_>;+=JL"P4R01@PTKE#KFYX(DKM"5+FSWQO\H1OW)N MG?C&)[T[QR.E5;,OQI,Q_]2_WQY@*=7=WQ)OB'PB4X M(_O1'?\#?^]\#4!V\!Y[5%,)K58X/[4]WK\ZJ7&J"=G#:_T02ID2EIH$L7\= M`)

PL=.R0'>P2&*KS+7L\[`O[Q\('L'12@>V:&;83V(^W`;7%=8`>"VI5E MM`,EE8.:ZLNH5NE&5%.R3_\25+_CVTD>P=\#-!2S+I!!%(XX(/D.U/'[2Y)$ MC.$F`S=IUX)H-@P[(*BC`#)Z^/.#QP9^P,CQV>GKWAO[\K1C=]I77?*4U/X% M+/]S,B2XW+26;,(?7X+DW=5Q_2E'1KFU60".+S5Z4WKIYND6Y``3X.'1J::; MDLEQH2S#@NJ;80'2CGX'XLYLT;FXVV%'+I-P0)_$@6<[<V']3$$T@V,FC,BK!/+$A$ M$?R"-W64C#+*/*3E`JO)(32B:<2$+[I,Y&HEUW,@%K%D$@5DO]L[?=\^`:&9 M_XXD"XITA%S-Q&NEDI:0N,@U\1UOFKPD5()_7,R^[OWVMMLB+`@GUS>D[U\W MB!\'_TB(G_R$8K8'8I%H0,T?D-H3LK_/2=3)G]A`//8#>Q+@UB7N@(*\!RBR MVK/!_A&^:W`-%2/W%0W-9^[5ZE1P8?T!)X>M?WF7]_U5J MX;&K7_^_7/W"0=EV]>^D@U0$5(__LGL`)(](;!(!I1*`"X!25*;;,]NA\E&[ M1)NUTB(Y64=T:])4HYHA8F+J#JA4OA-4JE**RL?'>1!F8G]L,\S2,=S)U-%- M;NS`!>2_D*_)*-H_RK$C!&T&+-Z8S3M4@Y)H2X-SBM+O;$@#'+\@^DLZ2T-_U+^OTK`%A80C_$4+J!"7.RR@BPN MJ/GOGT2Z5ZFJ:HHN->!^D/YKD*?0#=/4GC8J%-%$6L9^P9F4'X.GSTCL,+!2++[?E*#5PTB2L&M M[;@N`]7GU>M50C)3Y[#Z`]`"82QKG%-9,V>V(H[='2A29KL.*$K>(%J%0!56 MPH2!=`#KR*+*5^`H;TM^0+M85X@.=SFZJ;./XBKWHI;Z_)7*=0B@M5.B=GA[ MB$(+:8%H(6HAK8.#S#QUAG?.0\P7$)BU=2\_:(!JL"@@V4M@(,=9L.8S=_/I@P9GL\5 MWPZQ)`U-[$>.)>\\O!9#,!M.BR(2%[ZUEI7#\O[A>N6PVT;F5LJA;",3E`.H M!VNJJHHJ'&1K13=LSLL!4T3^AJH!655:LMS2,O=XM\P1-$?$CFZY-%T>R)V< M7LM00+H`A`PULTBX<`:+)/I(C@#2WB M#ID3D>B>>W_A)"$UL+Z32/G&O#&W];YOIJJB]U` MO;RMD>_Y-F\0J9*!XP_17D[P<7B_U&@#=]R=C(,G3YX@$^4+@$=#MT7_(X*R MVZCHLJ`L2$_54O2I)*FZSD%O[`!Z_;N(URD@Z%/07X,[)MPUW,,"/`R'H2NR M+?N`'1Y\0OB[SACL8?#D)OTX@6(C$6'C$>IM@,_'G9@]8SE*$(8X=K,V^`$RAVOY1VL_? M+T\[%^_M\^.W]N751;?]UCYNGU^]N^C^T9P3(T6W:`5G]_M'X+@F]6PU%?0$ M!LP>.]5DK47/(Y/!MA&_*\E@PC/")#E-$\8&E59`LSFD_#>R-D1:7"EH9B.X4R1` MXK*SEUZYW0H$%QVBCIJ&"]/K"K2`C1)8S3++U^/JD4GM6P%K):E=D\`^IAH& MI66C;$-6_F\21R*]OQQ9LR'<21Y1R>#RB$IF$6AF[M$*:N9IA6M1\]B,QL`DX$?M:>\"*U#AL.R0EX&,G$ M8^1XG-1%$(C_\#$B[?^X3;^RA.+;&A+ZZEA;2T$%S3 M=!S_D`<,Q.`._5N6#CN.1HSS=7?#@L)`&XP!$W$XYL'08V"ADFMX!#,?\3#" M[W^`[X,[I^UCR[#?MB^ONA<-PA]^Z;8[Y[^M;(*IP?VZ^Z MW?.TQ$+IWG%Z=]*#EUF%][U.]RS]T'[W6U;Q^&UZ=]$]MB^[)[/R^/RFW3M- M/[_IGG8OVB?V^;N+\[/+K"VE8Q^?G5Y=G,WK=7^[ZIYVNAV[UTD+S=Y<7K6O MWEW..8*W9Q=0CJ8%9R]D++./^\6'?(+,=(*X4L2(1U,$244(A4]-%DB!U[C? M#(C&$!4GH8>K-^KC9B7=I(`?H\-RE7GHM`:V2)J.) M:Z&LAT*&(0KQ:R&E1860'7E9JPL>=])F&[MS]:2-J5D4)*^LF5J9/[.%V:!\ M%VD`M*49*W)?9#'Y(DP>19-Q$@N9@A_%Z5T2@[`E?LRS49PA3XO^-J)79].UDM(B0J[B`R,UV?A*RAY?!Z!`CLYK.S6+P0H@AP(X!U!<$6@8@[Q\E M_:$-O$8^C.X^H2(BA47V7BZ4P1$]3#\]7_V$R6HB#[/RF6"H=DLZM>P;)_+C M2M$Z>4YHGGBUHXN-!UV9Y?G4``:I0.,[``AO7:"VWPR76.-_W4N1Z'89` MR@7B^1971] MV[YZ=6*_ZEW9KT_:;RK2O2J)?X5ENF1[]\MO<[+P$&W88#+J@S(!,'@L M=B-_#'@EB8-IN)G(1!MUA0:7<16DP*4:U'=RU1Y$)44F>_PESQL?WSS$O@LR MT?$\L,1B$'L\10V+>B/'QM<@V7D%_I">^]&LO''2G_A#SP80V+Q@*EQ1(\"E M0=:'+-!PK``XX6GBPOBY/IHZJ$S\>O7/U+AOD%2`IZ5X*N6U#?@`2@B35%B. MG&O?M5TG!D&Y(#N31CYJ@5T;1_XG<',+,O#3)":A$+!#\_1-'IB9QS2X[#UO MO^G:[9/>F]/:BFK;(V:]0>:4\O=\/'G`8_X.NG'Z[N0D30.JI`>H,)*2F1@Y M2`Q]%`LX53-V$71\\E\(MBY[_^X*[A?5YDNR4/PP7R#C/5]F5F`!WJEIGM.\ MRZW,F"AI@4^.H%K>QF+/CHY2JK_T7E_Q@<)A2O,QHP1ASQSW)AV=T20&?++, M&L.42Y/T'T"B`NY@>C`MWZ'@"T+1[W7'$SL)[2%3Y!IVM9Y.G2@G_=%$CD%\+$[6 M'O'KBPCY2]GP!1MU`8L\TE.4;VH=;5'!00[.G'1-\,`-PV5&EG4-F9)%:Q*A M+V)`\\R,S]E-%+J08?#5+ON+)*T6AZ^HJ:GG= MCJ)RST%1=;CDU"8.2VHYV3%,V!B%GA]Z<2U[B^=.P$!OD/D-LQ7 M'9NW>/,:S2P8F&7A'2B:.*BIZ<2LSK@75HI@_L-,N@K>A&F1254\!Q3>"5M% MYB+Q$U0;>O+,O\HD02;+EM^3)R`Y*8+\4WT.%IZ7X^7R39"BDU\SOG,&Z`2,*6NPY-TXONF_LL]>O+[M7]E7[U4G7 M/K^ZP!TGQ02;F0*AN8Y*)1'#I,1:'/%Y`L>S9V0)J*G[O3#_SY\?I@G5 M2[@XFO=G05.GIPF+4+1XR+"6[I_A?AP^YTX6HF'/<6:SH3..F;?*?GU.KI38 M9YQN&`2>5;:N:$^5Z:Q,*7<=5:2.B4M^GW!N8'*=G_?.A8-B"[--(*%V4KLBL#_&P(L\/P!/)GF__?^6%*^/Q;?2ERV MQ\I7\)(B6NR]QX8L8;7\JNSITO]VZ.:'LJ6?'X'QA"3 M-JMPLQ^S_'=<,=Q$#I9PLBFA;_Z&&J#CTS72$KBYX92I;QU+=!&;-<\8S6'Z MEQF,%$1BDD*0N5N"_P2_2DL8X)=(&YU)LX#&%H6["F!L>\IAVBWV.2F'\6KR MN]$`D_U[FO%!>B3/]ZQ1[CBD-`JJHE6BGL4ET;HW9*7$-156*%,#Q^\%CH]% M%Y]@4^0/X$S:]%2"Z4OZC@UVR"\D)UMHVDP$_)\03&B$XU_JNKD&W=9JEVZK MQ#@;T&W3E=7"VSE\F(8=!5;G3-I,WXF2Y13+9PASY&-,\@J?;HIQBO39C,X( M8>*S'T28_MQZGW&P56C;VH-Y4TH!@\@9S5G:?7,ZGN.'Z1O2,R*>FHKL*3;%0Q8<1QH>B[P/<-[<8!=!+^R* MR1'U0>^JZ9OJ>H5T[B>W#\[3HYS=93HMU=S<Y?#_=5(CB]QO; /= Linux Kernel Sound Maintainer ALSA Project http://www.alsa-project.org SuSE Linux http://www.suse.com - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/