summaryrefslogtreecommitdiffstats
path: root/sound/oss/maestro.c
diff options
context:
space:
mode:
authorAdrian Bunk <bunk@stusta.de>2006-10-04 02:17:22 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 07:55:32 -0700
commitd56b9b9c464a10ab1ee51a4c6190a2b57b8ef7a6 (patch)
treea48388734053900a8379042757ee241d1e9dfc7b /sound/oss/maestro.c
parent595182bcdf64fbfd7ae22c67ea6081b7d387d246 (diff)
[PATCH] The scheduled removal of some OSS drivers
This patch contains the scheduled removal of OSS drivers that: - have ALSA drivers for the same hardware without known regressions and - whose Kconfig options have been removed in 2.6.17. [michal.k.k.piotrowski@gmail.com: build fix] Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Michal Piotrowski <michal.k.k.piotrowski@gmail.com> Cc: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'sound/oss/maestro.c')
-rw-r--r--sound/oss/maestro.c3686
1 files changed, 0 insertions, 3686 deletions
diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c
deleted file mode 100644
index 1d98d100d739..000000000000
--- a/sound/oss/maestro.c
+++ /dev/null
@@ -1,3686 +0,0 @@
-/*****************************************************************************
- *
- * ESS Maestro/Maestro-2/Maestro-2E driver for Linux 2.[23].x
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (c) Copyright 1999 Alan Cox <alan.cox@linux.org>
- *
- * Based heavily on SonicVibes.c:
- * Copyright (C) 1998-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * Heavily modified by Zach Brown <zab@zabbo.net> based on lunch
- * with ESS engineers. Many thanks to Howard Kim for providing
- * contacts and hardware. Honorable mention goes to Eric
- * Brombaugh for all sorts of things. Best regards to the
- * proprietors of Hack Central for fine lodging.
- *
- * Supported devices:
- * /dev/dsp0-3 standard /dev/dsp device, (mostly) OSS compatible
- * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible
- *
- * 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.
- *
- * This driver has brute force APM suspend support. We catch suspend
- * notifications and stop all work being done on the chip. Any people
- * that try between this shutdown and the real suspend operation will
- * be put to sleep. When we resume we restore our software state on
- * the chip and wake up the people that were using it. The code thats
- * being used now is quite dirty and assumes we're on a uni-processor
- * machine. Much of it will need to be cleaned up for SMP ACPI or
- * similar.
- *
- * We also pay attention to PCI power management now. The driver
- * will power down units of the chip that it knows aren't needed.
- * The WaveProcessor and company are only powered on when people
- * have /dev/dsp*s open. On removal the driver will
- * power down the maestro entirely. There could still be
- * trouble with BIOSen that magically change power states
- * themselves, but we'll see.
- *
- * History
- * v0.15 - May 21 2001 - Marcus Meissner <mm@caldera.de>
- * Ported to Linux 2.4 PCI API. Some clean ups, global devs list
- * removed (now using pci device driver data).
- * PM needs to be polished still. Bumped version.
- * (still kind of v0.14) May 13 2001 - Ben Pfaff <pfaffben@msu.edu>
- * Add support for 978 docking and basic hardware volume control
- * (still kind of v0.14) Nov 23 - Alan Cox <alan@redhat.com>
- * Add clocking= for people with seriously warped hardware
- * (still v0.14) Nov 10 2000 - Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
- * add __init to maestro_ac97_init() and maestro_install()
- * (still based on v0.14) Mar 29 2000 - Zach Brown <zab@redhat.com>
- * move to 2.3 power management interface, which
- * required hacking some suspend/resume/check paths
- * make static compilation work
- * v0.14 - Jan 28 2000 - Zach Brown <zab@redhat.com>
- * add PCI power management through ACPI regs.
- * we now shut down on machine reboot/halt
- * leave scary PCI config items alone (isa stuff, mostly)
- * enable 1921s, it seems only mine was broke.
- * fix swapped left/right pcm dac. har har.
- * up bob freq, increase buffers, fix pointers at underflow
- * silly compilation problems
- * v0.13 - Nov 18 1999 - Zach Brown <zab@redhat.com>
- * fix nec Versas? man would that be cool.
- * v0.12 - Nov 12 1999 - Zach Brown <zab@redhat.com>
- * brown bag volume max fix..
- * v0.11 - Nov 11 1999 - Zach Brown <zab@redhat.com>
- * use proper stereo apu decoding, mmap/write should work.
- * make volume sliders more useful, tweak rate calculation.
- * fix lame 8bit format reporting bug. duh. apm apu saving buglet also
- * fix maestro 1 clock freq "bug", remove pt101 support
- * v0.10 - Oct 28 1999 - Zach Brown <zab@redhat.com>
- * aha, so, sometimes the WP writes a status word to offset 0
- * from one of the PCMBARs. rearrange allocation accordingly..
- * cheers again to Eric for being a good hacker in investigating this.
- * Jeroen Hoogervorst submits 7500 fix out of nowhere. yay. :)
- * v0.09 - Oct 23 1999 - Zach Brown <zab@redhat.com>
- * added APM support.
- * re-order something such that some 2Es now work. Magic!
- * new codec reset routine. made some codecs come to life.
- * fix clear_advance, sync some control with ESS.
- * now write to all base regs to be paranoid.
- * v0.08 - Oct 20 1999 - Zach Brown <zab@redhat.com>
- * Fix initial buflen bug. I am so smart. also smp compiling..
- * I owe Eric yet another beer: fixed recmask, igain,
- * muting, and adc sync consistency. Go Team.
- * v0.07 - Oct 4 1999 - Zach Brown <zab@redhat.com>
- * tweak adc/dac, formating, and stuff to allow full duplex
- * allocate dsps memory at open() so we can fit in the wavecache window
- * fix wavecache braindamage. again. no more scribbling?
- * fix ess 1921 codec bug on some laptops.
- * fix dumb pci scanning bug
- * started 2.3 cleanup, redid spinlocks, little cleanups
- * v0.06 - Sep 20 1999 - Zach Brown <zab@redhat.com>
- * fix wavecache thinkos. limit to 1 /dev/dsp.
- * eric is wearing his thinking toque this week.
- * spotted apu mode bugs and gain ramping problem
- * don't touch weird mixer regs, make recmask optional
- * fixed igain inversion, defaults for mixers, clean up rec_start
- * make mono recording work.
- * report subsystem stuff, please send reports.
- * littles: parallel out, amp now
- * v0.05 - Sep 17 1999 - Zach Brown <zab@redhat.com>
- * merged and fixed up Eric's initial recording code
- * munged format handling to catch misuse, needs rewrite.
- * revert ring bus init, fixup shared int, add pci busmaster setting
- * fix mixer oss interface, fix mic mute and recmask
- * mask off unsupported mixers, reset with all 1s, modularize defaults
- * make sure bob is running while we need it
- * got rid of device limit, initial minimal apm hooks
- * pull out dead code/includes, only allow multimedia/audio maestros
- * v0.04 - Sep 01 1999 - Zach Brown <zab@redhat.com>
- * copied memory leak fix from sonicvibes driver
- * different ac97 reset, play with 2.0 ac97, simplify ring bus setup
- * bob freq code, region sanity, jitter sync fix; all from Eric
- *
- * TODO
- * fix bob frequency
- * endianness
- * do smart things with ac97 2.0 bits.
- * dual codecs
- * leave 54->61 open
- *
- * it also would be fun to have a mode that would not use pci dma at all
- * but would copy into the wavecache on board memory and use that
- * on architectures that don't like the maestro's pci dma ickiness.
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/poll.h>
-#include <linux/reboot.h>
-#include <linux/bitops.h>
-#include <linux/wait.h>
-#include <linux/mutex.h>
-
-
-#include <asm/current.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/uaccess.h>
-
-#include "maestro.h"
-
-static struct pci_driver maestro_pci_driver;
-
-/* --------------------------------------------------------------------- */
-
-#define M_DEBUG 1
-
-#ifdef M_DEBUG
-static int debug;
-#define M_printk(args...) {if (debug) printk(args);}
-#else
-#define M_printk(x)
-#endif
-
-/* we try to setup 2^(dsps_order) /dev/dsp devices */
-static int dsps_order;
-/* whether or not we mess around with power management */
-static int use_pm=2; /* set to 1 for force */
-/* clocking for broken hardware - a few laptops seem to use a 50Khz clock
- ie insmod with clocking=50000 or so */
-
-static int clocking=48000;
-
-MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Alan Cox <alan@redhat.com>");
-MODULE_DESCRIPTION("ESS Maestro Driver");
-MODULE_LICENSE("GPL");
-
-#ifdef M_DEBUG
-module_param(debug, bool, 0644);
-#endif
-module_param(dsps_order, int, 0);
-module_param(use_pm, int, 0);
-module_param(clocking, int, 0);
-
-/* --------------------------------------------------------------------- */
-#define DRIVER_VERSION "0.15"
-
-#ifndef PCI_VENDOR_ESS
-#define PCI_VENDOR_ESS 0x125D
-#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 /* Maestro 2 */
-#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 /* Maestro 2E */
-
-#define PCI_VENDOR_ESS_OLD 0x1285 /* Platform Tech,
- the people the maestro
- was bought from */
-#define PCI_DEVICE_ID_ESS_ESS0100 0x0100 /* maestro 1 */
-#endif /* PCI_VENDOR_ESS */
-
-#define ESS_CHAN_HARD 0x100
-
-/* NEC Versas ? */
-#define NEC_VERSA_SUBID1 0x80581033
-#define NEC_VERSA_SUBID2 0x803c1033
-
-
-/* changed so that I could actually find all the
- references and fix them up. it's a little more readable now. */
-#define ESS_FMT_STEREO 0x01
-#define ESS_FMT_16BIT 0x02
-#define ESS_FMT_MASK 0x03
-#define ESS_DAC_SHIFT 0
-#define ESS_ADC_SHIFT 4
-
-#define ESS_STATE_MAGIC 0x125D1968
-#define ESS_CARD_MAGIC 0x19283746
-
-#define DAC_RUNNING 1
-#define ADC_RUNNING 2
-
-#define MAX_DSP_ORDER 2
-#define MAX_DSPS (1<<MAX_DSP_ORDER)
-#define NR_DSPS (1<<dsps_order)
-#define NR_IDRS 32
-
-#define NR_APUS 64
-#define NR_APU_REGS 16
-
-/* acpi states */
-enum {
- ACPI_D0=0,
- ACPI_D1,
- ACPI_D2,
- ACPI_D3
-};
-
-/* bits in the acpi masks */
-#define ACPI_12MHZ ( 1 << 15)
-#define ACPI_24MHZ ( 1 << 14)
-#define ACPI_978 ( 1 << 13)
-#define ACPI_SPDIF ( 1 << 12)
-#define ACPI_GLUE ( 1 << 11)
-#define ACPI__10 ( 1 << 10) /* reserved */
-#define ACPI_PCIINT ( 1 << 9)
-#define ACPI_HV ( 1 << 8) /* hardware volume */
-#define ACPI_GPIO ( 1 << 7)
-#define ACPI_ASSP ( 1 << 6)
-#define ACPI_SB ( 1 << 5) /* sb emul */
-#define ACPI_FM ( 1 << 4) /* fm emul */
-#define ACPI_RB ( 1 << 3) /* ringbus / aclink */
-#define ACPI_MIDI ( 1 << 2)
-#define ACPI_GP ( 1 << 1) /* game port */
-#define ACPI_WP ( 1 << 0) /* wave processor */
-
-#define ACPI_ALL (0xffff)
-#define ACPI_SLEEP (~(ACPI_SPDIF|ACPI_ASSP|ACPI_SB|ACPI_FM| \
- ACPI_MIDI|ACPI_GP|ACPI_WP))
-#define ACPI_NONE (ACPI__10)
-
-/* these masks indicate which units we care about at
- which states */
-static u16 acpi_state_mask[] = {
- [ACPI_D0] = ACPI_ALL,
- [ACPI_D1] = ACPI_SLEEP,
- [ACPI_D2] = ACPI_SLEEP,
- [ACPI_D3] = ACPI_NONE
-};
-
-static char version[] __devinitdata =
-KERN_INFO "maestro: version " DRIVER_VERSION " time " __TIME__ " " __DATE__ "\n";
-
-
-
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-
-enum card_types_t {
- TYPE_MAESTRO,
- TYPE_MAESTRO2,
- TYPE_MAESTRO2E
-};
-
-static const char *card_names[]={
- [TYPE_MAESTRO] = "ESS Maestro",
- [TYPE_MAESTRO2] = "ESS Maestro 2",
- [TYPE_MAESTRO2E] = "ESS Maestro 2E"
-};
-
-static int clock_freq[]={
- [TYPE_MAESTRO] = (49152000L / 1024L),
- [TYPE_MAESTRO2] = (50000000L / 1024L),
- [TYPE_MAESTRO2E] = (50000000L / 1024L)
-};
-
-static int maestro_notifier(struct notifier_block *nb, unsigned long event, void *buf);
-
-static struct notifier_block maestro_nb = {maestro_notifier, NULL, 0};
-
-/* --------------------------------------------------------------------- */
-
-struct ess_state {
- unsigned int magic;
- /* FIXME: we probably want submixers in here, but only one record pair */
- u8 apu[6]; /* l/r output, l/r intput converters, l/r input apus */
- u8 apu_mode[6]; /* Running mode for this APU */
- u8 apu_pan[6]; /* Panning setup for this APU */
- u32 apu_base[6]; /* base address for this apu */
- struct ess_card *card; /* Card info */
- /* wave stuff */
- unsigned int rateadc, ratedac;
- unsigned char fmt, enable;
-
- int index;
-
- /* this locks around the oss state in the driver */
- spinlock_t lock;
- /* only let 1 be opening at a time */
- struct mutex open_mutex;
- wait_queue_head_t open_wait;
- mode_t open_mode;
-
- /* soundcore stuff */
- int dev_audio;
-
- struct dmabuf {
- void *rawbuf;
- unsigned buforder;
- unsigned numfrag;
- unsigned fragshift;
- /* XXX zab - swptr only in here so that it can be referenced by
- clear_advance, as far as I can tell :( */
- unsigned hwptr, swptr;
- unsigned total_bytes;
- int count;
- unsigned error; /* over/underrun */
- wait_queue_head_t wait;
- /* redundant, but makes calculations easier */
- unsigned fragsize;
- unsigned dmasize;
- unsigned fragsamples;
- /* OSS stuff */
- unsigned mapped:1;
- unsigned ready:1; /* our oss buffers are ready to go */
- unsigned endcleared:1;
- unsigned ossfragshift;
- int ossmaxfrags;
- unsigned subdivision;
- u16 base; /* Offset for ptr */
- } dma_dac, dma_adc;
-
- /* pointer to each dsp?s piece of the apu->src buffer page */
- void *mixbuf;
-
-};
-
-struct ess_card {
- unsigned int magic;
-
- /* We keep maestro cards in a linked list */
- struct ess_card *next;
-
- int dev_mixer;
-
- int card_type;
-
- /* as most of this is static,
- perhaps it should be a pointer to a global struct */
- struct mixer_goo {
- int modcnt;
- int supported_mixers;
- int stereo_mixers;
- int record_sources;
- /* the caller must guarantee arg sanity before calling these */
-/* int (*read_mixer)(struct ess_card *card, int index);*/
- void (*write_mixer)(struct ess_card *card,int mixer, unsigned int left,unsigned int right);
- int (*recmask_io)(struct ess_card *card,int rw,int mask);
- unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
- } mix;
-
- int power_regs;
-
- int in_suspend;
- wait_queue_head_t suspend_queue;
-
- struct ess_state channels[MAX_DSPS];
- u16 maestro_map[NR_IDRS]; /* Register map */
- /* we have to store this junk so that we can come back from a
- suspend */
- u16 apu_map[NR_APUS][NR_APU_REGS]; /* contents of apu regs */
-
- /* this locks around the physical registers on the card */
- spinlock_t lock;
-
- /* memory for this card.. wavecache limited :(*/
- void *dmapages;
- int dmaorder;
-
- /* hardware resources */
- struct pci_dev *pcidev;
- u32 iobase;
- u32 irq;
-
- int bob_freq;
- char dsps_open;
-
- int dock_mute_vol;
-};
-
-static void set_mixer(struct ess_card *card,unsigned int mixer, unsigned int val );
-
-static unsigned
-ld2(unsigned int x)
-{
- unsigned r = 0;
-
- if (x >= 0x10000) {
- x >>= 16;
- r += 16;
- }
- if (x >= 0x100) {
- x >>= 8;
- r += 8;
- }
- if (x >= 0x10) {
- x >>= 4;
- r += 4;
- }
- if (x >= 4) {
- x >>= 2;
- r += 2;
- }
- if (x >= 2)
- r++;
- return r;
-}
-
-
-/* --------------------------------------------------------------------- */
-
-static void check_suspend(struct ess_card *card);
-
-/* --------------------------------------------------------------------- */
-
-
-/*
- * ESS Maestro AC97 codec programming interface.
- */
-
-static void maestro_ac97_set(struct ess_card *card, u8 cmd, u16 val)
-{
- int io = card->iobase;
- int i;
- /*
- * Wait for the codec bus to be free
- */
-
- check_suspend(card);
-
- for(i=0;i<10000;i++)
- {
- if(!(inb(io+ESS_AC97_INDEX)&1))
- break;
- }
- /*
- * Write the bus
- */
- outw(val, io+ESS_AC97_DATA);
- mdelay(1);
- outb(cmd, io+ESS_AC97_INDEX);
- mdelay(1);
-}
-
-static u16 maestro_ac97_get(struct ess_card *card, u8 cmd)
-{
- int io = card->iobase;
- int sanity=10000;
- u16 data;
- int i;
-
- check_suspend(card);
- /*
- * Wait for the codec bus to be free
- */
-
- for(i=0;i<10000;i++)
- {
- if(!(inb(io+ESS_AC97_INDEX)&1))
- break;
- }
-
- outb(cmd|0x80, io+ESS_AC97_INDEX);
- mdelay(1);
-
- while(inb(io+ESS_AC97_INDEX)&1)
- {
- sanity--;
- if(!sanity)
- {
- printk(KERN_ERR "maestro: ac97 codec timeout reading 0x%x.\n",cmd);
- return 0;
- }
- }
- data=inw(io+ESS_AC97_DATA);
- mdelay(1);
- return data;
-}
-
-/* OSS interface to the ac97s.. */
-
-#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|\
- SOUND_MASK_PCM|SOUND_MASK_LINE|SOUND_MASK_CD|\
- SOUND_MASK_VIDEO|SOUND_MASK_LINE1|SOUND_MASK_IGAIN)
-
-#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \
- SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_MIC|\
- SOUND_MASK_SPEAKER)
-
-#define AC97_RECORD_MASK (SOUND_MASK_MIC|\
- SOUND_MASK_CD| SOUND_MASK_VIDEO| SOUND_MASK_LINE1| SOUND_MASK_LINE|\
- SOUND_MASK_PHONEIN)
-
-#define supported_mixer(CARD,FOO) ( CARD->mix.supported_mixers & (1<<FOO) )
-
-/* this table has default mixer values for all OSS mixers.
- be sure to fill it in if you add oss mixers
- to anyone's supported mixer defines */
-
-static unsigned int mixer_defaults[SOUND_MIXER_NRDEVICES] = {
- [SOUND_MIXER_VOLUME] = 0x3232,
- [SOUND_MIXER_BASS] = 0x3232,
- [SOUND_MIXER_TREBLE] = 0x3232,
- [SOUND_MIXER_SPEAKER] = 0x3232,
- [SOUND_MIXER_MIC] = 0x8000, /* annoying */
- [SOUND_MIXER_LINE] = 0x3232,
- [SOUND_MIXER_CD] = 0x3232,
- [SOUND_MIXER_VIDEO] = 0x3232,
- [SOUND_MIXER_LINE1] = 0x3232,
- [SOUND_MIXER_PCM] = 0x3232,
- [SOUND_MIXER_IGAIN] = 0x3232
-};
-
-static struct ac97_mixer_hw {
- unsigned char offset;
- int scale;
-} ac97_hw[SOUND_MIXER_NRDEVICES]= {
- [SOUND_MIXER_VOLUME] = {0x02,63},
- [SOUND_MIXER_BASS] = {0x08,15},
- [SOUND_MIXER_TREBLE] = {0x08,15},
- [SOUND_MIXER_SPEAKER] = {0x0a,15},
- [SOUND_MIXER_MIC] = {0x0e,31},
- [SOUND_MIXER_LINE] = {0x10,31},
- [SOUND_MIXER_CD] = {0x12,31},
- [SOUND_MIXER_VIDEO] = {0x14,31},
- [SOUND_MIXER_LINE1] = {0x16,31},
- [SOUND_MIXER_PCM] = {0x18,31},
- [SOUND_MIXER_IGAIN] = {0x1c,15}
-};
-
-#if 0 /* *shrug* removed simply because we never used it.
- feel free to implement again if needed */
-
-/* reads the given OSS mixer from the ac97
- the caller must have insured that the ac97 knows
- about that given mixer, and should be holding a
- spinlock for the card */
-static int ac97_read_mixer(struct ess_card *card, int mixer)
-{
- u16 val;
- int ret=0;
- struct ac97_mixer_hw *mh = &ac97_hw[mixer];
-
- val = maestro_ac97_get(card, mh->offset);
-
- if(AC97_STEREO_MASK & (1<<mixer)) {
- /* nice stereo mixers .. */
- int left,right;
-
- left = (val >> 8) & 0x7f;
- right = val & 0x7f;
-
- if (mixer == SOUND_MIXER_IGAIN) {
- right = (right * 100) / mh->scale;
- left = (left * 100) / mh->scale;
- } else {
- right = 100 - ((right * 100) / mh->scale);
- left = 100 - ((left * 100) / mh->scale);
- }
-
- ret = left | (right << 8);
- } else if (mixer == SOUND_MIXER_SPEAKER) {
- ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);
- } else if (mixer == SOUND_MIXER_MIC) {
- ret = 100 - (((val & 0x1f) * 100) / mh->scale);
- /* the low bit is optional in the tone sliders and masking
- it lets is avoid the 0xf 'bypass'.. */
- } else if (mixer == SOUND_MIXER_BASS) {
- ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale);
- } else if (mixer == SOUND_MIXER_TREBLE) {
- ret = 100 - (((val & 0xe) * 100) / mh->scale);
- }
-
- M_printk("read mixer %d (0x%x) %x -> %x\n",mixer,mh->offset,val,ret);
-
- return ret;
-}
-#endif
-
-/* write the OSS encoded volume to the given OSS encoded mixer,
- again caller's job to make sure all is well in arg land,
- call with spinlock held */
-
-/* linear scale -> log */
-static unsigned char lin2log[101] =
-{
-0, 0 , 15 , 23 , 30 , 34 , 38 , 42 , 45 , 47 ,
-50 , 52 , 53 , 55 , 57 , 58 , 60 , 61 , 62 ,
-63 , 65 , 66 , 67 , 68 , 69 , 69 , 70 , 71 ,
-72 , 73 , 73 , 74 , 75 , 75 , 76 , 77 , 77 ,
-78 , 78 , 79 , 80 , 80 , 81 , 81 , 82 , 82 ,
-83 , 83 , 84 , 84 , 84 , 85 , 85 , 86 , 86 ,
-87 , 87 , 87 , 88 , 88 , 88 , 89 , 89 , 89 ,
-90 , 90 , 90 , 91 , 91 , 91 , 92 , 92 , 92 ,
-93 , 93 , 93 , 94 , 94 , 94 , 94 , 95 , 95 ,
-95 , 95 , 96 , 96 , 96 , 96 , 97 , 97 , 97 ,
-97 , 98 , 98 , 98 , 98 , 99 , 99 , 99 , 99 , 99
-};
-
-static void ac97_write_mixer(struct ess_card *card,int mixer, unsigned int left, unsigned int right)
-{
- u16 val=0;
- struct ac97_mixer_hw *mh = &ac97_hw[mixer];
-
- M_printk("wrote mixer %d (0x%x) %d,%d",mixer,mh->offset,left,right);
-
- if(AC97_STEREO_MASK & (1<<mixer)) {
- /* stereo mixers, mute them if we can */
-
- if (mixer == SOUND_MIXER_IGAIN) {
- /* igain's slider is reversed.. */
- right = (right * mh->scale) / 100;
- left = (left * mh->scale) / 100;
- if ((left == 0) && (right == 0))
- val |= 0x8000;
- } else if (mixer == SOUND_MIXER_PCM || mixer == SOUND_MIXER_CD) {
- /* log conversion seems bad for them */
- if ((left == 0) && (right == 0))
- val = 0x8000;
- right = ((100 - right) * mh->scale) / 100;
- left = ((100 - left) * mh->scale) / 100;
- } else {
- /* log conversion for the stereo controls */
- if((left == 0) && (right == 0))
- val = 0x8000;
- right = ((100 - lin2log[right]) * mh->scale) / 100;
- left = ((100 - lin2log[left]) * mh->scale) / 100;
- }
-
- val |= (left << 8) | right;
-
- } else if (mixer == SOUND_MIXER_SPEAKER) {
- val = (((100 - left) * mh->scale) / 100) << 1;
- } else if (mixer == SOUND_MIXER_MIC) {
- val = maestro_ac97_get(card, mh->offset) & ~0x801f;
- val |= (((100 - left) * mh->scale) / 100);
- /* the low bit is optional in the tone sliders and masking
- it lets is avoid the 0xf 'bypass'.. */
- } else if (mixer == SOUND_MIXER_BASS) {
- val = maestro_ac97_get(card , mh->offset) & ~0x0f00;
- val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
- } else if (mixer == SOUND_MIXER_TREBLE) {
- val = maestro_ac97_get(card , mh->offset) & ~0x000f;
- val |= (((100 - left) * mh->scale) / 100) & 0x000e;
- }
-
- maestro_ac97_set(card , mh->offset, val);
-
- M_printk(" -> %x\n",val);
-}
-
-/* the following tables allow us to go from
- OSS <-> ac97 quickly. */
-
-enum ac97_recsettings {
- AC97_REC_MIC=0,
- AC97_REC_CD,
- AC97_REC_VIDEO,
- AC97_REC_AUX,
- AC97_REC_LINE,
- AC97_REC_STEREO, /* combination of all enabled outputs.. */
- AC97_REC_MONO, /*.. or the mono equivalent */
- AC97_REC_PHONE
-};
-
-static unsigned int ac97_oss_mask[] = {
- [AC97_REC_MIC] = SOUND_MASK_MIC,
- [AC97_REC_CD] = SOUND_MASK_CD,
- [AC97_REC_VIDEO] = SOUND_MASK_VIDEO,
- [AC97_REC_AUX] = SOUND_MASK_LINE1,
- [AC97_REC_LINE] = SOUND_MASK_LINE,
- [AC97_REC_PHONE] = SOUND_MASK_PHONEIN
-};
-
-/* indexed by bit position */
-static unsigned int ac97_oss_rm[] = {
- [SOUND_MIXER_MIC] = AC97_REC_MIC,
- [SOUND_MIXER_CD] = AC97_REC_CD,
- [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
- [SOUND_MIXER_LINE1] = AC97_REC_AUX,
- [SOUND_MIXER_LINE] = AC97_REC_LINE,
- [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
-};
-
-/* read or write the recmask
- the ac97 can really have left and right recording
- inputs independently set, but OSS doesn't seem to
- want us to express that to the user.
- the caller guarantees that we have a supported bit set,
- and they must be holding the card's spinlock */
-static int
-ac97_recmask_io(struct ess_card *card, int read, int mask)
-{
- unsigned int val = ac97_oss_mask[ maestro_ac97_get(card, 0x1a) & 0x7 ];
-
- if (read) return val;
-
- /* oss can have many inputs, maestro can't. try
- to pick the 'new' one */
-
- if (mask != val) mask &= ~val;
-
- val = ffs(mask) - 1;
- val = ac97_oss_rm[val];
- val |= val << 8; /* set both channels */
-
- M_printk("maestro: setting ac97 recmask to 0x%x\n",val);
-
- maestro_ac97_set(card,0x1a,val);
-
- return 0;
-};
-
-/*
- * The Maestro can be wired to a standard AC97 compliant codec
- * (see www.intel.com for the pdf's on this), or to a PT101 codec
- * which appears to be the ES1918 (data sheet on the esstech.com.tw site)
- *
- * The PT101 setup is untested.
- */
-
-static u16 __init maestro_ac97_init(struct ess_card *card)
-{
- u16 vend1, vend2, caps;
-
- card->mix.supported_mixers = AC97_SUPPORTED_MASK;
- card->mix.stereo_mixers = AC97_STEREO_MASK;
- card->mix.record_sources = AC97_RECORD_MASK;
-/* card->mix.read_mixer = ac97_read_mixer;*/
- card->mix.write_mixer = ac97_write_mixer;
- card->mix.recmask_io = ac97_recmask_io;
-
- vend1 = maestro_ac97_get(card, 0x7c);
- vend2 = maestro_ac97_get(card, 0x7e);
-
- caps = maestro_ac97_get(card, 0x00);
-
- printk(KERN_INFO "maestro: AC97 Codec detected: v: 0x%2x%2x caps: 0x%x pwr: 0x%x\n",
- vend1,vend2,caps,maestro_ac97_get(card,0x26) & 0xf);
-
- if (! (caps & 0x4) ) {
- /* no bass/treble nobs */
- card->mix.supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE);
- }
-
- /* XXX endianness, dork head. */
- /* vendor specifc bits.. */
- switch ((long)(vend1 << 16) | vend2) {
- case 0x545200ff: /* TriTech */
- /* no idea what this does */
- maestro_ac97_set(card,0x2a,0x0001);
- maestro_ac97_set(card,0x2c,0x0000);
- maestro_ac97_set(card,0x2c,0xffff);
- break;
-#if 0 /* i thought the problems I was seeing were with
- the 1921, but apparently they were with the pci board
- it was on, so this code is commented out.
- lets see if this holds true. */
- case 0x83847609: /* ESS 1921 */
- /* writing to 0xe (mic) or 0x1a (recmask) seems
- to hang this codec */
- card->mix.supported_mixers &= ~(SOUND_MASK_MIC);
- card->mix.record_sources = 0;
- card->mix.recmask_io = NULL;
-#if 0 /* don't ask. I have yet to see what these actually do. */
- maestro_ac97_set(card,0x76,0xABBA); /* o/~ Take a chance on me o/~ */
- udelay(20);
- maestro_ac97_set(card,0x78,0x3002);
- udelay(20);
- maestro_ac97_set(card,0x78,0x3802);
- udelay(20);
-#endif
- break;
-#endif
- default: break;
- }
-
- maestro_ac97_set(card, 0x1E, 0x0404);
- /* null misc stuff */
- maestro_ac97_set(card, 0x20, 0x0000);
-
- return 0;
-}
-
-#if 0 /* there has been 1 person on the planet with a pt101 that we
- know of. If they care, they can put this back in :) */
-static u16 maestro_pt101_init(struct ess_card *card,int iobase)
-{
- printk(KERN_INFO "maestro: PT101 Codec detected, initializing but _not_ installing mixer device.\n");
- /* who knows.. */
- maestro_ac97_set(iobase, 0x2A, 0x0001);
- maestro_ac97_set(iobase, 0x2C, 0x0000);
- maestro_ac97_set(iobase, 0x2C, 0xFFFF);
- maestro_ac97_set(iobase, 0x10, 0x9F1F);
- maestro_ac97_set(iobase, 0x12, 0x0808);
- maestro_ac97_set(iobase, 0x14, 0x9F1F);
- maestro_ac97_set(iobase, 0x16, 0x9F1F);
- maestro_ac97_set(iobase, 0x18, 0x0404);
- maestro_ac97_set(iobase, 0x1A, 0x0000);
- maestro_ac97_set(iobase, 0x1C, 0x0000);
- maestro_ac97_set(iobase, 0x02, 0x0404);
- maestro_ac97_set(iobase, 0x04, 0x0808);
- maestro_ac97_set(iobase, 0x0C, 0x801F);
- maestro_ac97_set(iobase, 0x0E, 0x801F);
- return 0;
-}
-#endif
-
-/* this is very magic, and very slow.. */
-static void
-maestro_ac97_reset(int ioaddr, struct pci_dev *pcidev)
-{
- u16 save_68;
- u16 w;
- u32 vend;
-
- outw( inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38);
- outw( inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a);
- outw( inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c);
-
- /* reset the first codec */
- outw(0x0000, ioaddr+0x36);
- save_68 = inw(ioaddr+0x68);
- pci_read_config_word(pcidev, 0x58, &w); /* something magical with gpio and bus arb. */
- pci_read_config_dword(pcidev, PCI_SUBSYSTEM_VENDOR_ID, &vend);
- if( w & 0x1)
- save_68 |= 0x10;
- outw(0xfffe, ioaddr + 0x64); /* tickly gpio 0.. */
- outw(0x0001, ioaddr + 0x68);
- outw(0x0000, ioaddr + 0x60);
- udelay(20);
- outw(0x0001, ioaddr + 0x60);
- mdelay(20);
-
- outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */
- outw( (inw(ioaddr + 0x38) & 0xfffc)|0x1, ioaddr + 0x38);
- outw( (inw(ioaddr + 0x3a) & 0xfffc)|0x1, ioaddr + 0x3a);
- outw( (inw(ioaddr + 0x3c) & 0xfffc)|0x1, ioaddr + 0x3c);
-
- /* now the second codec */
- outw(0x0000, ioaddr+0x36);
- outw(0xfff7, ioaddr + 0x64);
- save_68 = inw(ioaddr+0x68);
- outw(0x0009, ioaddr + 0x68);
- outw(0x0001, ioaddr + 0x60);
- udelay(20);
- outw(0x0009, ioaddr + 0x60);
- mdelay(500); /* .. ouch.. */
- outw( inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38);
- outw( inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a);
- outw( inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c);
-
-#if 0 /* the loop here needs to be much better if we want it.. */
- M_printk("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;
-
- outb(0x80|0x7d, ioaddr + 0x30);
- if (((inw(ioaddr+ 0x30) & 1) == 0) && (inb(ioaddr + 0x32) !=0)) break;
- outb(0x80|0x7f, ioaddr + 0x30);
- if (((inw(ioaddr+ 0x30) & 1) == 0) && (inb(ioaddr + 0x32) !=0)) break;
- }
-
- if( w > 10000) {
- outb( inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */
- mdelay(500); /* oh my.. */
- outb( inb(ioaddr + 0x37) & ~0x08, ioaddr + 0x37);
- udelay(1);
- outw( 0x80, ioaddr+0x30);
- for(w = 0 ; w < 10000; w++) {
- if((inw(ioaddr + 0x30) & 1) ==0) break;
- }
- }
- }
-#endif
- if ( vend == NEC_VERSA_SUBID1 || vend == NEC_VERSA_SUBID2) {
- /* turn on external amp? */
- outw(0xf9ff, ioaddr + 0x64);
- outw(inw(ioaddr+0x68) | 0x600, ioaddr + 0x68);
- outw(0x0209, ioaddr + 0x60);
- }
-
- /* 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);
-}
-/*
- * Indirect register access. Not all registers are readable so we
- * need to keep register state ourselves
- */
-
-#define WRITEABLE_MAP 0xEFFFFF
-#define READABLE_MAP 0x64003F
-
-/*
- * The Maestro engineers were a little indirection happy. These indirected
- * registers themselves include indirect registers at another layer
- */
-
-static void __maestro_write(struct ess_card *card, u16 reg, u16 data)
-{
- long ioaddr = card->iobase;
-
- outw(reg, ioaddr+0x02);
- outw(data, ioaddr+0x00);
- if( reg >= NR_IDRS) printk("maestro: IDR %d out of bounds!\n",reg);
- else card->maestro_map[reg]=data;
-
-}
-
-static void maestro_write(struct ess_state *s, u16 reg, u16 data)
-{
- unsigned long flags;
-
- check_suspend(s->card);
- spin_lock_irqsave(&s->card->lock,flags);
-
- __maestro_write(s->card,reg,data);
-
- spin_unlock_irqrestore(&s->card->lock,flags);
-}
-
-static u16 __maestro_read(struct ess_card *card, u16 reg)
-{
- long ioaddr = c