// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for ESS Maestro 1/2/2E Sound Card (started 21.8.99) * Copyright (c) by Matze Braun <MatzeBraun@gmx.de>. * Takashi Iwai <tiwai@suse.de> * * Most of the driver code comes from Zach Brown(zab@redhat.com) * Alan Cox OSS Driver * Rewritted from card-es1938.c source. * * TODO: * Perhaps Synth * * Notes from Zach Brown about the driver code * * Hardware Description * * A working Maestro setup contains the Maestro chip wired to a * codec or 2. In the Maestro we have the APUs, the ASSP, and the * Wavecache. The APUs can be though of as virtual audio routing * channels. They can take data from a number of sources and perform * basic encodings of the data. The wavecache is a storehouse for * PCM data. Typically it deals with PCI and interracts with the * APUs. The ASSP is a wacky DSP like device that ESS is loth * to release docs on. Thankfully it isn't required on the Maestro * until you start doing insane things like FM emulation and surround * encoding. The codecs are almost always AC-97 compliant codecs, * but it appears that early Maestros may have had PT101 (an ESS * part?) wired to them. The only real difference in the Maestro * families is external goop like docking capability, memory for * the ASSP, and initialization differences. * * Driver Operation * * We only drive the APU/Wavecache as typical DACs and drive the * mixers in the codecs. There are 64 APUs. We assign 6 to each * /dev/dsp? device. 2 channels for output, and 4 channels for * input. * * Each APU can do a number of things, but we only really use * 3 basic functions. For playback we use them to convert PCM * data fetched over PCI by the wavecahche into analog data that * is handed to the codec. One APU for mono, and a pair for stereo. * When in stereo, the combination of smarts in the APU and Wavecache * decide which wavecache gets the left or right channel. * * For record we still use the old overly mono system. For each in * coming channel the data comes in from the codec, through a 'input' * APU, through another rate converter APU, and then into memory via * the wavecache and PCI. If its stereo, we mash it back into LRLR in * software. The pass between the 2 APUs is supposedly what requires us * to have a 512 byte buffer sitting around in wavecache/memory. * * The wavecache makes our life even more fun. First off, it can * only address the first 28 bits of PCI address space, making it * useless on quite a few architectures. Secondly, its insane. * It claims to fetch from 4 regions of PCI space, each 4 meg in length. * But that doesn't really work. You can only use 1 region. So all our * allocations have to be in 4meg of each other. Booo. Hiss. * So we have a module parameter, dsps_order, that is the order of * the number of dsps to provide. All their buffer space is allocated * on open time. The sonicvibes OSS routines we inherited really want * power of 2 buffers, so we have all those next to each other, then * 512 byte regions for the recording wavecaches. This ends up * wasting quite a bit of memory. The only fixes I can see would be * getting a kernel allocator that could work in zones, or figuring out * just how to coerce the WP into doing what we want. * * The indirection of the various registers means we have to spinlock * nearly all register accesses. We have the main register indirection * like the wave cache, maestro registers, etc. Then we have beasts * like the APU interface that is indirect registers gotten at through * the main maestro indirection. Ouch. We spinlock around the actual * ports on a per card basis. This means spinlock activity at each IO * operation, but the only IO operation clusters are in non critical * paths and it makes the code far easier to follow. Interrupts are * blocked while holding the locks because the int handler has to * get at some of them :(. The mixer interface doesn't, however. * We also have an OSS state lock that is thrown around in a few * places.
*/
/* Values for Ring Bus Control B */ #define RINGB_2CODEC_ID_MASK 0x0003 #define RINGB_DIS_VALIDATION 0x0008 #define RINGB_EN_SPDIF 0x0010 #define RINGB_EN_2CODEC 0x0020 #define RINGB_SING_BIT_DUAL 0x0040
staticvoid snd_es1968_bob_start(struct es1968 *chip)
{ int prescale; int divide;
/* compute ideal interrupt frequency for buffer size & play rate */ /* first, find best prescaler value to match freq */ for (prescale = 5; prescale < 12; prescale++) if (chip->bob_freq > (ESS_SYSCLK >> (prescale + 9))) break;
/* next, back off prescaler whilst getting divider into optimum range */
divide = 1; while ((prescale > 5) && (divide < 32)) {
prescale--;
divide <<= 1;
}
divide >>= 1;
/* now fine-tune the divider for best match */ for (; divide < 31; divide++) if (chip->bob_freq >
((ESS_SYSCLK >> (prescale + 9)) / (divide + 1))) break;
/* divide = 0 is illegal, but don't let prescale = 4! */ if (divide == 0) {
divide++; if (prescale > 5)
prescale--;
} elseif (divide > 1)
divide--;
if (es->fmt & ESS_FMT_STEREO) { /* set panning: left or right */ /* Check: different panning. On my Canyon 3D Chipset the Channels are swapped. I don't know, about the output to the SPDif Link. Perhaps you have to change this
and not the APU Regs 4-5. */
apu_set_register(chip, apu, 10,
0x8F00 | (channel ? 0 : 0x10));
es->apu_mode[channel] += 1; /* stereo */
} else
apu_set_register(chip, apu, 10, 0x8F08);
}
/* Load the frequency, turn on 6dB */
snd_es1968_apu_set_freq(chip, es->apu[0], freq);
snd_es1968_apu_set_freq(chip, es->apu[1], freq);
}
staticvoid init_capture_apu(struct es1968 *chip, struct esschan *es, int channel, unsignedint pa, unsignedint bsize, int mode, int route)
{ int i, apu = es->apu[channel];
es->apu_mode[channel] = mode;
/* set the wavecache control reg */
snd_es1968_program_wavecache(chip, es, channel, pa, 1);
/* Offset to PCMBAR */
pa -= chip->dma.addr;
pa >>= 1; /* words */
/* base offset of dma calcs when reading the pointer
on this left one */
es->base[channel] = pa & 0xFFFF;
pa |= 0x00400000; /* bit 22 -> System RAM */
/* Begin loading the APU */ for (i = 0; i < 16; i++)
apu_set_register(chip, apu, i, 0x0000);
/* need to enable subgroups.. and we should probably
have different groups for different /dev/dsps.. */
apu_set_register(chip, apu, 2, 0x8);
/* Load the buffer into the wave engine */
apu_set_register(chip, apu, 4, ((pa >> 16) & 0xFF) << 8);
apu_set_register(chip, apu, 5, pa & 0xFFFF);
apu_set_register(chip, apu, 6, (pa + bsize) & 0xFFFF);
apu_set_register(chip, apu, 7, bsize); /* clear effects/env.. */
apu_set_register(chip, apu, 8, 0x00F0); /* amplitude now? sure. why not. */
apu_set_register(chip, apu, 9, 0x0000); /* set filter tune, radius, polar pan */
apu_set_register(chip, apu, 10, 0x8F08); /* route input */
apu_set_register(chip, apu, 11, route); /* dma on, no envelopes, filter to all 1s) */
apu_set_register(chip, apu, 0, 0x400F);
}
/* APU assignments: 0 = mono/left SRC 1 = right SRC 2 = mono/left Input Mixer 3 = right Input Mixer
*/ /* data seems to flow from the codec, through an apu into the 'mixbuf' bit of page, then through the SRC apu
and out to the real 'buffer'. ok. sure. */
/* input mixer (left/mono) */ /* parallel in crap, see maestro reg 0xC [8-11] */
init_capture_apu(chip, es, 2,
es->mixbuf->buf.addr, ESM_MIXBUF_SIZE/4, /* in words */
ESM_APU_INPUTMIXER, 0x14); /* SRC (left/mono); get input from inputing apu */
init_capture_apu(chip, es, 0, es->memory->buf.addr, size,
ESM_APU_SRCONVERTOR, es->apu[2]); if (es->fmt & ESS_FMT_STEREO) { /* input mixer (right) */
init_capture_apu(chip, es, 3,
es->mixbuf->buf.addr + ESM_MIXBUF_SIZE/2,
ESM_MIXBUF_SIZE/4, /* in words */
ESM_APU_INPUTMIXER, 0x15); /* SRC (right) */
init_capture_apu(chip, es, 1,
es->memory->buf.addr + size*2, size,
ESM_APU_SRCONVERTOR, es->apu[3]);
}
freq = runtime->rate; /* Sample Rate conversion APUs don't like 0x10000 for their rate */ if (freq > 47999)
freq = 47999; if (freq < 4000)
freq = 4000;
freq = snd_es1968_compute_rate(chip, freq);
/* Load the frequency, turn on 6dB */
snd_es1968_apu_set_freq(chip, es->apu[0], freq);
snd_es1968_apu_set_freq(chip, es->apu[1], freq);
/* fix mixer rate at 48khz. and its _must_ be 0x10000. */
freq = 0x10000;
snd_es1968_apu_set_freq(chip, es->apu[2], freq);
snd_es1968_apu_set_freq(chip, es->apu[3], freq);
/* allocate a new memory chunk with the specified size */ staticstruct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size)
{ struct esm_memory *buf;
/* The hardware volume works by incrementing / decrementing 2 counters (without wrap around) in response to volume button presses and then generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
of a byte wide register. The meaning of bits 0 and 4 is unknown. */ staticvoid es1968_update_hw_volume(struct work_struct *work)
{ struct es1968 *chip = container_of(work, struct es1968, hwvol_work); int x, val;
/* Figure out which volume control button was pushed, based on differences from the default register
values. */
x = inb(chip->io_port + 0x1c) & 0xee; /* Reset the volume control registers. */
outb(0x88, chip->io_port + 0x1c);
outb(0x88, chip->io_port + 0x1d);
outb(0x88, chip->io_port + 0x1e);
outb(0x88, chip->io_port + 0x1f);
if (chip->in_suspend) return;
#ifndef CONFIG_SND_ES1968_INPUT if (! chip->master_switch || ! chip->master_volume) return;
val = snd_ac97_read(chip->ac97, AC97_MASTER); switch (x) { case 0x88: /* mute */
val ^= 0x8000; break; case 0xaa: /* volume up */ if ((val & 0x7f) > 0)
val--; if ((val & 0x7f00) > 0)
val -= 0x0100; break; case 0x66: /* volume down */ if ((val & 0x7f) < 0x1f)
val++; if ((val & 0x7f00) < 0x1f00)
val += 0x0100; break;
} if (snd_ac97_update(chip->ac97, AC97_MASTER, val))
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->master_volume->id); #else if (!chip->input_dev) return;
val = 0; switch (x) { case 0x88: /* The counters have not changed, yet we've received a HV interrupt. According to tests run by various people this
happens when pressing the mute button. */
val = KEY_MUTE; break; case 0xaa: /* counters increased by 1 -> volume up */
val = KEY_VOLUMEUP; break; case 0x66: /* counters decreased by 1 -> volume down */
val = KEY_VOLUMEDOWN; break;
}
#if 0 /* the loop here needs to be much better if we want it.. */
dev_info(chip->card->dev, "trying software reset\n"); /* try and do a software reset */
outb(0x80 | 0x7c, ioaddr + 0x30); for (w = 0;; w++) { if ((inw(ioaddr + 0x30) & 1) == 0) { if (inb(ioaddr + 0x32) != 0) break;
/* Turn on the 978 docking chip. First frob the "master output enable" bit,
then set most of the playback volume control registers to max. */
outb(inb(ioaddr+0xc0)|(1<<5), ioaddr+0xc0);
outb(0xff, ioaddr+0xc3);
outb(0xff, ioaddr+0xc4);
outb(0xff, ioaddr+0xc6);
outb(0xff, ioaddr+0xc8);
outb(0x3f, ioaddr+0xcf);
outb(0x3f, ioaddr+0xd0);
}
/* We used to muck around with pci config space that * we had no business messing with. We don't know enough * about the machine to know which DMA mode is appropriate, * etc. We were guessing wrong on some machines and making * them unhappy. We now trust in the BIOS to do things right, * which almost certainly means a new host of problems will * arise with broken BIOS implementations. screw 'em. * We're already intolerant of machines that don't assign * IRQs.
*/
/* Config Reg A */
pci_read_config_word(pci, ESM_CONFIG_A, &w);
w &= ~DMA_CLEAR; /* Clear DMA bits */
w &= ~(PIC_SNOOP1 | PIC_SNOOP2); /* Clear Pic Snoop Mode Bits */
w &= ~SAFEGUARD; /* Safeguard off */
w |= POST_WRITE; /* Posted write */
w |= PCI_TIMING; /* PCI timing on */ /* XXX huh? claims to be reserved.. */
w &= ~SWAP_LR; /* swap left/right seems to only have effect on SB
Emulation */
w &= ~SUBTR_DECODE; /* Subtractive decode off */
pci_write_config_word(pci, ESM_CONFIG_A, w);
/* Config Reg B */
pci_read_config_word(pci, ESM_CONFIG_B, &w);
w &= ~(1 << 15); /* Turn off internal clock multiplier */ /* XXX how do we know which to use? */
w &= ~(1 << 14); /* External clock */
w &= ~SPDIF_CONFB; /* disable S/PDIF output */
w |= HWV_CONFB; /* HWV on */
w |= DEBOUNCE; /* Debounce off: easier to push the HW buttons */
w &= ~GPIO_CONFB; /* GPIO 4:5 */
w |= CHI_CONFB; /* Disconnect from the CHI. Enabling this made a dell 7500 work. */
w &= ~IDMA_CONFB; /* IDMA off (undocumented) */
w &= ~MIDI_FIX; /* MIDI fix off (undoc) */
w &= ~(1 << 1); /* reserved, always write 0 */
w &= ~IRQ_TO_ISA; /* IRQ to ISA off (undoc) */
/* Set up 978 docking control chip. */
pci_read_config_word(pci, 0x58, &w);
w|=1<<2; /* Enable 978. */
w|=1<<3; /* Turn on 978 hardware volume control. */
w&=~(1<<11); /* Turn on 978 mixer volume control. */
pci_write_config_word(pci, 0x58, w);
/* Sound Reset */
snd_es1968_reset(chip);
/* * Ring Bus Setup
*/
/* setup usual 0x34 stuff.. 0x36 may be chip specific */
outw(0xC090, iobase + ESM_RING_BUS_DEST); /* direct sound, stereo */
udelay(20);
outw(0x3000, iobase + ESM_RING_BUS_CONTR_A); /* enable ringbus/serial */
udelay(20);
/* * Reset the CODEC
*/
snd_es1968_ac97_reset(chip);
/* Ring Bus Control B */
n = inl(iobase + ESM_RING_BUS_CONTR_B);
n &= ~RINGB_EN_SPDIF; /* SPDIF off */ //w |= RINGB_EN_2CODEC; /* enable 2nd codec */
outl(n, iobase + ESM_RING_BUS_CONTR_B);
/* Set hardware volume control registers to midpoints.
We can tell which button was pushed based on how they change. */
outb(0x88, iobase+0x1c);
outb(0x88, iobase+0x1d);
outb(0x88, iobase+0x1e);
outb(0x88, iobase+0x1f);
/* it appears some maestros (dell 7500) only work if these are set,
regardless of whether we use the assp or not. */
outb(0, iobase + ASSP_CONTROL_B);
outb(3, iobase + ASSP_CONTROL_A); /* M: Reserved bits... */
outb(0, iobase + ASSP_CONTROL_C); /* M: Disable ASSP, ASSP IRQ's and FM Port */
/* * set up wavecache
*/ for (i = 0; i < 16; i++) { /* Write 0 into the buffer area 0x1E0->1EF */
outw(0x01E0 + i, iobase + WC_INDEX);
outw(0x0000, iobase + WC_DATA);
/* The 1.10 test program seem to write 0 into the buffer area
* 0x1D0-0x1DF too.*/
outw(0x01D0 + i, iobase + WC_INDEX);
outw(0x0000, iobase + WC_DATA);
}
wave_set_register(chip, IDR7_WAVE_ROMRAM,
(wave_get_register(chip, IDR7_WAVE_ROMRAM) & 0xFF00));
wave_set_register(chip, IDR7_WAVE_ROMRAM,
wave_get_register(chip, IDR7_WAVE_ROMRAM) | 0x100);
wave_set_register(chip, IDR7_WAVE_ROMRAM,
wave_get_register(chip, IDR7_WAVE_ROMRAM) & ~0x200);
wave_set_register(chip, IDR7_WAVE_ROMRAM,
wave_get_register(chip, IDR7_WAVE_ROMRAM) | ~0x400);
maestro_write(chip, IDR2_CRAM_DATA, 0x0000); /* Now back to the DirectSound stuff */ /* audio serial configuration.. ? */
maestro_write(chip, 0x08, 0xB004);
maestro_write(chip, 0x09, 0x001B);
maestro_write(chip, 0x0A, 0x8000);
maestro_write(chip, 0x0B, 0x3F37);
maestro_write(chip, 0x0C, 0x0098);
/* parallel in, has something to do with recording :) */
maestro_write(chip, 0x0C,
(maestro_read(chip, 0x0C) & ~0xF000) | 0x8000); /* parallel out */
maestro_write(chip, 0x0C,
(maestro_read(chip, 0x0C) & ~0x0F00) | 0x0500);
maestro_write(chip, 0x0D, 0x7632);
/* Wave cache control on - test off, sg off,
enable, enable extra chans 1Mb */
w = inw(iobase + WC_CONTROL);
w &= ~0xFA00; /* Seems to be reserved? I don't know */
w |= 0xA000; /* reserved... I don't know */
w &= ~0x0200; /* Channels 56,57,58,59 as Extra Play,Rec Channel enable
Seems to crash the Computer if enabled... */
w |= 0x0100; /* Wave Cache Operation Enabled */
w |= 0x0080; /* Channels 60/61 as Placback/Record enabled */
w &= ~0x0060; /* Clear Wavtable Size */
w |= 0x0020; /* Wavetable Size : 1MB */ /* Bit 4 is reserved */
w &= ~0x000C; /* DMA Stuff? I don't understand what the datasheet means */ /* Bit 1 is reserved */
w &= ~0x0001; /* Test Mode off */
outw(w, iobase + WC_CONTROL);
/* Now clear the APU control ram */ for (i = 0; i < NR_APUS; i++) { for (w = 0; w < NR_APU_REGS; w++)
apu_set_register(chip, i, w, 0);
}
}
/* Enable IRQ's */ staticvoid snd_es1968_start_irq(struct es1968 *chip)
{ unsignedshort w;
w = ESM_HIRQ_DSIE | ESM_HIRQ_HW_VOLUME; if (chip->rmidi)
w |= ESM_HIRQ_MPU401;
outb(w, chip->io_port + 0x1A);
outw(w, chip->io_port + ESM_PORT_HOST_IRQ);
}
/* * PM support
*/
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.