Commit e2fa3083 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

[PATCH] ALSA update [8/10] - 2002/07/31

  - 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
parent b21fd933
......@@ -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 @@ struct _snd_ac97 {
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 {
......
/* 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)"
......@@ -146,20 +146,15 @@ static inline int compare_timestamp_rel(snd_seq_event_t *a, snd_seq_event_t *b)
}
/* 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 @@ void snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell)
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 @@ void snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell)
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 @@ void snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell)
/* 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 @@ void snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell)
f->tail = cell;
f->cells++;
spin_unlock_irqrestore(&f->lock, flags);
return 0;
}
/* dequeue cell from prioq */
......
......@@ -41,7 +41,7 @@ extern prioq_t *snd_seq_prioq_new(void);
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);
......
......@@ -365,9 +365,11 @@ void snd_seq_timer_continue(seq_timer_t * tmr)
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);
......
......@@ -168,7 +168,7 @@ static int __init snd_card_dt019x_isapnp(int dev, struct snd_card_dt019x *acard)
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)
......
......@@ -91,10 +91,10 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 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 @@ void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value
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 @@ static void snd_ac97_write_cache_test(ac97_t *ac97, unsigned short reg, unsigned
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 @@ static int snd_ac97_try_volume_mix(ac97_t * ac97, int reg)
{
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 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
*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 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
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 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
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,6 +1752,9 @@ static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffe
int reg, val;
for (reg = 0; reg < 0x80; reg += 2) {
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 @@ void snd_ac97_resume(ac97_t *ac97)
{
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 @@ void snd_ac97_resume(ac97_t *ac97)
break;
mdelay(1);
}
__reset_ready:
if (ac97->init)
ac97->init(ac97);
......
......@@ -300,6 +300,20 @@ int patch_ad1881(ac97_t * ac97)
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);
......
......@@ -35,4 +35,5 @@ int patch_cirrus_spdif(ac97_t * ac97);
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);
......@@ -1970,9 +1970,10 @@ static void snd_ali_resume(struct pci_dev *dev)
static int snd_ali_free(ali_t * codec)
{
snd_ali_disable_address_interrupt(codec);
if (codec->irq >= 0) {
synchronize_irq(codec->irq);
if (codec->irq >=0)
free_irq(codec->irq, (void *)codec);
}
if (codec->res_port) {
release_resource(codec->res_port);
kfree_nocheck(codec->res_port);
......
......@@ -1300,7 +1300,7 @@ static int snd_cs4281_free(cs4281_t *chip)
}
#endif
snd_cs4281_proc_done(chip);
if(chip->irq >= 0)
if (chip->irq >= 0)
synchronize_irq(chip->irq);
/* Mask interrupts */
......
......@@ -64,7 +64,7 @@ static void mpu401_clear_rx(emu10k1_t *emu, emu10k1_midi_t *mpu)
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 @@ static void snd_emu10k1_midi_cmd(emu10k1_t * emu, emu10k1_midi_t *midi, unsigned
}
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));
......
......@@ -968,11 +968,13 @@ static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
{
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)
......@@ -992,6 +994,10 @@ int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
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;
......
......@@ -1532,7 +1532,6 @@ static int snd_ensoniq_free(ensoniq_t *ensoniq)
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);
pci_set_power_state(ensoniq->pci, 3);
__hw_end:
......
......@@ -4072,7 +4072,7 @@ static int snd_ice1712_free(ice1712_t *ice)
/* --- */
__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 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
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);
......
......@@ -1104,7 +1104,6 @@ static int snd_intel8x0_free(intel8x0_t *chip)
outb(ICH_RESETREGS, ICHREG(chip, PO_CR));
outb(ICH_RESETREGS, ICHREG(chip, MC_CR));
/* --- */
if(chip->irq >= 0)
synchronize_irq(chip->irq);
__hw_end:
if (chip->bdbars)
......
......@@ -2310,7 +2310,7 @@ static int snd_m3_free(m3_t *chip)
vfree(chip->suspend_mem);
#endif
if(chip->irq >= 0)
if (chip->irq >= 0)
synchronize_irq(chip->irq);
if (chip->iobase_res) {
......
......@@ -892,7 +892,7 @@ static snd_pcm_ops_t snd_nm256_capture_ops = {
#endif
};
static int __init
static int __devinit
snd_nm256_pcm(nm256_t *chip, int device)
{
snd_pcm_t *pcm;
......@@ -1188,21 +1188,31 @@ snd_nm256_ac97_reset(ac97_t *ac97)
}
/* 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 @@ snd_nm256_mixer(nm256_t *chip)
* 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 @@ static int snd_nm256_free(nm256_t *chip)
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 @@ static int snd_nm256_dev_free(snd_device_t *device)
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,
......
......@@ -238,7 +238,7 @@ struct _snd_via686a {
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 @@ static inline unsigned int snd_via686a_cur_ptr(via686a_t *chip, viadev_t *viadev
val = 0;
else
val = ((ptr - (unsigned int)viadev->table_addr) / 8 - 1) % 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;
}
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 @@ static int snd_via686a_playback_open(snd_pcm_substream_t * substream)
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 @@ static int snd_via686a_capture_open(snd_pcm_substream_t * substream)
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 @@ static int __devinit snd_via686a_create(snd_card_t * card,
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;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment