From: Juergen Sawinski <juergen.sawinski@mpimf-heidelberg.mpg.de>
To: "linux-kernel@vger" <linux-kernel@vger.kernel.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>,
Jim Radford <radford@robotics.caltech.edu>,
Andris Pavenis <pavenis@latnet.lv>,
Doug Ledford <dledford@redhat.com>
Subject: [PATCH 2.4.20-pre4-ac2] fix broken i810_audio DMA (?)
Date: 29 Aug 2002 18:26:18 +0200 [thread overview]
Message-ID: <1030638379.2726.3.camel@voyager> (raw)
In-Reply-To: <1030585168.2548.18.camel@volans>
[-- Attachment #1: Type: text/plain, Size: 1542 bytes --]
F*ck. This time the patch attached.
Thanx Jim.
George
On Thu, 2002-08-29 at 03:39, Juergen Sawinski wrote:
> Changes:
> -remove dma reset in stop_{dac,adc}
> (from ICH4 manual: contents of all Bus master related registers to be
> reset; so, probably some registers are not re-initilized properly on
> consecutive re-opening of /dev/dsp ???)
> -remove writes to OFF_CIV, instead set LVI relative to CIV
>
> and some stuff that was already in the last diff I send to the list:
> -implement a codec ID <-> IO register offset mapping
> -in i810_ioctl, case SNDCTL_DSP_CHANNELS: only touch bits 20:21
> off GLOB_CNT (multichannel capabilities)
> -AMD 8111 has 6 hw channels so I must have mmio (but I don't have
> any docs to verify this)
> -minor fixes
>
> --
> Juergen "George" Sawinski
> Max-Planck Institute for Medical Research
> Dept. of Biomedical Optics
> Jahnstr. 29
> D-69120 Heidelberg
> Germany
>
> Phone: +49-6221-486-308
> Fax: +49-6221-486-325
>
> priv.
> Phone: +49-6221-418 858
> Mobile: +49-171-532 5302
>
>
> -
> 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/
--
Juergen "George" Sawinski
Max-Planck-Institute for Medical Research
Dept. of Biomedical Optics
Jahnstr. 29
D-69120 Heidelberg
Germany
Phone: +49-6221-486-309
Fax: +49-6221-486-325
priv.
Phone: +49-6221-418 848
Mobile: +49-171-532 5302
[-- Attachment #2: diff-pre4-ac2-jsaw-2 --]
[-- Type: text/plain, Size: 10147 bytes --]
--- linux-2.4.20-pre4-ac2/drivers/sound/i810_audio.c Tue Aug 27 21:44:25 2002
+++ jsaw/drivers/sound/i810_audio.c Thu Aug 29 03:18:16 2002
@@ -69,12 +69,12 @@
*
* ICH 4 caveats
*
- * The ICH4 has the feature, that the codec ID may not be congruent
- * with the AC-link channel.
+ * The ICH4 has the feature, that the codec ID doesn't have to be
+ * congruent with the IO connection.
*
- * Right now, the codec ID is not the real codec ID but the AC-link
- * channel. A ID <-> AC-link mapping has still to be implemented.
- *
+ * Therefore, from driver version 0.23 on, there is a "codec ID" <->
+ * "IO register base offset" mapping (card->ac97_id_map) field.
+ *
* Juergen "George" Sawinski (jsaw)
*/
@@ -207,7 +207,7 @@
CAS = 0x34 /* Codec Write Semaphore Register */
};
-ENUM_ENGINE(MC2,4); /* Mic. 2 */
+ENUM_ENGINE(MC2,4); /* Mic In 2 */
ENUM_ENGINE(PI2,5); /* PCM In 2 */
ENUM_ENGINE(SP,6); /* S/PDIF */
@@ -234,8 +234,7 @@
#define INT_GPI (1<<0)
#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
-
-#define DRIVER_VERSION "0.22"
+#define DRIVER_VERSION "0.23"
/* magic numbers to protect our data structures */
#define I810_CARD_MAGIC 0x5072696E /* "Prin" */
@@ -295,7 +294,7 @@
/*@FIXME to be verified*/ { 2, 0x0000 }, /* SI7012 */
/*@FIXME to be verified*/ { 2, 0x0000 }, /* NVIDIA_NFORCE */
/*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD768 */
- /*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD8111 */
+ /*@FIXME to be verified*/ { 3, 0x0001 }, /* AMD8111 */
};
static struct pci_device_id i810_pci_tbl [] __initdata = {
@@ -417,6 +416,7 @@
int dev_audio;
/* structures for abstraction of hardware facilities, codecs, banks and channels*/
+ u16 ac97_id_map[NR_AC97];
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 */
@@ -449,6 +449,12 @@
int initializing;
};
+/* extract register offset from codec struct */
+#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
+
+/* set LVI from CIV */
+#define CIV_TO_LVI(port, off) outb((inb(port+OFF_CIV)+off) & 31, port+OFF_LVI)
+
static struct i810_card *devs = NULL;
static int i810_open_mixdev(struct inode *inode, struct file *file);
@@ -786,8 +792,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 );
@@ -838,8 +842,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 );
@@ -1033,11 +1035,11 @@
}
spin_lock_irqsave(&state->card->lock, flags);
outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */
+ while( inb(state->card->iobase+c->port+OFF_CR) & 0x02 ) ;
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);
+ CIV_TO_LVI(state->card->iobase+c->port, 0);
spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1083,13 +1085,13 @@
if(rec && dmabuf->count < dmabuf->dmasize &&
(dmabuf->trigger & PCM_ENABLE_INPUT))
{
- outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI);
+ CIV_TO_LVI(port, 1);
__start_adc(state);
while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
} else if (!rec && dmabuf->count &&
(dmabuf->trigger & PCM_ENABLE_OUTPUT))
{
- outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI);
+ CIV_TO_LVI(port, 1);
__start_dac(state);
while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
}
@@ -1802,11 +1804,11 @@
}
if (c != NULL) {
outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */
+ while ( inb(state->card->iobase+c->port+OFF_CR) & 2 );
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);
+ CIV_TO_LVI(state->card->iobase+c->port, 0);
}
spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1948,13 +1950,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 {
@@ -1963,7 +1965,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 {
@@ -2553,8 +2555,7 @@
{
struct i810_card *card = dev->private_data;
int count = 100;
- u16 reg_set = ((u16) reg) & 0x7f;
- reg_set |= ((u16) dev->id) << 7;
+ u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (readb(card->iobase_mmio + CAS) & 1))
udelay(1);
@@ -2574,7 +2575,7 @@
{
struct i810_card *card = dev->private_data;
int count = 100;
- u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f));
+ u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (inb(card->iobase + CAS) & 1))
udelay(1);
@@ -2586,8 +2587,7 @@
{
struct i810_card *card = dev->private_data;
int count = 100;
- u16 reg_set = ((u16) reg) & 0x7f;
- reg_set |= ((u16) dev->id) << 7;
+ u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (readb(card->iobase_mmio + CAS) & 1))
udelay(1);
@@ -2603,7 +2603,7 @@
{
struct i810_card *card = dev->private_data;
int count = 100;
- u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f));
+ u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (inb(card->iobase + CAS) & 1))
udelay(1);
@@ -2779,7 +2779,7 @@
if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4)
&& (card->use_mmio)) {
primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
- printk(KERN_INFO "i810_audio: primary codec id %d\n",
+ printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
primary_codec_id);
}
@@ -2803,6 +2803,7 @@
int num_ac97 = 0;
int ac97_id;
int total_channels = 0;
+ int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97;
struct ac97_codec *codec;
u16 eid;
u32 reg;
@@ -2828,13 +2829,15 @@
reg = inl(card->iobase + GLOB_CNT);
outl(reg & 0xffcfffff, card->iobase + GLOB_CNT);
- for (num_ac97 = 0; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) {
+ for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++)
card->ac97_codec[num_ac97] = NULL;
- }
- for (num_ac97 = 0; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) {
+ /*@FIXME I don't know, if I'm playing to safe here... (jsaw) */
+ if ((nr_ac97_max > 2) && !card->use_mmio) nr_ac97_max = 2;
+
+ for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) {
/* codec reset */
- printk(KERN_INFO "i810_audio: resetting hw channel %d\n", num_ac97);
+ printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97);
if (card->use_mmio) readw(card->ac97base_mmio + 0x80*num_ac97);
else inw(card->ac97base + 0x80*num_ac97);
@@ -2846,7 +2849,7 @@
if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4)
&& (card->use_mmio)) {
ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
- printk(KERN_INFO "i810_audio: hw channel %d, codec id %d\n",
+ printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
num_ac97, ac97_id);
}
else {
@@ -2869,9 +2872,8 @@
/* initialize some basic codec information, other fields will be filled
in ac97_probe_codec */
codec->private_data = card;
-
- /*@FIXME this will lead to problems!!! id=2 <-> io offset=0*/
- codec->id = num_ac97;
+ codec->id = ac97_id;
+ card->ac97_id_map[ac97_id] = num_ac97 * 0x80;
if (card->use_mmio) {
codec->codec_read = i810_ac97_get_mmio;
@@ -2883,7 +2885,7 @@
}
if(!i810_ac97_probe_and_powerup(card,codec)) {
- printk(KERN_ERR "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", ac97_id);
kfree(codec);
break; /* it didn't work */
}
@@ -2903,7 +2905,7 @@
codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L);
if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID))
{
- printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", num_ac97);
+ printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", ac97_id);
kfree(codec);
continue;
}
@@ -3042,8 +3044,7 @@
}
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);
+ CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, -1);
save_flags(flags);
cli();
start_dac(state);
next prev parent reply other threads:[~2002-08-29 16:19 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-08-29 1:39 [PATCH 2.4.20-pre4-ac2] fix broken i810_audio DMA (?) Juergen Sawinski
2002-08-29 16:26 ` Juergen Sawinski [this message]
2002-08-29 16:43 ` Andris Pavenis
2002-08-29 16:50 ` Jim Radford
2002-08-29 16:59 ` Juergen Sawinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1030638379.2726.3.camel@voyager \
--to=juergen.sawinski@mpimf-heidelberg.mpg.de \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=dledford@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pavenis@latnet.lv \
--cc=radford@robotics.caltech.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.