diff -u linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c --- linux/drivers/sound/i810_audio.c.alan Thu Aug 8 16:05:48 2002 +++ linux/drivers/sound/i810_audio.c Thu Aug 8 16:08:23 2002 @@ -213,7 +213,7 @@ #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) -#define DRIVER_VERSION "0.21" +#define DRIVER_VERSION "0.22" /* magic numbers to protect our data structures */ #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -354,7 +354,6 @@ struct i810_card { - struct i810_channel channel[3]; unsigned int magic; /* We keep i810 cards in a linked list */ @@ -378,6 +377,8 @@ /* structures for abstraction of hardware facilities, codecs, banks and channels*/ struct ac97_codec *ac97_codec[NR_AC97]; struct i810_state *states[NR_HW_CH]; + struct i810_channel *channel; /* 1:1 to states[] but diff. lifetime */ + dma_addr_t chandma; u16 ac97_features; u16 ac97_status; @@ -732,6 +733,8 @@ outb(0, card->iobase + PI_CR); // wait for the card to acknowledge shutdown while( inb(card->iobase + PI_CR) != 0 ) ; + // reset the dma engine now + outb(0x02, card->iobase + PI_CR); // now clear any latent interrupt bits (like the halt bit) if(card->pci_id == PCI_DEVICE_ID_SI_7012) outb( inb(card->iobase + PI_PICB), card->iobase + PI_PICB ); @@ -757,7 +760,8 @@ if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_INPUT)) { dmabuf->enable |= ADC_RUNNING; - outb((1<<4) | (1<<2) | 1, state->card->iobase + PI_CR); + // Interrupt enable, LVI enable, DMA enable + outb(0x10 | 0x04 | 0x01, state->card->iobase + PI_CR); } } @@ -781,6 +785,8 @@ outb(0, card->iobase + PO_CR); // wait for the card to acknowledge shutdown while( inb(card->iobase + PO_CR) != 0 ) ; + // reset the dma engine now + outb(0x02, card->iobase + PO_CR); // now clear any latent interrupt bits (like the halt bit) if(card->pci_id == PCI_DEVICE_ID_SI_7012) outb( inb(card->iobase + PO_PICB), card->iobase + PO_PICB ); @@ -806,7 +812,8 @@ if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { dmabuf->enable |= DAC_RUNNING; - outb((1<<4) | (1<<2) | 1, state->card->iobase + PO_CR); + // Interrupt enable, LVI enable, DMA enable + outb(0x10 | 0x04 | 0x01, state->card->iobase + PO_CR); } } static void start_dac(struct i810_state *state) @@ -958,7 +965,7 @@ for(i=0;inumfrag;i++) { - sg->busaddr=virt_to_bus(dmabuf->rawbuf+dmabuf->fragsize*i); + sg->busaddr=(u32)dmabuf->dma_handle+dmabuf->fragsize*i; // the card will always be doing 16bit stereo sg->control=dmabuf->fragsamples; if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) @@ -973,7 +980,9 @@ } spin_lock_irqsave(&state->card->lock, flags); outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ - outl(virt_to_bus(&c->sg[0]), state->card->iobase+c->port+OFF_BDBAR); + outl((u32)state->card->chandma + + c->num*sizeof(struct i810_channel), + state->card->iobase+c->port+OFF_BDBAR); outb(0, state->card->iobase+c->port+OFF_CIV); outb(0, state->card->iobase+c->port+OFF_LVI); @@ -1295,7 +1304,6 @@ if (dmabuf->enable & ADC_RUNNING) __stop_adc(state); dmabuf->enable = 0; - wake_up(&dmabuf->wait); #ifdef DEBUG_INTERRUPTS printk(" STOP "); #endif @@ -1741,7 +1749,9 @@ } if (c != NULL) { outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ - outl(virt_to_bus(&c->sg[0]), state->card->iobase+c->port+OFF_BDBAR); + outl((u32)state->card->chandma + + c->num*sizeof(struct i810_channel), + state->card->iobase+c->port+OFF_BDBAR); outb(0, state->card->iobase+c->port+OFF_CIV); outb(0, state->card->iobase+c->port+OFF_LVI); } @@ -1884,12 +1894,14 @@ switch ( val ) { case 2: /* 2 channels is always supported */ - outl(state->card->iobase + GLOB_CNT, (i_glob_cnt & 0xcfffff)); + outl(i_glob_cnt & 0xcfffff, + state->card->iobase + GLOB_CNT); /* Do we need to change mixer settings???? */ break; case 4: /* Supported on some chipsets, better check first */ if ( state->card->channels >= 4 ) { - outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0100000)); + outl((i_glob_cnt & 0xcfffff) | 0x100000, + state->card->iobase + GLOB_CNT); /* Do we need to change mixer settings??? */ } else { val = ret; @@ -1897,7 +1909,8 @@ break; case 6: /* Supported on some chipsets, better check first */ if ( state->card->channels >= 6 ) { - outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0200000)); + outl((i_glob_cnt & 0xcfffff) | 0x200000, + state->card->iobase + GLOB_CNT); /* Do we need to change mixer settings??? */ } else { val = ret; @@ -2415,6 +2428,9 @@ i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked); } else { i810_set_dac_rate(state, 8000); + /* Put the ACLink in 2 channel mode by default */ + i = inl(card->iobase + GLOB_CNT); + outl(i & 0xffcfffff, card->iobase + GLOB_CNT); } } @@ -2674,7 +2690,10 @@ card->channels = 6; else if ( reg & 0x0100000 ) card->channels = 4; - printk("i810_audio: Audio Controller supports %d channels.\n", card->channels); + printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels); + printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n"); + reg = inl(card->iobase + GLOB_CNT); + outl(reg & 0xffcfffff, card->iobase + GLOB_CNT); inw(card->ac97base); @@ -2707,7 +2726,7 @@ codec->codec_write = i810_ac97_set; if(!i810_ac97_probe_and_powerup(card,codec)) { - printk("i810_audio: timed out waiting for codec %d analog ready.\n", num_ac97); + printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", num_ac97); kfree(codec); break; /* it didn't work */ } @@ -2716,7 +2735,7 @@ /* Don't attempt to get eid until powerup is complete */ eid = i810_ac97_get(codec, AC97_EXTENDED_ID); - + if(eid==0xFFFFFF) { printk(KERN_WARNING "i810_audio: no codec attached ?\n"); @@ -2855,6 +2874,8 @@ init_MUTEX(&state->open_sem); dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT; dmabuf->trigger = PCM_ENABLE_OUTPUT; + i810_set_spdif_output(state, -1, 0); + i810_set_dac_channels(state, 2); i810_set_dac_rate(state, 48000); if(prog_dmabuf(state, 0) != 0) { goto config_out_nodmabuf; @@ -2863,6 +2884,8 @@ goto config_out; } dmabuf->count = dmabuf->dmasize; + stop_dac(state); + outb(0,card->iobase+dmabuf->write_channel->port+OFF_CIV); outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI); save_flags(flags); cli(); @@ -2871,10 +2894,9 @@ mdelay(50); new_offset = i810_get_dma_addr(state, 0); stop_dac(state); - outb(2,card->iobase+dmabuf->write_channel->port+OFF_CR); restore_flags(flags); i = new_offset - offset; -#ifdef DEBUG +#ifdef DEBUG_INTERRUPTS printk("i810_audio: %d bytes in 50 milliseconds\n", i); #endif if(i == 0) @@ -2939,15 +2961,26 @@ card->alloc_rec_pcm_channel = i810_alloc_rec_pcm_channel; card->alloc_rec_mic_channel = i810_alloc_rec_mic_channel; card->free_pcm_channel = i810_free_pcm_channel; - card->channel[0].offset = 0; - card->channel[0].port = 0x00; - card->channel[0].num=0; - card->channel[1].offset = 0; - card->channel[1].port = 0x10; - card->channel[1].num=1; - card->channel[2].offset = 0; - card->channel[2].port = 0x20; - card->channel[2].num=2; + + if ((card->channel = pci_alloc_consistent(pci_dev, + sizeof(struct i810_channel)*NR_HW_CH, &card->chandma)) == NULL) { + printk(KERN_ERR "i810: cannot allocate channel DMA memory\n"); + goto out_mem; + } + + { /* We may dispose of this altogether some time soon, so... */ + struct i810_channel *cp = card->channel; + + cp[0].offset = 0; + cp[0].port = 0x00; + cp[0].num = 0; + cp[1].offset = 0; + cp[1].port = 0x10; + cp[1].num = 1; + cp[2].offset = 0; + cp[2].port = 0x20; + cp[2].num = 2; + } /* claim our iospace and irq */ request_region(card->iobase, 64, card_names[pci_id->driver_data]); @@ -2958,8 +2991,7 @@ printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq); release_region(card->iobase, 64); release_region(card->ac97base, 256); - kfree(card); - return -ENODEV; + goto out_chan; } /* initialize AC97 codec and register /dev/mixer */ @@ -2967,8 +2999,7 @@ release_region(card->iobase, 64); release_region(card->ac97base, 256); free_irq(card->irq, card); - kfree(card); - return -ENODEV; + goto out_chan; } pci_set_drvdata(pci_dev, card); @@ -2989,11 +3020,17 @@ unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); kfree (card->ac97_codec[i]); } - kfree(card); - return -ENODEV; + goto out_chan; } card->initializing = 0; return 0; + + out_chan: + pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH, + card->channel, card->chandma); + out_mem: + kfree(card); + return -ENODEV; } static void __devexit i810_remove(struct pci_dev *pci_dev) diff -u linux/drivers/sound.org/i810_audio.c linux/drivers/sound/i810_audio.c --- linux/drivers/sound.org/i810_audio.c 2002-09-03 12:24:46.000000000 +0200 +++ linux/drivers/sound/i810_audio.c 2002-09-03 13:22:18.000000000 +0200 @@ -1,3 +1,4 @@ + /* * Intel i810 and friends ICH driver for Linux * Alan Cox @@ -116,6 +117,9 @@ #ifndef PCI_DEVICE_ID_AMD_768_AUDIO #define PCI_DEVICE_ID_AMD_768_AUDIO 0x7445 #endif +#ifndef PCI_DEVICE_ID_AMD_8111_AC97 +#define PCI_DEVICE_ID_AMD_8111_AC97 0x746d +#endif static int ftsodell=0; static int strict_clocking=0; @@ -728,8 +736,6 @@ outb(0, card->iobase + PI_CR); // wait for the card to acknowledge shutdown while( inb(card->iobase + PI_CR) != 0 ) ; - // reset the dma engine now - outb(0x02, card->iobase + PI_CR); // now clear any latent interrupt bits (like the halt bit) if(card->pci_id == PCI_DEVICE_ID_SI_7012) outb( inb(card->iobase + PI_PICB), card->iobase + PI_PICB ); @@ -780,8 +786,6 @@ outb(0, card->iobase + PO_CR); // wait for the card to acknowledge shutdown while( inb(card->iobase + PO_CR) != 0 ) ; - // reset the dma engine now - outb(0x02, card->iobase + PO_CR); // now clear any latent interrupt bits (like the halt bit) if(card->pci_id == PCI_DEVICE_ID_SI_7012) outb( inb(card->iobase + PO_PICB), card->iobase + PO_PICB ); @@ -978,8 +982,9 @@ outl((u32)state->card->chandma + c->num*sizeof(struct i810_channel), state->card->iobase+c->port+OFF_BDBAR); - outb(0, state->card->iobase+c->port+OFF_CIV); - outb(0, state->card->iobase+c->port+OFF_LVI); + // The next two lines aren't needed, the reset clears these to 0 + // outb(0, state->card->iobase+c->port+OFF_CIV); + // outb(0, state->card->iobase+c->port+OFF_LVI); spin_unlock_irqrestore(&state->card->lock, flags); @@ -1747,8 +1752,10 @@ outl((u32)state->card->chandma + c->num*sizeof(struct i810_channel), state->card->iobase+c->port+OFF_BDBAR); - outb(0, state->card->iobase+c->port+OFF_CIV); - outb(0, state->card->iobase+c->port+OFF_LVI); + // The next two lines aren't needed since the DMA + // reset clears out these registers + // outb(0, state->card->iobase+c->port+OFF_CIV); + // outb(0, state->card->iobase+c->port+OFF_LVI); } spin_unlock_irqrestore(&state->card->lock, flags); @@ -1889,13 +1896,13 @@ switch ( val ) { case 2: /* 2 channels is always supported */ - outl(i_glob_cnt & 0xcfffff, + outl(i_glob_cnt & 0xffcfffff, state->card->iobase + GLOB_CNT); /* Do we need to change mixer settings???? */ break; case 4: /* Supported on some chipsets, better check first */ if ( state->card->channels >= 4 ) { - outl((i_glob_cnt & 0xcfffff) | 0x100000, + outl((i_glob_cnt & 0xffcfffff) | 0x100000, state->card->iobase + GLOB_CNT); /* Do we need to change mixer settings??? */ } else { @@ -1904,7 +1911,7 @@ break; case 6: /* Supported on some chipsets, better check first */ if ( state->card->channels >= 6 ) { - outl((i_glob_cnt & 0xcfffff) | 0x200000, + outl((i_glob_cnt & 0xffcfffff) | 0x200000, state->card->iobase + GLOB_CNT); /* Do we need to change mixer settings??? */ } else { @@ -2590,9 +2597,7 @@ i810_ac97_set(codec, AC97_POWER_CONTROL, i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00); /* wait for analog ready */ - for (i=10; - i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); - i--) + for (i=10; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/20); @@ -2600,8 +2605,14 @@ return i; } -/* if I knew what this did, I'd give it a better name */ -static int i810_ac97_random_init_stuff(struct i810_card *card) +/** + * i810_ac97_power_up_bus - bring up AC97 link + * @card : ICH audio device to power up + * + * Bring up the ACLink AC97 codec bus + */ + +static int i810_ac97_power_up_bus(struct i810_card *card) { u32 reg = inl(card->iobase + GLOB_CNT); int i; @@ -2612,8 +2623,13 @@ reg|=4; /* Warm */ reg&=~8; /* ACLink on */ - outl(reg , card->iobase + GLOB_CNT); + /* At this point we deassert AC_RESET # */ + outl(reg , card->iobase + GLOB_CNT); + + /* We must now allow time for the Codec initialisation. + 600mS is the specified time */ + for(i=0;i<10;i++) { if((inl(card->iobase+GLOB_CNT)&4)==0) @@ -2630,7 +2646,24 @@ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/2); + + /* + * See if the primary codec comes ready. This must happen + * before we start doing DMA stuff + */ + reg = inl(card->iobase + GLOB_STA); + if(!(reg & 0x100)) + { + printk(KERN_INFO "i810_audio: Codec not ready.. wait.. "); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); /* actually 600mS by the spec */ + reg = inl(card->iobase + GLOB_STA); + if(reg & 0x100) + printk("OK\n"); + else + printk("no response.\n"); + } inw(card->ac97base); return 1; } @@ -2643,7 +2676,7 @@ u16 eid; u32 reg; - if(!i810_ac97_random_init_stuff(card)) return 0; + if(!i810_ac97_power_up_bus(card)) return 0; /* Number of channels supported */ /* What about the codec? Just because the ICH supports */ @@ -2721,7 +2754,7 @@ } card->ac97_features = eid; - + /* Now check the codec for useful features to make up for the dumbness of the 810 hardware engine */ @@ -2735,6 +2768,11 @@ } } + /* Turn on the amplifier */ + + codec->codec_write(codec, AC97_POWER_CONTROL, + codec->codec_read(codec, AC97_POWER_CONTROL) & ~0x8000); + /* Determine how many channels the codec(s) support */ /* - The primary codec always supports 2 */ /* - If the codec supports AMAP, surround DACs will */ @@ -2849,7 +2887,10 @@ } dmabuf->count = dmabuf->dmasize; stop_dac(state); - outb(0,card->iobase+dmabuf->write_channel->port+OFF_CIV); + // OFF_CIV is a readonly register on some chipsets. But, we + // know it will be 0 anyway because prog_dmabuf() resets the + // DMA hardware, which 0's out all the DMA registers + // outb(0,card->iobase+dmabuf->write_channel->port+OFF_CIV); outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI); save_flags(flags); cli(); @@ -2860,7 +2901,7 @@ stop_dac(state); restore_flags(flags); i = new_offset - offset; -#ifdef DEBUG_INTERRUPTS +#ifdef DEBUG printk("i810_audio: %d bytes in 50 milliseconds\n", i); #endif if(i == 0) @@ -3087,7 +3128,7 @@ hardware has to be more or less completely reinitialized from scratch after an apm suspend. Works For Me. -dan */ - i810_ac97_random_init_stuff(card); + i810_ac97_power_up_bus(card); for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { struct ac97_codec *codec = card->ac97_codec[num_ac97];