xref: /openbmc/linux/sound/pci/es1968.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  Driver for ESS Maestro 1/2/2E Sound Card (started 21.8.99)
41da177e4SLinus Torvalds  *  Copyright (c) by Matze Braun <MatzeBraun@gmx.de>.
51da177e4SLinus Torvalds  *                   Takashi Iwai <tiwai@suse.de>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  Most of the driver code comes from Zach Brown(zab@redhat.com)
81da177e4SLinus Torvalds  *	Alan Cox OSS Driver
91da177e4SLinus Torvalds  *  Rewritted from card-es1938.c source.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  TODO:
121da177e4SLinus Torvalds  *   Perhaps Synth
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Notes from Zach Brown about the driver code
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  *  Hardware Description
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  *	A working Maestro setup contains the Maestro chip wired to a
191da177e4SLinus Torvalds  *	codec or 2.  In the Maestro we have the APUs, the ASSP, and the
201da177e4SLinus Torvalds  *	Wavecache.  The APUs can be though of as virtual audio routing
211da177e4SLinus Torvalds  *	channels.  They can take data from a number of sources and perform
221da177e4SLinus Torvalds  *	basic encodings of the data.  The wavecache is a storehouse for
231da177e4SLinus Torvalds  *	PCM data.  Typically it deals with PCI and interracts with the
241da177e4SLinus Torvalds  *	APUs.  The ASSP is a wacky DSP like device that ESS is loth
251da177e4SLinus Torvalds  *	to release docs on.  Thankfully it isn't required on the Maestro
261da177e4SLinus Torvalds  *	until you start doing insane things like FM emulation and surround
271da177e4SLinus Torvalds  *	encoding.  The codecs are almost always AC-97 compliant codecs,
281da177e4SLinus Torvalds  *	but it appears that early Maestros may have had PT101 (an ESS
291da177e4SLinus Torvalds  *	part?) wired to them.  The only real difference in the Maestro
301da177e4SLinus Torvalds  *	families is external goop like docking capability, memory for
311da177e4SLinus Torvalds  *	the ASSP, and initialization differences.
321da177e4SLinus Torvalds  *
331da177e4SLinus Torvalds  *  Driver Operation
341da177e4SLinus Torvalds  *
351da177e4SLinus Torvalds  *	We only drive the APU/Wavecache as typical DACs and drive the
361da177e4SLinus Torvalds  *	mixers in the codecs.  There are 64 APUs.  We assign 6 to each
371da177e4SLinus Torvalds  *	/dev/dsp? device.  2 channels for output, and 4 channels for
381da177e4SLinus Torvalds  *	input.
391da177e4SLinus Torvalds  *
401da177e4SLinus Torvalds  *	Each APU can do a number of things, but we only really use
411da177e4SLinus Torvalds  *	3 basic functions.  For playback we use them to convert PCM
421da177e4SLinus Torvalds  *	data fetched over PCI by the wavecahche into analog data that
431da177e4SLinus Torvalds  *	is handed to the codec.  One APU for mono, and a pair for stereo.
441da177e4SLinus Torvalds  *	When in stereo, the combination of smarts in the APU and Wavecache
451da177e4SLinus Torvalds  *	decide which wavecache gets the left or right channel.
461da177e4SLinus Torvalds  *
471da177e4SLinus Torvalds  *	For record we still use the old overly mono system.  For each in
481da177e4SLinus Torvalds  *	coming channel the data comes in from the codec, through a 'input'
491da177e4SLinus Torvalds  *	APU, through another rate converter APU, and then into memory via
501da177e4SLinus Torvalds  *	the wavecache and PCI.  If its stereo, we mash it back into LRLR in
511da177e4SLinus Torvalds  *	software.  The pass between the 2 APUs is supposedly what requires us
521da177e4SLinus Torvalds  *	to have a 512 byte buffer sitting around in wavecache/memory.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *	The wavecache makes our life even more fun.  First off, it can
551da177e4SLinus Torvalds  *	only address the first 28 bits of PCI address space, making it
561da177e4SLinus Torvalds  *	useless on quite a few architectures.  Secondly, its insane.
571da177e4SLinus Torvalds  *	It claims to fetch from 4 regions of PCI space, each 4 meg in length.
581da177e4SLinus Torvalds  *	But that doesn't really work.  You can only use 1 region.  So all our
591da177e4SLinus Torvalds  *	allocations have to be in 4meg of each other.  Booo.  Hiss.
601da177e4SLinus Torvalds  *	So we have a module parameter, dsps_order, that is the order of
611da177e4SLinus Torvalds  *	the number of dsps to provide.  All their buffer space is allocated
621da177e4SLinus Torvalds  *	on open time.  The sonicvibes OSS routines we inherited really want
631da177e4SLinus Torvalds  *	power of 2 buffers, so we have all those next to each other, then
641da177e4SLinus Torvalds  *	512 byte regions for the recording wavecaches.  This ends up
651da177e4SLinus Torvalds  *	wasting quite a bit of memory.  The only fixes I can see would be
661da177e4SLinus Torvalds  *	getting a kernel allocator that could work in zones, or figuring out
671da177e4SLinus Torvalds  *	just how to coerce the WP into doing what we want.
681da177e4SLinus Torvalds  *
691da177e4SLinus Torvalds  *	The indirection of the various registers means we have to spinlock
701da177e4SLinus Torvalds  *	nearly all register accesses.  We have the main register indirection
711da177e4SLinus Torvalds  *	like the wave cache, maestro registers, etc.  Then we have beasts
721da177e4SLinus Torvalds  *	like the APU interface that is indirect registers gotten at through
731da177e4SLinus Torvalds  *	the main maestro indirection.  Ouch.  We spinlock around the actual
741da177e4SLinus Torvalds  *	ports on a per card basis.  This means spinlock activity at each IO
751da177e4SLinus Torvalds  *	operation, but the only IO operation clusters are in non critical
761da177e4SLinus Torvalds  *	paths and it makes the code far easier to follow.  Interrupts are
771da177e4SLinus Torvalds  *	blocked while holding the locks because the int handler has to
781da177e4SLinus Torvalds  *	get at some of them :(.  The mixer interface doesn't, however.
791da177e4SLinus Torvalds  *	We also have an OSS state lock that is thrown around in a few
801da177e4SLinus Torvalds  *	places.
811da177e4SLinus Torvalds  */
821da177e4SLinus Torvalds 
836cbbfe1cSTakashi Iwai #include <linux/io.h>
841da177e4SLinus Torvalds #include <linux/delay.h>
851da177e4SLinus Torvalds #include <linux/interrupt.h>
861da177e4SLinus Torvalds #include <linux/init.h>
871da177e4SLinus Torvalds #include <linux/pci.h>
889d2f928dSTobias Klauser #include <linux/dma-mapping.h>
891da177e4SLinus Torvalds #include <linux/slab.h>
901da177e4SLinus Torvalds #include <linux/gameport.h>
9165a77217SPaul Gortmaker #include <linux/module.h>
9262932df8SIngo Molnar #include <linux/mutex.h>
935a5e02e5SHans de Goede #include <linux/input.h>
9462932df8SIngo Molnar 
951da177e4SLinus Torvalds #include <sound/core.h>
961da177e4SLinus Torvalds #include <sound/pcm.h>
971da177e4SLinus Torvalds #include <sound/mpu401.h>
981da177e4SLinus Torvalds #include <sound/ac97_codec.h>
991da177e4SLinus Torvalds #include <sound/initval.h>
1001da177e4SLinus Torvalds 
1011872f589SOndrej Zary #ifdef CONFIG_SND_ES1968_RADIO
102d647f0b7SMauro Carvalho Chehab #include <media/drv-intf/tea575x.h>
1031872f589SOndrej Zary #endif
1041872f589SOndrej Zary 
1051da177e4SLinus Torvalds #define CARD_NAME "ESS Maestro1/2"
1061da177e4SLinus Torvalds #define DRIVER_NAME "ES1968"
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds MODULE_DESCRIPTION("ESS Maestro");
1091da177e4SLinus Torvalds MODULE_LICENSE("GPL");
1101da177e4SLinus Torvalds 
111b2fac073SFabian Frederick #if IS_REACHABLE(CONFIG_GAMEPORT)
1121da177e4SLinus Torvalds #define SUPPORT_JOYSTICK 1
1131da177e4SLinus Torvalds #endif
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 1-MAX */
1161da177e4SLinus Torvalds static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
117a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
1181da177e4SLinus Torvalds static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 };
1191da177e4SLinus Torvalds static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 };
1201da177e4SLinus Torvalds static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 };
1216581f4e7STakashi Iwai static int clock[SNDRV_CARDS];
1221da177e4SLinus Torvalds static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
1231da177e4SLinus Torvalds static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
1241da177e4SLinus Torvalds #ifdef SUPPORT_JOYSTICK
125a67ff6a5SRusty Russell static bool joystick[SNDRV_CARDS];
1261da177e4SLinus Torvalds #endif
127d4ecc83bSHans Verkuil static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds module_param_array(index, int, NULL, 0444);
1301da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
1311da177e4SLinus Torvalds module_param_array(id, charp, NULL, 0444);
1321da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
1331da177e4SLinus Torvalds module_param_array(enable, bool, NULL, 0444);
1341da177e4SLinus Torvalds MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
1351da177e4SLinus Torvalds module_param_array(total_bufsize, int, NULL, 0444);
1361da177e4SLinus Torvalds MODULE_PARM_DESC(total_bufsize, "Total buffer size in kB.");
1371da177e4SLinus Torvalds module_param_array(pcm_substreams_p, int, NULL, 0444);
1381da177e4SLinus Torvalds MODULE_PARM_DESC(pcm_substreams_p, "PCM Playback substreams for " CARD_NAME " soundcard.");
1391da177e4SLinus Torvalds module_param_array(pcm_substreams_c, int, NULL, 0444);
1401da177e4SLinus Torvalds MODULE_PARM_DESC(pcm_substreams_c, "PCM Capture substreams for " CARD_NAME " soundcard.");
1411da177e4SLinus Torvalds module_param_array(clock, int, NULL, 0444);
1421da177e4SLinus Torvalds MODULE_PARM_DESC(clock, "Clock on " CARD_NAME " soundcard.  (0 = auto-detect)");
1431da177e4SLinus Torvalds module_param_array(use_pm, int, NULL, 0444);
1441da177e4SLinus Torvalds MODULE_PARM_DESC(use_pm, "Toggle power-management.  (0 = off, 1 = on, 2 = auto)");
1451da177e4SLinus Torvalds module_param_array(enable_mpu, int, NULL, 0444);
1461da177e4SLinus Torvalds MODULE_PARM_DESC(enable_mpu, "Enable MPU401.  (0 = off, 1 = on, 2 = auto)");
1471da177e4SLinus Torvalds #ifdef SUPPORT_JOYSTICK
1481da177e4SLinus Torvalds module_param_array(joystick, bool, NULL, 0444);
1491da177e4SLinus Torvalds MODULE_PARM_DESC(joystick, "Enable joystick.");
1501da177e4SLinus Torvalds #endif
151d4ecc83bSHans Verkuil module_param_array(radio_nr, int, NULL, 0444);
152d4ecc83bSHans Verkuil MODULE_PARM_DESC(radio_nr, "Radio device numbers");
153d4ecc83bSHans Verkuil 
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds #define NR_APUS			64
1571da177e4SLinus Torvalds #define NR_APU_REGS		16
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds /* NEC Versas ? */
1601da177e4SLinus Torvalds #define NEC_VERSA_SUBID1	0x80581033
1611da177e4SLinus Torvalds #define NEC_VERSA_SUBID2	0x803c1033
1621da177e4SLinus Torvalds 
1631da177e4SLinus Torvalds /* Mode Flags */
1641da177e4SLinus Torvalds #define ESS_FMT_STEREO     	0x01
1651da177e4SLinus Torvalds #define ESS_FMT_16BIT      	0x02
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds #define DAC_RUNNING		1
1681da177e4SLinus Torvalds #define ADC_RUNNING		2
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds /* Values for the ESM_LEGACY_AUDIO_CONTROL */
1711da177e4SLinus Torvalds 
172607da7f8SRene Herman #define ESS_DISABLE_AUDIO	0x8000
1731da177e4SLinus Torvalds #define ESS_ENABLE_SERIAL_IRQ	0x4000
1741da177e4SLinus Torvalds #define IO_ADRESS_ALIAS		0x0020
1751da177e4SLinus Torvalds #define MPU401_IRQ_ENABLE	0x0010
1761da177e4SLinus Torvalds #define MPU401_IO_ENABLE	0x0008
1771da177e4SLinus Torvalds #define GAME_IO_ENABLE		0x0004
1781da177e4SLinus Torvalds #define FM_IO_ENABLE		0x0002
1791da177e4SLinus Torvalds #define SB_IO_ENABLE		0x0001
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds /* Values for the ESM_CONFIG_A */
1821da177e4SLinus Torvalds 
1831da177e4SLinus Torvalds #define PIC_SNOOP1		0x4000
1841da177e4SLinus Torvalds #define PIC_SNOOP2		0x2000
1851da177e4SLinus Torvalds #define SAFEGUARD		0x0800
1861da177e4SLinus Torvalds #define DMA_CLEAR		0x0700
1871da177e4SLinus Torvalds #define DMA_DDMA		0x0000
1881da177e4SLinus Torvalds #define DMA_TDMA		0x0100
1891da177e4SLinus Torvalds #define DMA_PCPCI		0x0200
1901da177e4SLinus Torvalds #define POST_WRITE		0x0080
191607da7f8SRene Herman #define PCI_TIMING		0x0040
1921da177e4SLinus Torvalds #define SWAP_LR			0x0020
1931da177e4SLinus Torvalds #define SUBTR_DECODE		0x0002
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds /* Values for the ESM_CONFIG_B */
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds #define SPDIF_CONFB		0x0100
1981da177e4SLinus Torvalds #define HWV_CONFB		0x0080
1991da177e4SLinus Torvalds #define DEBOUNCE		0x0040
2001da177e4SLinus Torvalds #define GPIO_CONFB		0x0020
2011da177e4SLinus Torvalds #define CHI_CONFB		0x0010
2021da177e4SLinus Torvalds #define IDMA_CONFB		0x0008	/*undoc */
2031da177e4SLinus Torvalds #define MIDI_FIX		0x0004	/*undoc */
2041da177e4SLinus Torvalds #define IRQ_TO_ISA		0x0001	/*undoc */
2051da177e4SLinus Torvalds 
2061da177e4SLinus Torvalds /* Values for Ring Bus Control B */
2071da177e4SLinus Torvalds #define	RINGB_2CODEC_ID_MASK	0x0003
2081da177e4SLinus Torvalds #define RINGB_DIS_VALIDATION	0x0008
2091da177e4SLinus Torvalds #define RINGB_EN_SPDIF		0x0010
2101da177e4SLinus Torvalds #define	RINGB_EN_2CODEC		0x0020
2111da177e4SLinus Torvalds #define RINGB_SING_BIT_DUAL	0x0040
2121da177e4SLinus Torvalds 
213b595076aSUwe Kleine-König /* ****Port Addresses**** */
2141da177e4SLinus Torvalds 
2151da177e4SLinus Torvalds /*   Write & Read */
2161da177e4SLinus Torvalds #define ESM_INDEX		0x02
2171da177e4SLinus Torvalds #define ESM_DATA		0x00
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds /*   AC97 + RingBus */
2201da177e4SLinus Torvalds #define ESM_AC97_INDEX		0x30
2211da177e4SLinus Torvalds #define	ESM_AC97_DATA		0x32
2221da177e4SLinus Torvalds #define ESM_RING_BUS_DEST	0x34
2231da177e4SLinus Torvalds #define ESM_RING_BUS_CONTR_A	0x36
2241da177e4SLinus Torvalds #define ESM_RING_BUS_CONTR_B	0x38
2251da177e4SLinus Torvalds #define ESM_RING_BUS_SDO	0x3A
2261da177e4SLinus Torvalds 
2271da177e4SLinus Torvalds /*   WaveCache*/
2281da177e4SLinus Torvalds #define WC_INDEX		0x10
2291da177e4SLinus Torvalds #define WC_DATA			0x12
2301da177e4SLinus Torvalds #define WC_CONTROL		0x14
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds /*   ASSP*/
2331da177e4SLinus Torvalds #define ASSP_INDEX		0x80
2341da177e4SLinus Torvalds #define ASSP_MEMORY		0x82
2351da177e4SLinus Torvalds #define ASSP_DATA		0x84
2361da177e4SLinus Torvalds #define ASSP_CONTROL_A		0xA2
2371da177e4SLinus Torvalds #define ASSP_CONTROL_B		0xA4
2381da177e4SLinus Torvalds #define ASSP_CONTROL_C		0xA6
2391da177e4SLinus Torvalds #define ASSP_HOSTW_INDEX	0xA8
2401da177e4SLinus Torvalds #define ASSP_HOSTW_DATA		0xAA
2411da177e4SLinus Torvalds #define ASSP_HOSTW_IRQ		0xAC
2421da177e4SLinus Torvalds /* Midi */
2431da177e4SLinus Torvalds #define ESM_MPU401_PORT		0x98
2441da177e4SLinus Torvalds /* Others */
2451da177e4SLinus Torvalds #define ESM_PORT_HOST_IRQ	0x18
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds #define IDR0_DATA_PORT		0x00
2481da177e4SLinus Torvalds #define IDR1_CRAM_POINTER	0x01
2491da177e4SLinus Torvalds #define IDR2_CRAM_DATA		0x02
2501da177e4SLinus Torvalds #define IDR3_WAVE_DATA		0x03
2511da177e4SLinus Torvalds #define IDR4_WAVE_PTR_LOW	0x04
2521da177e4SLinus Torvalds #define IDR5_WAVE_PTR_HI	0x05
2531da177e4SLinus Torvalds #define IDR6_TIMER_CTRL		0x06
2541da177e4SLinus Torvalds #define IDR7_WAVE_ROMRAM	0x07
2551da177e4SLinus Torvalds 
2561da177e4SLinus Torvalds #define WRITEABLE_MAP		0xEFFFFF
2571da177e4SLinus Torvalds #define READABLE_MAP		0x64003F
2581da177e4SLinus Torvalds 
2591da177e4SLinus Torvalds /* PCI Register */
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds #define ESM_LEGACY_AUDIO_CONTROL 0x40
2621da177e4SLinus Torvalds #define ESM_ACPI_COMMAND	0x54
2631da177e4SLinus Torvalds #define ESM_CONFIG_A		0x50
2641da177e4SLinus Torvalds #define ESM_CONFIG_B		0x52
2651da177e4SLinus Torvalds #define ESM_DDMA		0x60
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds /* Bob Bits */
2681da177e4SLinus Torvalds #define ESM_BOB_ENABLE		0x0001
2691da177e4SLinus Torvalds #define ESM_BOB_START		0x0001
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds /* Host IRQ Control Bits */
2721da177e4SLinus Torvalds #define ESM_RESET_MAESTRO	0x8000
2731da177e4SLinus Torvalds #define ESM_RESET_DIRECTSOUND   0x4000
2741da177e4SLinus Torvalds #define ESM_HIRQ_ClkRun		0x0100
2751da177e4SLinus Torvalds #define ESM_HIRQ_HW_VOLUME	0x0040
2761da177e4SLinus Torvalds #define ESM_HIRQ_HARPO		0x0030	/* What's that? */
2771da177e4SLinus Torvalds #define ESM_HIRQ_ASSP		0x0010
2781da177e4SLinus Torvalds #define	ESM_HIRQ_DSIE		0x0004
2791da177e4SLinus Torvalds #define ESM_HIRQ_MPU401		0x0002
2801da177e4SLinus Torvalds #define ESM_HIRQ_SB		0x0001
2811da177e4SLinus Torvalds 
2821da177e4SLinus Torvalds /* Host IRQ Status Bits */
2831da177e4SLinus Torvalds #define ESM_MPU401_IRQ		0x02
2841da177e4SLinus Torvalds #define ESM_SB_IRQ		0x01
2851da177e4SLinus Torvalds #define ESM_SOUND_IRQ		0x04
2861da177e4SLinus Torvalds #define	ESM_ASSP_IRQ		0x10
2871da177e4SLinus Torvalds #define ESM_HWVOL_IRQ		0x40
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds #define ESS_SYSCLK		50000000
2901da177e4SLinus Torvalds #define ESM_BOB_FREQ 		200
2911da177e4SLinus Torvalds #define ESM_BOB_FREQ_MAX	800
2921da177e4SLinus Torvalds 
2931da177e4SLinus Torvalds #define ESM_FREQ_ESM1  		(49152000L / 1024L)	/* default rate 48000 */
2941da177e4SLinus Torvalds #define ESM_FREQ_ESM2  		(50000000L / 1024L)
2951da177e4SLinus Torvalds 
2961da177e4SLinus Torvalds /* APU Modes: reg 0x00, bit 4-7 */
2971da177e4SLinus Torvalds #define ESM_APU_MODE_SHIFT	4
2981da177e4SLinus Torvalds #define ESM_APU_MODE_MASK	(0xf << 4)
2991da177e4SLinus Torvalds #define	ESM_APU_OFF		0x00
3001da177e4SLinus Torvalds #define	ESM_APU_16BITLINEAR	0x01	/* 16-Bit Linear Sample Player */
3011da177e4SLinus Torvalds #define	ESM_APU_16BITSTEREO	0x02	/* 16-Bit Stereo Sample Player */
3021da177e4SLinus Torvalds #define	ESM_APU_8BITLINEAR	0x03	/* 8-Bit Linear Sample Player */
3031da177e4SLinus Torvalds #define	ESM_APU_8BITSTEREO	0x04	/* 8-Bit Stereo Sample Player */
3041da177e4SLinus Torvalds #define	ESM_APU_8BITDIFF	0x05	/* 8-Bit Differential Sample Playrer */
3051da177e4SLinus Torvalds #define	ESM_APU_DIGITALDELAY	0x06	/* Digital Delay Line */
3061da177e4SLinus Torvalds #define	ESM_APU_DUALTAP		0x07	/* Dual Tap Reader */
3071da177e4SLinus Torvalds #define	ESM_APU_CORRELATOR	0x08	/* Correlator */
3081da177e4SLinus Torvalds #define	ESM_APU_INPUTMIXER	0x09	/* Input Mixer */
3091da177e4SLinus Torvalds #define	ESM_APU_WAVETABLE	0x0A	/* Wave Table Mode */
3101da177e4SLinus Torvalds #define	ESM_APU_SRCONVERTOR	0x0B	/* Sample Rate Convertor */
3111da177e4SLinus Torvalds #define	ESM_APU_16BITPINGPONG	0x0C	/* 16-Bit Ping-Pong Sample Player */
3121da177e4SLinus Torvalds #define	ESM_APU_RESERVED1	0x0D	/* Reserved 1 */
3131da177e4SLinus Torvalds #define	ESM_APU_RESERVED2	0x0E	/* Reserved 2 */
3141da177e4SLinus Torvalds #define	ESM_APU_RESERVED3	0x0F	/* Reserved 3 */
3151da177e4SLinus Torvalds 
3161da177e4SLinus Torvalds /* reg 0x00 */
3171da177e4SLinus Torvalds #define ESM_APU_FILTER_Q_SHIFT		0
3181da177e4SLinus Torvalds #define ESM_APU_FILTER_Q_MASK		(3 << 0)
3191da177e4SLinus Torvalds /* APU Filtey Q Control */
3201da177e4SLinus Torvalds #define ESM_APU_FILTER_LESSQ	0x00
3211da177e4SLinus Torvalds #define ESM_APU_FILTER_MOREQ	0x03
3221da177e4SLinus Torvalds 
3231da177e4SLinus Torvalds #define ESM_APU_FILTER_TYPE_SHIFT	2
3241da177e4SLinus Torvalds #define ESM_APU_FILTER_TYPE_MASK	(3 << 2)
3251da177e4SLinus Torvalds #define ESM_APU_ENV_TYPE_SHIFT		8
3261da177e4SLinus Torvalds #define ESM_APU_ENV_TYPE_MASK		(3 << 8)
3271da177e4SLinus Torvalds #define ESM_APU_ENV_STATE_SHIFT		10
3281da177e4SLinus Torvalds #define ESM_APU_ENV_STATE_MASK		(3 << 10)
3291da177e4SLinus Torvalds #define ESM_APU_END_CURVE		(1 << 12)
3301da177e4SLinus Torvalds #define ESM_APU_INT_ON_LOOP		(1 << 13)
3311da177e4SLinus Torvalds #define ESM_APU_DMA_ENABLE		(1 << 14)
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds /* reg 0x02 */
3341da177e4SLinus Torvalds #define ESM_APU_SUBMIX_GROUP_SHIRT	0
3351da177e4SLinus Torvalds #define ESM_APU_SUBMIX_GROUP_MASK	(7 << 0)
3361da177e4SLinus Torvalds #define ESM_APU_SUBMIX_MODE		(1 << 3)
3371da177e4SLinus Torvalds #define ESM_APU_6dB			(1 << 4)
3381da177e4SLinus Torvalds #define ESM_APU_DUAL_EFFECT		(1 << 5)
3391da177e4SLinus Torvalds #define ESM_APU_EFFECT_CHANNELS_SHIFT	6
3401da177e4SLinus Torvalds #define ESM_APU_EFFECT_CHANNELS_MASK	(3 << 6)
3411da177e4SLinus Torvalds 
3421da177e4SLinus Torvalds /* reg 0x03 */
3431da177e4SLinus Torvalds #define ESM_APU_STEP_SIZE_MASK		0x0fff
3441da177e4SLinus Torvalds 
3451da177e4SLinus Torvalds /* reg 0x04 */
3461da177e4SLinus Torvalds #define ESM_APU_PHASE_SHIFT		0
3471da177e4SLinus Torvalds #define ESM_APU_PHASE_MASK		(0xff << 0)
3481da177e4SLinus Torvalds #define ESM_APU_WAVE64K_PAGE_SHIFT	8	/* most 8bit of wave start offset */
3491da177e4SLinus Torvalds #define ESM_APU_WAVE64K_PAGE_MASK	(0xff << 8)
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds /* reg 0x05 - wave start offset */
3521da177e4SLinus Torvalds /* reg 0x06 - wave end offset */
3531da177e4SLinus Torvalds /* reg 0x07 - wave loop length */
3541da177e4SLinus Torvalds 
3551da177e4SLinus Torvalds /* reg 0x08 */
3561da177e4SLinus Torvalds #define ESM_APU_EFFECT_GAIN_SHIFT	0
3571da177e4SLinus Torvalds #define ESM_APU_EFFECT_GAIN_MASK	(0xff << 0)
3581da177e4SLinus Torvalds #define ESM_APU_TREMOLO_DEPTH_SHIFT	8
3591da177e4SLinus Torvalds #define ESM_APU_TREMOLO_DEPTH_MASK	(0xf << 8)
3601da177e4SLinus Torvalds #define ESM_APU_TREMOLO_RATE_SHIFT	12
3611da177e4SLinus Torvalds #define ESM_APU_TREMOLO_RATE_MASK	(0xf << 12)
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds /* reg 0x09 */
3641da177e4SLinus Torvalds /* bit 0-7 amplitude dest? */
3651da177e4SLinus Torvalds #define ESM_APU_AMPLITUDE_NOW_SHIFT	8
3661da177e4SLinus Torvalds #define ESM_APU_AMPLITUDE_NOW_MASK	(0xff << 8)
3671da177e4SLinus Torvalds 
3681da177e4SLinus Torvalds /* reg 0x0a */
3691da177e4SLinus Torvalds #define ESM_APU_POLAR_PAN_SHIFT		0
3701da177e4SLinus Torvalds #define ESM_APU_POLAR_PAN_MASK		(0x3f << 0)
3711da177e4SLinus Torvalds /* Polar Pan Control */
3721da177e4SLinus Torvalds #define	ESM_APU_PAN_CENTER_CIRCLE		0x00
3731da177e4SLinus Torvalds #define	ESM_APU_PAN_MIDDLE_RADIUS		0x01
3741da177e4SLinus Torvalds #define	ESM_APU_PAN_OUTSIDE_RADIUS		0x02
3751da177e4SLinus Torvalds 
3761da177e4SLinus Torvalds #define ESM_APU_FILTER_TUNING_SHIFT	8
3771da177e4SLinus Torvalds #define ESM_APU_FILTER_TUNING_MASK	(0xff << 8)
3781da177e4SLinus Torvalds 
3791da177e4SLinus Torvalds /* reg 0x0b */
3801da177e4SLinus Torvalds #define ESM_APU_DATA_SRC_A_SHIFT	0
3811da177e4SLinus Torvalds #define ESM_APU_DATA_SRC_A_MASK		(0x7f << 0)
3821da177e4SLinus Torvalds #define ESM_APU_INV_POL_A		(1 << 7)
3831da177e4SLinus Torvalds #define ESM_APU_DATA_SRC_B_SHIFT	8
3841da177e4SLinus Torvalds #define ESM_APU_DATA_SRC_B_MASK		(0x7f << 8)
3851da177e4SLinus Torvalds #define ESM_APU_INV_POL_B		(1 << 15)
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds #define ESM_APU_VIBRATO_RATE_SHIFT	0
3881da177e4SLinus Torvalds #define ESM_APU_VIBRATO_RATE_MASK	(0xf << 0)
3891da177e4SLinus Torvalds #define ESM_APU_VIBRATO_DEPTH_SHIFT	4
3901da177e4SLinus Torvalds #define ESM_APU_VIBRATO_DEPTH_MASK	(0xf << 4)
3911da177e4SLinus Torvalds #define ESM_APU_VIBRATO_PHASE_SHIFT	8
3921da177e4SLinus Torvalds #define ESM_APU_VIBRATO_PHASE_MASK	(0xff << 8)
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds /* reg 0x0c */
3951da177e4SLinus Torvalds #define ESM_APU_RADIUS_SELECT		(1 << 6)
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds /* APU Filter Control */
3981da177e4SLinus Torvalds #define	ESM_APU_FILTER_2POLE_LOPASS	0x00
3991da177e4SLinus Torvalds #define	ESM_APU_FILTER_2POLE_BANDPASS	0x01
4001da177e4SLinus Torvalds #define	ESM_APU_FILTER_2POLE_HIPASS	0x02
4011da177e4SLinus Torvalds #define	ESM_APU_FILTER_1POLE_LOPASS	0x03
4021da177e4SLinus Torvalds #define	ESM_APU_FILTER_1POLE_HIPASS	0x04
4031da177e4SLinus Torvalds #define	ESM_APU_FILTER_OFF		0x05
4041da177e4SLinus Torvalds 
4051da177e4SLinus Torvalds /* APU ATFP Type */
4061da177e4SLinus Torvalds #define	ESM_APU_ATFP_AMPLITUDE			0x00
4071da177e4SLinus Torvalds #define	ESM_APU_ATFP_TREMELO			0x01
4081da177e4SLinus Torvalds #define	ESM_APU_ATFP_FILTER			0x02
4091da177e4SLinus Torvalds #define	ESM_APU_ATFP_PAN			0x03
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds /* APU ATFP Flags */
4121da177e4SLinus Torvalds #define	ESM_APU_ATFP_FLG_OFF			0x00
4131da177e4SLinus Torvalds #define	ESM_APU_ATFP_FLG_WAIT			0x01
4141da177e4SLinus Torvalds #define	ESM_APU_ATFP_FLG_DONE			0x02
4151da177e4SLinus Torvalds #define	ESM_APU_ATFP_FLG_INPROCESS		0x03
4161da177e4SLinus Torvalds 
4171da177e4SLinus Torvalds 
4181da177e4SLinus Torvalds /* capture mixing buffer size */
4191da177e4SLinus Torvalds #define ESM_MEM_ALIGN		0x1000
4201da177e4SLinus Torvalds #define ESM_MIXBUF_SIZE		0x400
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds #define ESM_MODE_PLAY		0
4231da177e4SLinus Torvalds #define ESM_MODE_CAPTURE	1
4241da177e4SLinus Torvalds 
4251da177e4SLinus Torvalds 
4261da177e4SLinus Torvalds /* APU use in the driver */
4271da177e4SLinus Torvalds enum snd_enum_apu_type {
4281da177e4SLinus Torvalds 	ESM_APU_PCM_PLAY,
4291da177e4SLinus Torvalds 	ESM_APU_PCM_CAPTURE,
4301da177e4SLinus Torvalds 	ESM_APU_PCM_RATECONV,
4311da177e4SLinus Torvalds 	ESM_APU_FREE
4321da177e4SLinus Torvalds };
4331da177e4SLinus Torvalds 
4341da177e4SLinus Torvalds /* chip type */
4351da177e4SLinus Torvalds enum {
4361da177e4SLinus Torvalds 	TYPE_MAESTRO, TYPE_MAESTRO2, TYPE_MAESTRO2E
4371da177e4SLinus Torvalds };
4381da177e4SLinus Torvalds 
4391da177e4SLinus Torvalds /* DMA Hack! */
440969165a8STakashi Iwai struct esm_memory {
4411da177e4SLinus Torvalds 	struct snd_dma_buffer buf;
4421da177e4SLinus Torvalds 	int empty;	/* status */
4431da177e4SLinus Torvalds 	struct list_head list;
4441da177e4SLinus Torvalds };
4451da177e4SLinus Torvalds 
4461da177e4SLinus Torvalds /* Playback Channel */
447969165a8STakashi Iwai struct esschan {
4481da177e4SLinus Torvalds 	int running;
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds 	u8 apu[4];
4511da177e4SLinus Torvalds 	u8 apu_mode[4];
4521da177e4SLinus Torvalds 
4531da177e4SLinus Torvalds 	/* playback/capture pcm buffer */
454969165a8STakashi Iwai 	struct esm_memory *memory;
4551da177e4SLinus Torvalds 	/* capture mixer buffer */
456969165a8STakashi Iwai 	struct esm_memory *mixbuf;
4571da177e4SLinus Torvalds 
4581da177e4SLinus Torvalds 	unsigned int hwptr;	/* current hw pointer in bytes */
4591da177e4SLinus Torvalds 	unsigned int count;	/* sample counter in bytes */
4601da177e4SLinus Torvalds 	unsigned int dma_size;	/* total buffer size in bytes */
4611da177e4SLinus Torvalds 	unsigned int frag_size;	/* period size in bytes */
4621da177e4SLinus Torvalds 	unsigned int wav_shift;
4631da177e4SLinus Torvalds 	u16 base[4];		/* offset for ptr */
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds 	/* stereo/16bit flag */
4661da177e4SLinus Torvalds 	unsigned char fmt;
4671da177e4SLinus Torvalds 	int mode;	/* playback / capture */
4681da177e4SLinus Torvalds 
4691da177e4SLinus Torvalds 	int bob_freq;	/* required timer frequency */
4701da177e4SLinus Torvalds 
471969165a8STakashi Iwai 	struct snd_pcm_substream *substream;
4721da177e4SLinus Torvalds 
4731da177e4SLinus Torvalds 	/* linked list */
4741da177e4SLinus Torvalds 	struct list_head list;
4751da177e4SLinus Torvalds 
476c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
4771da177e4SLinus Torvalds 	u16 wc_map[4];
4781da177e4SLinus Torvalds #endif
4791da177e4SLinus Torvalds };
4801da177e4SLinus Torvalds 
481969165a8STakashi Iwai struct es1968 {
4821da177e4SLinus Torvalds 	/* Module Config */
4831da177e4SLinus Torvalds 	int total_bufsize;			/* in bytes */
4841da177e4SLinus Torvalds 
4851da177e4SLinus Torvalds 	int playback_streams, capture_streams;
4861da177e4SLinus Torvalds 
4871da177e4SLinus Torvalds 	unsigned int clock;		/* clock */
4881da177e4SLinus Torvalds 	/* for clock measurement */
4891da177e4SLinus Torvalds 	unsigned int in_measurement: 1;
4901da177e4SLinus Torvalds 	unsigned int measure_apu;
4911da177e4SLinus Torvalds 	unsigned int measure_lastpos;
4921da177e4SLinus Torvalds 	unsigned int measure_count;
4931da177e4SLinus Torvalds 
4941da177e4SLinus Torvalds 	/* buffer */
4951da177e4SLinus Torvalds 	struct snd_dma_buffer dma;
4961da177e4SLinus Torvalds 
4971da177e4SLinus Torvalds 	/* Resources... */
4981da177e4SLinus Torvalds 	int irq;
4991da177e4SLinus Torvalds 	unsigned long io_port;
5001da177e4SLinus Torvalds 	int type;
5011da177e4SLinus Torvalds 	struct pci_dev *pci;
502969165a8STakashi Iwai 	struct snd_card *card;
503969165a8STakashi Iwai 	struct snd_pcm *pcm;
5041da177e4SLinus Torvalds 	int do_pm;		/* power-management enabled */
5051da177e4SLinus Torvalds 
5061da177e4SLinus Torvalds 	/* DMA memory block */
5071da177e4SLinus Torvalds 	struct list_head buf_list;
5081da177e4SLinus Torvalds 
5091da177e4SLinus Torvalds 	/* ALSA Stuff */
510969165a8STakashi Iwai 	struct snd_ac97 *ac97;
511969165a8STakashi Iwai 	struct snd_rawmidi *rmidi;
5121da177e4SLinus Torvalds 
5131da177e4SLinus Torvalds 	spinlock_t reg_lock;
5141da177e4SLinus Torvalds 	unsigned int in_suspend;
5151da177e4SLinus Torvalds 
5161da177e4SLinus Torvalds 	/* Maestro Stuff */
5171da177e4SLinus Torvalds 	u16 maestro_map[32];
5181da177e4SLinus Torvalds 	int bobclient;		/* active timer instancs */
5191da177e4SLinus Torvalds 	int bob_freq;		/* timer frequency */
52062932df8SIngo Molnar 	struct mutex memory_mutex;	/* memory lock */
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds 	/* APU states */
5231da177e4SLinus Torvalds 	unsigned char apu[NR_APUS];
5241da177e4SLinus Torvalds 
5251da177e4SLinus Torvalds 	/* active substreams */
5261da177e4SLinus Torvalds 	struct list_head substream_list;
5271da177e4SLinus Torvalds 	spinlock_t substream_lock;
5281da177e4SLinus Torvalds 
529c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
5301da177e4SLinus Torvalds 	u16 apu_map[NR_APUS][NR_APU_REGS];
5311da177e4SLinus Torvalds #endif
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds #ifdef SUPPORT_JOYSTICK
5341da177e4SLinus Torvalds 	struct gameport *gameport;
5351da177e4SLinus Torvalds #endif
5365a5e02e5SHans de Goede 
5375a5e02e5SHans de Goede #ifdef CONFIG_SND_ES1968_INPUT
5385a5e02e5SHans de Goede 	struct input_dev *input_dev;
5395a5e02e5SHans de Goede 	char phys[64];			/* physical device path */
5405a5e02e5SHans de Goede #else
5415a5e02e5SHans de Goede 	struct snd_kcontrol *master_switch; /* for h/w volume control */
5425a5e02e5SHans de Goede 	struct snd_kcontrol *master_volume;
5435a5e02e5SHans de Goede #endif
54430bdee02STakashi Iwai 	struct work_struct hwvol_work;
5451872f589SOndrej Zary 
5461872f589SOndrej Zary #ifdef CONFIG_SND_ES1968_RADIO
547d4ecc83bSHans Verkuil 	struct v4l2_device v4l2_dev;
5481872f589SOndrej Zary 	struct snd_tea575x tea;
5498e0d7043SOndrej Zary 	unsigned int tea575x_tuner;
5501872f589SOndrej Zary #endif
5511da177e4SLinus Torvalds };
5521da177e4SLinus Torvalds 
5537d12e780SDavid Howells static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id);
5541da177e4SLinus Torvalds 
5559baa3c34SBenoit Taine static const struct pci_device_id snd_es1968_ids[] = {
5561da177e4SLinus Torvalds 	/* Maestro 1 */
5571da177e4SLinus Torvalds         { 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO },
5581da177e4SLinus Torvalds 	/* Maestro 2 */
5591da177e4SLinus Torvalds 	{ 0x125d, 0x1968, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2 },
5601da177e4SLinus Torvalds 	/* Maestro 2E */
5611da177e4SLinus Torvalds         { 0x125d, 0x1978, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2E },
5621da177e4SLinus Torvalds 	{ 0, }
5631da177e4SLinus Torvalds };
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, snd_es1968_ids);
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds /* *********************
5681da177e4SLinus Torvalds    * Low Level Funcs!  *
5691da177e4SLinus Torvalds    *********************/
5701da177e4SLinus Torvalds 
5711da177e4SLinus Torvalds /* no spinlock */
__maestro_write(struct es1968 * chip,u16 reg,u16 data)572969165a8STakashi Iwai static void __maestro_write(struct es1968 *chip, u16 reg, u16 data)
5731da177e4SLinus Torvalds {
5741da177e4SLinus Torvalds 	outw(reg, chip->io_port + ESM_INDEX);
5751da177e4SLinus Torvalds 	outw(data, chip->io_port + ESM_DATA);
5761da177e4SLinus Torvalds 	chip->maestro_map[reg] = data;
5771da177e4SLinus Torvalds }
5781da177e4SLinus Torvalds 
maestro_write(struct es1968 * chip,u16 reg,u16 data)579969165a8STakashi Iwai static inline void maestro_write(struct es1968 *chip, u16 reg, u16 data)
5801da177e4SLinus Torvalds {
5811da177e4SLinus Torvalds 	unsigned long flags;
5821da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
5831da177e4SLinus Torvalds 	__maestro_write(chip, reg, data);
5841da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
5851da177e4SLinus Torvalds }
5861da177e4SLinus Torvalds 
5871da177e4SLinus Torvalds /* no spinlock */
__maestro_read(struct es1968 * chip,u16 reg)588969165a8STakashi Iwai static u16 __maestro_read(struct es1968 *chip, u16 reg)
5891da177e4SLinus Torvalds {
5901da177e4SLinus Torvalds 	if (READABLE_MAP & (1 << reg)) {
5911da177e4SLinus Torvalds 		outw(reg, chip->io_port + ESM_INDEX);
5921da177e4SLinus Torvalds 		chip->maestro_map[reg] = inw(chip->io_port + ESM_DATA);
5931da177e4SLinus Torvalds 	}
5941da177e4SLinus Torvalds 	return chip->maestro_map[reg];
5951da177e4SLinus Torvalds }
5961da177e4SLinus Torvalds 
maestro_read(struct es1968 * chip,u16 reg)597969165a8STakashi Iwai static inline u16 maestro_read(struct es1968 *chip, u16 reg)
5981da177e4SLinus Torvalds {
5991da177e4SLinus Torvalds 	unsigned long flags;
6001da177e4SLinus Torvalds 	u16 result;
6011da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
6021da177e4SLinus Torvalds 	result = __maestro_read(chip, reg);
6031da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
6041da177e4SLinus Torvalds 	return result;
6051da177e4SLinus Torvalds }
6061da177e4SLinus Torvalds 
6071da177e4SLinus Torvalds /* Wait for the codec bus to be free */
snd_es1968_ac97_wait(struct es1968 * chip)608969165a8STakashi Iwai static int snd_es1968_ac97_wait(struct es1968 *chip)
6091da177e4SLinus Torvalds {
6101da177e4SLinus Torvalds 	int timeout = 100000;
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 	while (timeout-- > 0) {
6131da177e4SLinus Torvalds 		if (!(inb(chip->io_port + ESM_AC97_INDEX) & 1))
6141da177e4SLinus Torvalds 			return 0;
6151da177e4SLinus Torvalds 		cond_resched();
6161da177e4SLinus Torvalds 	}
61786cd372fSTakashi Iwai 	dev_dbg(chip->card->dev, "ac97 timeout\n");
6181da177e4SLinus Torvalds 	return 1; /* timeout */
6191da177e4SLinus Torvalds }
6201da177e4SLinus Torvalds 
snd_es1968_ac97_wait_poll(struct es1968 * chip)6214b47c971SArjan van de Ven static int snd_es1968_ac97_wait_poll(struct es1968 *chip)
6224b47c971SArjan van de Ven {
6234b47c971SArjan van de Ven 	int timeout = 100000;
6244b47c971SArjan van de Ven 
6254b47c971SArjan van de Ven 	while (timeout-- > 0) {
6264b47c971SArjan van de Ven 		if (!(inb(chip->io_port + ESM_AC97_INDEX) & 1))
6274b47c971SArjan van de Ven 			return 0;
6284b47c971SArjan van de Ven 	}
62986cd372fSTakashi Iwai 	dev_dbg(chip->card->dev, "ac97 timeout\n");
6304b47c971SArjan van de Ven 	return 1; /* timeout */
6314b47c971SArjan van de Ven }
6324b47c971SArjan van de Ven 
snd_es1968_ac97_write(struct snd_ac97 * ac97,unsigned short reg,unsigned short val)633969165a8STakashi Iwai static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
6341da177e4SLinus Torvalds {
635969165a8STakashi Iwai 	struct es1968 *chip = ac97->private_data;
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds 	snd_es1968_ac97_wait(chip);
6381da177e4SLinus Torvalds 
6391da177e4SLinus Torvalds 	/* Write the bus */
6401da177e4SLinus Torvalds 	outw(val, chip->io_port + ESM_AC97_DATA);
6411da177e4SLinus Torvalds 	/*msleep(1);*/
6421da177e4SLinus Torvalds 	outb(reg, chip->io_port + ESM_AC97_INDEX);
6431da177e4SLinus Torvalds 	/*msleep(1);*/
6441da177e4SLinus Torvalds }
6451da177e4SLinus Torvalds 
snd_es1968_ac97_read(struct snd_ac97 * ac97,unsigned short reg)646969165a8STakashi Iwai static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
6471da177e4SLinus Torvalds {
6481da177e4SLinus Torvalds 	u16 data = 0;
649969165a8STakashi Iwai 	struct es1968 *chip = ac97->private_data;
6501da177e4SLinus Torvalds 
6511da177e4SLinus Torvalds 	snd_es1968_ac97_wait(chip);
6521da177e4SLinus Torvalds 
6531da177e4SLinus Torvalds 	outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
6541da177e4SLinus Torvalds 	/*msleep(1);*/
6551da177e4SLinus Torvalds 
6564b47c971SArjan van de Ven 	if (!snd_es1968_ac97_wait_poll(chip)) {
6571da177e4SLinus Torvalds 		data = inw(chip->io_port + ESM_AC97_DATA);
6581da177e4SLinus Torvalds 		/*msleep(1);*/
6591da177e4SLinus Torvalds 	}
6601da177e4SLinus Torvalds 
6611da177e4SLinus Torvalds 	return data;
6621da177e4SLinus Torvalds }
6631da177e4SLinus Torvalds 
6641da177e4SLinus Torvalds /* no spinlock */
apu_index_set(struct es1968 * chip,u16 index)665969165a8STakashi Iwai static void apu_index_set(struct es1968 *chip, u16 index)
6661da177e4SLinus Torvalds {
6671da177e4SLinus Torvalds 	int i;
6681da177e4SLinus Torvalds 	__maestro_write(chip, IDR1_CRAM_POINTER, index);
6691da177e4SLinus Torvalds 	for (i = 0; i < 1000; i++)
6701da177e4SLinus Torvalds 		if (__maestro_read(chip, IDR1_CRAM_POINTER) == index)
6711da177e4SLinus Torvalds 			return;
67286cd372fSTakashi Iwai 	dev_dbg(chip->card->dev, "APU register select failed. (Timeout)\n");
6731da177e4SLinus Torvalds }
6741da177e4SLinus Torvalds 
6751da177e4SLinus Torvalds /* no spinlock */
apu_data_set(struct es1968 * chip,u16 data)676969165a8STakashi Iwai static void apu_data_set(struct es1968 *chip, u16 data)
6771da177e4SLinus Torvalds {
6781da177e4SLinus Torvalds 	int i;
6791da177e4SLinus Torvalds 	for (i = 0; i < 1000; i++) {
6801da177e4SLinus Torvalds 		if (__maestro_read(chip, IDR0_DATA_PORT) == data)
6811da177e4SLinus Torvalds 			return;
6821da177e4SLinus Torvalds 		__maestro_write(chip, IDR0_DATA_PORT, data);
6831da177e4SLinus Torvalds 	}
68486cd372fSTakashi Iwai 	dev_dbg(chip->card->dev, "APU register set probably failed (Timeout)!\n");
6851da177e4SLinus Torvalds }
6861da177e4SLinus Torvalds 
6871da177e4SLinus Torvalds /* no spinlock */
__apu_set_register(struct es1968 * chip,u16 channel,u8 reg,u16 data)688969165a8STakashi Iwai static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data)
6891da177e4SLinus Torvalds {
690da3cec35STakashi Iwai 	if (snd_BUG_ON(channel >= NR_APUS))
691da3cec35STakashi Iwai 		return;
692c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
6931da177e4SLinus Torvalds 	chip->apu_map[channel][reg] = data;
6941da177e4SLinus Torvalds #endif
6951da177e4SLinus Torvalds 	reg |= (channel << 4);
6961da177e4SLinus Torvalds 	apu_index_set(chip, reg);
6971da177e4SLinus Torvalds 	apu_data_set(chip, data);
6981da177e4SLinus Torvalds }
6991da177e4SLinus Torvalds 
apu_set_register(struct es1968 * chip,u16 channel,u8 reg,u16 data)700858119e1SArjan van de Ven static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data)
7011da177e4SLinus Torvalds {
7021da177e4SLinus Torvalds 	unsigned long flags;
7031da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
7041da177e4SLinus Torvalds 	__apu_set_register(chip, channel, reg, data);
7051da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
7061da177e4SLinus Torvalds }
7071da177e4SLinus Torvalds 
__apu_get_register(struct es1968 * chip,u16 channel,u8 reg)708969165a8STakashi Iwai static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg)
7091da177e4SLinus Torvalds {
710da3cec35STakashi Iwai 	if (snd_BUG_ON(channel >= NR_APUS))
711da3cec35STakashi Iwai 		return 0;
7121da177e4SLinus Torvalds 	reg |= (channel << 4);
7131da177e4SLinus Torvalds 	apu_index_set(chip, reg);
7141da177e4SLinus Torvalds 	return __maestro_read(chip, IDR0_DATA_PORT);
7151da177e4SLinus Torvalds }
7161da177e4SLinus Torvalds 
apu_get_register(struct es1968 * chip,u16 channel,u8 reg)717858119e1SArjan van de Ven static u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg)
7181da177e4SLinus Torvalds {
7191da177e4SLinus Torvalds 	unsigned long flags;
7201da177e4SLinus Torvalds 	u16 v;
7211da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
7221da177e4SLinus Torvalds 	v = __apu_get_register(chip, channel, reg);
7231da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
7241da177e4SLinus Torvalds 	return v;
7251da177e4SLinus Torvalds }
7261da177e4SLinus Torvalds 
7271da177e4SLinus Torvalds #if 0 /* ASSP is not supported */
7281da177e4SLinus Torvalds 
729969165a8STakashi Iwai static void assp_set_register(struct es1968 *chip, u32 reg, u32 value)
7301da177e4SLinus Torvalds {
7311da177e4SLinus Torvalds 	unsigned long flags;
7321da177e4SLinus Torvalds 
7331da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
7341da177e4SLinus Torvalds 	outl(reg, chip->io_port + ASSP_INDEX);
7351da177e4SLinus Torvalds 	outl(value, chip->io_port + ASSP_DATA);
7361da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
7371da177e4SLinus Torvalds }
7381da177e4SLinus Torvalds 
739969165a8STakashi Iwai static u32 assp_get_register(struct es1968 *chip, u32 reg)
7401da177e4SLinus Torvalds {
7411da177e4SLinus Torvalds 	unsigned long flags;
7421da177e4SLinus Torvalds 	u32 value;
7431da177e4SLinus Torvalds 
7441da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
7451da177e4SLinus Torvalds 	outl(reg, chip->io_port + ASSP_INDEX);
7461da177e4SLinus Torvalds 	value = inl(chip->io_port + ASSP_DATA);
7471da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
7481da177e4SLinus Torvalds 
7491da177e4SLinus Torvalds 	return value;
7501da177e4SLinus Torvalds }
7511da177e4SLinus Torvalds 
7521da177e4SLinus Torvalds #endif
7531da177e4SLinus Torvalds 
wave_set_register(struct es1968 * chip,u16 reg,u16 value)754969165a8STakashi Iwai static void wave_set_register(struct es1968 *chip, u16 reg, u16 value)
7551da177e4SLinus Torvalds {
7561da177e4SLinus Torvalds 	unsigned long flags;
7571da177e4SLinus Torvalds 
7581da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
7591da177e4SLinus Torvalds 	outw(reg, chip->io_port + WC_INDEX);
7601da177e4SLinus Torvalds 	outw(value, chip->io_port + WC_DATA);
7611da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
7621da177e4SLinus Torvalds }
7631da177e4SLinus Torvalds 
wave_get_register(struct es1968 * chip,u16 reg)764969165a8STakashi Iwai static u16 wave_get_register(struct es1968 *chip, u16 reg)
7651da177e4SLinus Torvalds {
7661da177e4SLinus Torvalds 	unsigned long flags;
7671da177e4SLinus Torvalds 	u16 value;
7681da177e4SLinus Torvalds 
7691da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
7701da177e4SLinus Torvalds 	outw(reg, chip->io_port + WC_INDEX);
7711da177e4SLinus Torvalds 	value = inw(chip->io_port + WC_DATA);
7721da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
7731da177e4SLinus Torvalds 
7741da177e4SLinus Torvalds 	return value;
7751da177e4SLinus Torvalds }
7761da177e4SLinus Torvalds 
7771da177e4SLinus Torvalds /* *******************
7781da177e4SLinus Torvalds    * Bob the Timer!  *
7791da177e4SLinus Torvalds    *******************/
7801da177e4SLinus Torvalds 
snd_es1968_bob_stop(struct es1968 * chip)781969165a8STakashi Iwai static void snd_es1968_bob_stop(struct es1968 *chip)
7821da177e4SLinus Torvalds {
7831da177e4SLinus Torvalds 	u16 reg;
7841da177e4SLinus Torvalds 
7851da177e4SLinus Torvalds 	reg = __maestro_read(chip, 0x11);
7861da177e4SLinus Torvalds 	reg &= ~ESM_BOB_ENABLE;
7871da177e4SLinus Torvalds 	__maestro_write(chip, 0x11, reg);
7881da177e4SLinus Torvalds 	reg = __maestro_read(chip, 0x17);
7891da177e4SLinus Torvalds 	reg &= ~ESM_BOB_START;
7901da177e4SLinus Torvalds 	__maestro_write(chip, 0x17, reg);
7911da177e4SLinus Torvalds }
7921da177e4SLinus Torvalds 
snd_es1968_bob_start(struct es1968 * chip)793969165a8STakashi Iwai static void snd_es1968_bob_start(struct es1968 *chip)
7941da177e4SLinus Torvalds {
7951da177e4SLinus Torvalds 	int prescale;
7961da177e4SLinus Torvalds 	int divide;
7971da177e4SLinus Torvalds 
7981da177e4SLinus Torvalds 	/* compute ideal interrupt frequency for buffer size & play rate */
7991da177e4SLinus Torvalds 	/* first, find best prescaler value to match freq */
8001da177e4SLinus Torvalds 	for (prescale = 5; prescale < 12; prescale++)
8011da177e4SLinus Torvalds 		if (chip->bob_freq > (ESS_SYSCLK >> (prescale + 9)))
8021da177e4SLinus Torvalds 			break;
8031da177e4SLinus Torvalds 
8041da177e4SLinus Torvalds 	/* next, back off prescaler whilst getting divider into optimum range */
8051da177e4SLinus Torvalds 	divide = 1;
8061da177e4SLinus Torvalds 	while ((prescale > 5) && (divide < 32)) {
8071da177e4SLinus Torvalds 		prescale--;
8081da177e4SLinus Torvalds 		divide <<= 1;
8091da177e4SLinus Torvalds 	}
8101da177e4SLinus Torvalds 	divide >>= 1;
8111da177e4SLinus Torvalds 
8121da177e4SLinus Torvalds 	/* now fine-tune the divider for best match */
8131da177e4SLinus Torvalds 	for (; divide < 31; divide++)
8141da177e4SLinus Torvalds 		if (chip->bob_freq >
8151da177e4SLinus Torvalds 		    ((ESS_SYSCLK >> (prescale + 9)) / (divide + 1))) break;
8161da177e4SLinus Torvalds 
8171da177e4SLinus Torvalds 	/* divide = 0 is illegal, but don't let prescale = 4! */
8181da177e4SLinus Torvalds 	if (divide == 0) {
8191da177e4SLinus Torvalds 		divide++;
8201da177e4SLinus Torvalds 		if (prescale > 5)
8211da177e4SLinus Torvalds 			prescale--;
8221da177e4SLinus Torvalds 	} else if (divide > 1)
8231da177e4SLinus Torvalds 		divide--;
8241da177e4SLinus Torvalds 
8251da177e4SLinus Torvalds 	__maestro_write(chip, 6, 0x9000 | (prescale << 5) | divide);	/* set reg */
8261da177e4SLinus Torvalds 
8271da177e4SLinus Torvalds 	/* Now set IDR 11/17 */
8281da177e4SLinus Torvalds 	__maestro_write(chip, 0x11, __maestro_read(chip, 0x11) | 1);
8291da177e4SLinus Torvalds 	__maestro_write(chip, 0x17, __maestro_read(chip, 0x17) | 1);
8301da177e4SLinus Torvalds }
8311da177e4SLinus Torvalds 
8321da177e4SLinus Torvalds /* call with substream spinlock */
snd_es1968_bob_inc(struct es1968 * chip,int freq)833969165a8STakashi Iwai static void snd_es1968_bob_inc(struct es1968 *chip, int freq)
8341da177e4SLinus Torvalds {
8351da177e4SLinus Torvalds 	chip->bobclient++;
8361da177e4SLinus Torvalds 	if (chip->bobclient == 1) {
8371da177e4SLinus Torvalds 		chip->bob_freq = freq;
8381da177e4SLinus Torvalds 		snd_es1968_bob_start(chip);
8391da177e4SLinus Torvalds 	} else if (chip->bob_freq < freq) {
8401da177e4SLinus Torvalds 		snd_es1968_bob_stop(chip);
8411da177e4SLinus Torvalds 		chip->bob_freq = freq;
8421da177e4SLinus Torvalds 		snd_es1968_bob_start(chip);
8431da177e4SLinus Torvalds 	}
8441da177e4SLinus Torvalds }
8451da177e4SLinus Torvalds 
8461da177e4SLinus Torvalds /* call with substream spinlock */
snd_es1968_bob_dec(struct es1968 * chip)847969165a8STakashi Iwai static void snd_es1968_bob_dec(struct es1968 *chip)
8481da177e4SLinus Torvalds {
8491da177e4SLinus Torvalds 	chip->bobclient--;
8501da177e4SLinus Torvalds 	if (chip->bobclient <= 0)
8511da177e4SLinus Torvalds 		snd_es1968_bob_stop(chip);
8521da177e4SLinus Torvalds 	else if (chip->bob_freq > ESM_BOB_FREQ) {
8531da177e4SLinus Torvalds 		/* check reduction of timer frequency */
8541da177e4SLinus Torvalds 		int max_freq = ESM_BOB_FREQ;
85550f47ff1SMatthias Kaehlcke 		struct esschan *es;
85650f47ff1SMatthias Kaehlcke 		list_for_each_entry(es, &chip->substream_list, list) {
8571da177e4SLinus Torvalds 			if (max_freq < es->bob_freq)
8581da177e4SLinus Torvalds 				max_freq = es->bob_freq;
8591da177e4SLinus Torvalds 		}
8601da177e4SLinus Torvalds 		if (max_freq != chip->bob_freq) {
8611da177e4SLinus Torvalds 			snd_es1968_bob_stop(chip);
8621da177e4SLinus Torvalds 			chip->bob_freq = max_freq;
8631da177e4SLinus Torvalds 			snd_es1968_bob_start(chip);
8641da177e4SLinus Torvalds 		}
8651da177e4SLinus Torvalds 	}
8661da177e4SLinus Torvalds }
8671da177e4SLinus Torvalds 
8681da177e4SLinus Torvalds static int
snd_es1968_calc_bob_rate(struct es1968 * chip,struct esschan * es,struct snd_pcm_runtime * runtime)869969165a8STakashi Iwai snd_es1968_calc_bob_rate(struct es1968 *chip, struct esschan *es,
870969165a8STakashi Iwai 			 struct snd_pcm_runtime *runtime)
8711da177e4SLinus Torvalds {
8721da177e4SLinus Torvalds 	/* we acquire 4 interrupts per period for precise control.. */
8731da177e4SLinus Torvalds 	int freq = runtime->rate * 4;
8741da177e4SLinus Torvalds 	if (es->fmt & ESS_FMT_STEREO)
8751da177e4SLinus Torvalds 		freq <<= 1;
8761da177e4SLinus Torvalds 	if (es->fmt & ESS_FMT_16BIT)
8771da177e4SLinus Torvalds 		freq <<= 1;
8781da177e4SLinus Torvalds 	freq /= es->frag_size;
8791da177e4SLinus Torvalds 	if (freq < ESM_BOB_FREQ)
8801da177e4SLinus Torvalds 		freq = ESM_BOB_FREQ;
8811da177e4SLinus Torvalds 	else if (freq > ESM_BOB_FREQ_MAX)
8821da177e4SLinus Torvalds 		freq = ESM_BOB_FREQ_MAX;
8831da177e4SLinus Torvalds 	return freq;
8841da177e4SLinus Torvalds }
8851da177e4SLinus Torvalds 
8861da177e4SLinus Torvalds 
8871da177e4SLinus Torvalds /*************
8881da177e4SLinus Torvalds  *  PCM Part *
8891da177e4SLinus Torvalds  *************/
8901da177e4SLinus Torvalds 
snd_es1968_compute_rate(struct es1968 * chip,u32 freq)891969165a8STakashi Iwai static u32 snd_es1968_compute_rate(struct es1968 *chip, u32 freq)
8921da177e4SLinus Torvalds {
8931da177e4SLinus Torvalds 	u32 rate = (freq << 16) / chip->clock;
8941da177e4SLinus Torvalds #if 0 /* XXX: do we need this? */
8951da177e4SLinus Torvalds 	if (rate > 0x10000)
8961da177e4SLinus Torvalds 		rate = 0x10000;
8971da177e4SLinus Torvalds #endif
8981da177e4SLinus Torvalds 	return rate;
8991da177e4SLinus Torvalds }
9001da177e4SLinus Torvalds 
9011da177e4SLinus Torvalds /* get current pointer */
90277933d72SJesper Juhl static inline unsigned int
snd_es1968_get_dma_ptr(struct es1968 * chip,struct esschan * es)903969165a8STakashi Iwai snd_es1968_get_dma_ptr(struct es1968 *chip, struct esschan *es)
9041da177e4SLinus Torvalds {
9051da177e4SLinus Torvalds 	unsigned int offset;
9061da177e4SLinus Torvalds 
9071da177e4SLinus Torvalds 	offset = apu_get_register(chip, es->apu[0], 5);
9081da177e4SLinus Torvalds 
9091da177e4SLinus Torvalds 	offset -= es->base[0];
9101da177e4SLinus Torvalds 
9111da177e4SLinus Torvalds 	return (offset & 0xFFFE);	/* hardware is in words */
9121da177e4SLinus Torvalds }
9131da177e4SLinus Torvalds 
snd_es1968_apu_set_freq(struct es1968 * chip,int apu,int freq)914969165a8STakashi Iwai static void snd_es1968_apu_set_freq(struct es1968 *chip, int apu, int freq)
9151da177e4SLinus Torvalds {
9161da177e4SLinus Torvalds 	apu_set_register(chip, apu, 2,
9171da177e4SLinus Torvalds 			   (apu_get_register(chip, apu, 2) & 0x00FF) |
9181da177e4SLinus Torvalds 			   ((freq & 0xff) << 8) | 0x10);
9191da177e4SLinus Torvalds 	apu_set_register(chip, apu, 3, freq >> 8);
9201da177e4SLinus Torvalds }
9211da177e4SLinus Torvalds 
9221da177e4SLinus Torvalds /* spin lock held */
snd_es1968_trigger_apu(struct es1968 * esm,int apu,int mode)923969165a8STakashi Iwai static inline void snd_es1968_trigger_apu(struct es1968 *esm, int apu, int mode)
9241da177e4SLinus Torvalds {
9251da177e4SLinus Torvalds 	/* set the APU mode */
9261da177e4SLinus Torvalds 	__apu_set_register(esm, apu, 0,
9271da177e4SLinus Torvalds 			   (__apu_get_register(esm, apu, 0) & 0xff0f) |
9281da177e4SLinus Torvalds 			   (mode << 4));
9291da177e4SLinus Torvalds }
9301da177e4SLinus Torvalds 
snd_es1968_pcm_start(struct es1968 * chip,struct esschan * es)931969165a8STakashi Iwai static void snd_es1968_pcm_start(struct es1968 *chip, struct esschan *es)
9321da177e4SLinus Torvalds {
9331da177e4SLinus Torvalds 	spin_lock(&chip->reg_lock);
9341da177e4SLinus Torvalds 	__apu_set_register(chip, es->apu[0], 5, es->base[0]);
9351da177e4SLinus Torvalds 	snd_es1968_trigger_apu(chip, es->apu[0], es->apu_mode[0]);
9361da177e4SLinus Torvalds 	if (es->mode == ESM_MODE_CAPTURE) {
9371da177e4SLinus Torvalds 		__apu_set_register(chip, es->apu[2], 5, es->base[2]);
9381da177e4SLinus Torvalds 		snd_es1968_trigger_apu(chip, es->apu[2], es->apu_mode[2]);
9391da177e4SLinus Torvalds 	}
9401da177e4SLinus Torvalds 	if (es->fmt & ESS_FMT_STEREO) {
9411da177e4SLinus Torvalds 		__apu_set_register(chip, es->apu[1], 5, es->base[1]);
9421da177e4SLinus Torvalds 		snd_es1968_trigger_apu(chip, es->apu[1], es->apu_mode[1]);
9431da177e4SLinus Torvalds 		if (es->mode == ESM_MODE_CAPTURE) {
9441da177e4SLinus Torvalds 			__apu_set_register(chip, es->apu[3], 5, es->base[3]);
9451da177e4SLinus Torvalds 			snd_es1968_trigger_apu(chip, es->apu[3], es->apu_mode[3]);
9461da177e4SLinus Torvalds 		}
9471da177e4SLinus Torvalds 	}
9481da177e4SLinus Torvalds 	spin_unlock(&chip->reg_lock);
9491da177e4SLinus Torvalds }
9501da177e4SLinus Torvalds 
snd_es1968_pcm_stop(struct es1968 * chip,struct esschan * es)951969165a8STakashi Iwai static void snd_es1968_pcm_stop(struct es1968 *chip, struct esschan *es)
9521da177e4SLinus Torvalds {
9531da177e4SLinus Torvalds 	spin_lock(&chip->reg_lock);
9541da177e4SLinus Torvalds 	snd_es1968_trigger_apu(chip, es->apu[0], 0);
9551da177e4SLinus Torvalds 	snd_es1968_trigger_apu(chip, es->apu[1], 0);
9561da177e4SLinus Torvalds 	if (es->mode == ESM_MODE_CAPTURE) {
9571da177e4SLinus Torvalds 		snd_es1968_trigger_apu(chip, es->apu[2], 0);
9581da177e4SLinus Torvalds 		snd_es1968_trigger_apu(chip, es->apu[3], 0);
9591da177e4SLinus Torvalds 	}
9601da177e4SLinus Torvalds 	spin_unlock(&chip->reg_lock);
9611da177e4SLinus Torvalds }
9621da177e4SLinus Torvalds 
9631da177e4SLinus Torvalds /* set the wavecache control reg */
snd_es1968_program_wavecache(struct es1968 * chip,struct esschan * es,int channel,u32 addr,int capture)964969165a8STakashi Iwai static void snd_es1968_program_wavecache(struct es1968 *chip, struct esschan *es,
9651da177e4SLinus Torvalds 					 int channel, u32 addr, int capture)
9661da177e4SLinus Torvalds {
9671da177e4SLinus Torvalds 	u32 tmpval = (addr - 0x10) & 0xFFF8;
9681da177e4SLinus Torvalds 
9691da177e4SLinus Torvalds 	if (! capture) {
9701da177e4SLinus Torvalds 		if (!(es->fmt & ESS_FMT_16BIT))
9711da177e4SLinus Torvalds 			tmpval |= 4;	/* 8bit */
9721da177e4SLinus Torvalds 		if (es->fmt & ESS_FMT_STEREO)
9731da177e4SLinus Torvalds 			tmpval |= 2;	/* stereo */
9741da177e4SLinus Torvalds 	}
9751da177e4SLinus Torvalds 
9761da177e4SLinus Torvalds 	/* set the wavecache control reg */
9771da177e4SLinus Torvalds 	wave_set_register(chip, es->apu[channel] << 3, tmpval);
9781da177e4SLinus Torvalds 
979c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
9801da177e4SLinus Torvalds 	es->wc_map[channel] = tmpval;
9811da177e4SLinus Torvalds #endif
9821da177e4SLinus Torvalds }
9831da177e4SLinus Torvalds 
9841da177e4SLinus Torvalds 
snd_es1968_playback_setup(struct es1968 * chip,struct esschan * es,struct snd_pcm_runtime * runtime)985969165a8STakashi Iwai static void snd_es1968_playback_setup(struct es1968 *chip, struct esschan *es,
986969165a8STakashi Iwai 				      struct snd_pcm_runtime *runtime)
9871da177e4SLinus Torvalds {
9881da177e4SLinus Torvalds 	u32 pa;
9891da177e4SLinus Torvalds 	int high_apu = 0;
9901da177e4SLinus Torvalds 	int channel, apu;
9911da177e4SLinus Torvalds 	int i, size;
9921da177e4SLinus Torvalds 	unsigned long flags;
9931da177e4SLinus Torvalds 	u32 freq;
9941da177e4SLinus Torvalds 
9951da177e4SLinus Torvalds 	size = es->dma_size >> es->wav_shift;
9961da177e4SLinus Torvalds 
9971da177e4SLinus Torvalds 	if (es->fmt & ESS_FMT_STEREO)
9981da177e4SLinus Torvalds 		high_apu++;
9991da177e4SLinus Torvalds 
10001da177e4SLinus Torvalds 	for (channel = 0; channel <= high_apu; channel++) {
10011da177e4SLinus Torvalds 		apu = es->apu[channel];
10021da177e4SLinus Torvalds 
10031da177e4SLinus Torvalds 		snd_es1968_program_wavecache(chip, es, channel, es->memory->buf.addr, 0);
10041da177e4SLinus Torvalds 
10051da177e4SLinus Torvalds 		/* Offset to PCMBAR */
10061da177e4SLinus Torvalds 		pa = es->memory->buf.addr;
10071da177e4SLinus Torvalds 		pa -= chip->dma.addr;
10081da177e4SLinus Torvalds 		pa >>= 1;	/* words */
10091da177e4SLinus Torvalds 
10101da177e4SLinus Torvalds 		pa |= 0x00400000;	/* System RAM (Bit 22) */
10111da177e4SLinus Torvalds 
10121da177e4SLinus Torvalds 		if (es->fmt & ESS_FMT_STEREO) {
10131da177e4SLinus Torvalds 			/* Enable stereo */
10141da177e4SLinus Torvalds 			if (channel)
10151da177e4SLinus Torvalds 				pa |= 0x00800000;	/* (Bit 23) */
10161da177e4SLinus Torvalds 			if (es->fmt & ESS_FMT_16BIT)
10171da177e4SLinus Torvalds 				pa >>= 1;
10181da177e4SLinus Torvalds 		}
10191da177e4SLinus Torvalds 
10201da177e4SLinus Torvalds 		/* base offset of dma calcs when reading the pointer
10211da177e4SLinus Torvalds 		   on this left one */
10221da177e4SLinus Torvalds 		es->base[channel] = pa & 0xFFFF;
10231da177e4SLinus Torvalds 
10241da177e4SLinus Torvalds 		for (i = 0; i < 16; i++)
10251da177e4SLinus Torvalds 			apu_set_register(chip, apu, i, 0x0000);
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds 		/* Load the buffer into the wave engine */
10281da177e4SLinus Torvalds 		apu_set_register(chip, apu, 4, ((pa >> 16) & 0xFF) << 8);
10291da177e4SLinus Torvalds 		apu_set_register(chip, apu, 5, pa & 0xFFFF);
10301da177e4SLinus Torvalds 		apu_set_register(chip, apu, 6, (pa + size) & 0xFFFF);
10311da177e4SLinus Torvalds 		/* setting loop == sample len */
10321da177e4SLinus Torvalds 		apu_set_register(chip, apu, 7, size);
10331da177e4SLinus Torvalds 
10341da177e4SLinus Torvalds 		/* clear effects/env.. */
10351da177e4SLinus Torvalds 		apu_set_register(chip, apu, 8, 0x0000);
10361da177e4SLinus Torvalds 		/* set amp now to 0xd0 (?), low byte is 'amplitude dest'? */
10371da177e4SLinus Torvalds 		apu_set_register(chip, apu, 9, 0xD000);
10381da177e4SLinus Torvalds 
10391da177e4SLinus Torvalds 		/* clear routing stuff */
10401da177e4SLinus Torvalds 		apu_set_register(chip, apu, 11, 0x0000);
10411da177e4SLinus Torvalds 		/* dma on, no envelopes, filter to all 1s) */
10421da177e4SLinus Torvalds 		apu_set_register(chip, apu, 0, 0x400F);
10431da177e4SLinus Torvalds 
10441da177e4SLinus Torvalds 		if (es->fmt & ESS_FMT_16BIT)
10451da177e4SLinus Torvalds 			es->apu_mode[channel] = ESM_APU_16BITLINEAR;
10461da177e4SLinus Torvalds 		else
10471da177e4SLinus Torvalds 			es->apu_mode[channel] = ESM_APU_8BITLINEAR;
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds 		if (es->fmt & ESS_FMT_STEREO) {
10501da177e4SLinus Torvalds 			/* set panning: left or right */
10511da177e4SLinus Torvalds 			/* Check: different panning. On my Canyon 3D Chipset the
10521da177e4SLinus Torvalds 			   Channels are swapped. I don't know, about the output
10531da177e4SLinus Torvalds 			   to the SPDif Link. Perhaps you have to change this
10541da177e4SLinus Torvalds 			   and not the APU Regs 4-5. */
10551da177e4SLinus Torvalds 			apu_set_register(chip, apu, 10,
10561da177e4SLinus Torvalds 					 0x8F00 | (channel ? 0 : 0x10));
10571da177e4SLinus Torvalds 			es->apu_mode[channel] += 1;	/* stereo */
10581da177e4SLinus Torvalds 		} else
10591da177e4SLinus Torvalds 			apu_set_register(chip, apu, 10, 0x8F08);
10601da177e4SLinus Torvalds 	}
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
10631da177e4SLinus Torvalds 	/* clear WP interrupts */
10641da177e4SLinus Torvalds 	outw(1, chip->io_port + 0x04);
10651da177e4SLinus Torvalds 	/* enable WP ints */
10661da177e4SLinus Torvalds 	outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ);
10671da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
10681da177e4SLinus Torvalds 
10691da177e4SLinus Torvalds 	freq = runtime->rate;
10701da177e4SLinus Torvalds 	/* set frequency */
10711da177e4SLinus Torvalds 	if (freq > 48000)
10721da177e4SLinus Torvalds 		freq = 48000;
10731da177e4SLinus Torvalds 	if (freq < 4000)
10741da177e4SLinus Torvalds 		freq = 4000;
10751da177e4SLinus Torvalds 
10761da177e4SLinus Torvalds 	/* hmmm.. */
10771da177e4SLinus Torvalds 	if (!(es->fmt & ESS_FMT_16BIT) && !(es->fmt & ESS_FMT_STEREO))
10781da177e4SLinus Torvalds 		freq >>= 1;
10791da177e4SLinus Torvalds 
10801da177e4SLinus Torvalds 	freq = snd_es1968_compute_rate(chip, freq);
10811da177e4SLinus Torvalds 
10821da177e4SLinus Torvalds 	/* Load the frequency, turn on 6dB */
10831da177e4SLinus Torvalds 	snd_es1968_apu_set_freq(chip, es->apu[0], freq);
10841da177e4SLinus Torvalds 	snd_es1968_apu_set_freq(chip, es->apu[1], freq);
10851da177e4SLinus Torvalds }
10861da177e4SLinus Torvalds 
10871da177e4SLinus Torvalds 
init_capture_apu(struct es1968 * chip,struct esschan * es,int channel,unsigned int pa,unsigned int bsize,int mode,int route)1088969165a8STakashi Iwai static void init_capture_apu(struct es1968 *chip, struct esschan *es, int channel,
10891da177e4SLinus Torvalds 			     unsigned int pa, unsigned int bsize,
10901da177e4SLinus Torvalds 			     int mode, int route)
10911da177e4SLinus Torvalds {
10921da177e4SLinus Torvalds 	int i, apu = es->apu[channel];
10931da177e4SLinus Torvalds 
10941da177e4SLinus Torvalds 	es->apu_mode[channel] = mode;
10951da177e4SLinus Torvalds 
10961da177e4SLinus Torvalds 	/* set the wavecache control reg */
10971da177e4SLinus Torvalds 	snd_es1968_program_wavecache(chip, es, channel, pa, 1);
10981da177e4SLinus Torvalds 
10991da177e4SLinus Torvalds 	/* Offset to PCMBAR */
11001da177e4SLinus Torvalds 	pa -= chip->dma.addr;
11011da177e4SLinus Torvalds 	pa >>= 1;	/* words */
11021da177e4SLinus Torvalds 
11031da177e4SLinus Torvalds 	/* base offset of dma calcs when reading the pointer
11041da177e4SLinus Torvalds 	   on this left one */
11051da177e4SLinus Torvalds 	es->base[channel] = pa & 0xFFFF;
11061da177e4SLinus Torvalds 	pa |= 0x00400000;	/* bit 22 -> System RAM */
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds 	/* Begin loading the APU */
11091da177e4SLinus Torvalds 	for (i = 0; i < 16; i++)
11101da177e4SLinus Torvalds 		apu_set_register(chip, apu, i, 0x0000);
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds 	/* need to enable subgroups.. and we should probably
11131da177e4SLinus Torvalds 	   have different groups for different /dev/dsps..  */
11141da177e4SLinus Torvalds 	apu_set_register(chip, apu, 2, 0x8);
11151da177e4SLinus Torvalds 
11161da177e4SLinus Torvalds 	/* Load the buffer into the wave engine */
11171da177e4SLinus Torvalds 	apu_set_register(chip, apu, 4, ((pa >> 16) & 0xFF) << 8);
11181da177e4SLinus Torvalds 	apu_set_register(chip, apu, 5, pa & 0xFFFF);
11191da177e4SLinus Torvalds 	apu_set_register(chip, apu, 6, (pa + bsize) & 0xFFFF);
11201da177e4SLinus Torvalds 	apu_set_register(chip, apu, 7, bsize);
11211da177e4SLinus Torvalds 	/* clear effects/env.. */
11221da177e4SLinus Torvalds 	apu_set_register(chip, apu, 8, 0x00F0);
11231da177e4SLinus Torvalds 	/* amplitude now?  sure.  why not.  */
11241da177e4SLinus Torvalds 	apu_set_register(chip, apu, 9, 0x0000);
11251da177e4SLinus Torvalds 	/* set filter tune, radius, polar pan */
11261da177e4SLinus Torvalds 	apu_set_register(chip, apu, 10, 0x8F08);
11271da177e4SLinus Torvalds 	/* route input */
11281da177e4SLinus Torvalds 	apu_set_register(chip, apu, 11, route);
11291da177e4SLinus Torvalds 	/* dma on, no envelopes, filter to all 1s) */
11301da177e4SLinus Torvalds 	apu_set_register(chip, apu, 0, 0x400F);
11311da177e4SLinus Torvalds }
11321da177e4SLinus Torvalds 
snd_es1968_capture_setup(struct es1968 * chip,struct esschan * es,struct snd_pcm_runtime * runtime)1133969165a8STakashi Iwai static void snd_es1968_capture_setup(struct es1968 *chip, struct esschan *es,
1134969165a8STakashi Iwai 				     struct snd_pcm_runtime *runtime)
11351da177e4SLinus Torvalds {
11361da177e4SLinus Torvalds 	int size;
11371da177e4SLinus Torvalds 	u32 freq;
11381da177e4SLinus Torvalds 	unsigned long flags;
11391da177e4SLinus Torvalds 
11401da177e4SLinus Torvalds 	size = es->dma_size >> es->wav_shift;
11411da177e4SLinus Torvalds 
11421da177e4SLinus Torvalds 	/* APU assignments:
11431da177e4SLinus Torvalds 	   0 = mono/left SRC
11441da177e4SLinus Torvalds 	   1 = right SRC
11451da177e4SLinus Torvalds 	   2 = mono/left Input Mixer
11461da177e4SLinus Torvalds 	   3 = right Input Mixer
11471da177e4SLinus Torvalds 	*/
11481da177e4SLinus Torvalds 	/* data seems to flow from the codec, through an apu into
11491da177e4SLinus Torvalds 	   the 'mixbuf' bit of page, then through the SRC apu
11501da177e4SLinus Torvalds 	   and out to the real 'buffer'.  ok.  sure.  */
11511da177e4SLinus Torvalds 
11521da177e4SLinus Torvalds 	/* input mixer (left/mono) */
11531da177e4SLinus Torvalds 	/* parallel in crap, see maestro reg 0xC [8-11] */
11541da177e4SLinus Torvalds 	init_capture_apu(chip, es, 2,
11551da177e4SLinus Torvalds 			 es->mixbuf->buf.addr, ESM_MIXBUF_SIZE/4, /* in words */
11561da177e4SLinus Torvalds 			 ESM_APU_INPUTMIXER, 0x14);
11571da177e4SLinus Torvalds 	/* SRC (left/mono); get input from inputing apu */
11581da177e4SLinus Torvalds 	init_capture_apu(chip, es, 0, es->memory->buf.addr, size,
11591da177e4SLinus Torvalds 			 ESM_APU_SRCONVERTOR, es->apu[2]);
11601da177e4SLinus Torvalds 	if (es->fmt & ESS_FMT_STEREO) {
11611da177e4SLinus Torvalds 		/* input mixer (right) */
11621da177e4SLinus Torvalds 		init_capture_apu(chip, es, 3,
11631da177e4SLinus Torvalds 				 es->mixbuf->buf.addr + ESM_MIXBUF_SIZE/2,
11641da177e4SLinus Torvalds 				 ESM_MIXBUF_SIZE/4, /* in words */
11651da177e4SLinus Torvalds 				 ESM_APU_INPUTMIXER, 0x15);
11661da177e4SLinus Torvalds 		/* SRC (right) */
11671da177e4SLinus Torvalds 		init_capture_apu(chip, es, 1,
11681da177e4SLinus Torvalds 				 es->memory->buf.addr + size*2, size,
11691da177e4SLinus Torvalds 				 ESM_APU_SRCONVERTOR, es->apu[3]);
11701da177e4SLinus Torvalds 	}
11711da177e4SLinus Torvalds 
11721da177e4SLinus Torvalds 	freq = runtime->rate;
11731da177e4SLinus Torvalds 	/* Sample Rate conversion APUs don't like 0x10000 for their rate */
11741da177e4SLinus Torvalds 	if (freq > 47999)
11751da177e4SLinus Torvalds 		freq = 47999;
11761da177e4SLinus Torvalds 	if (freq < 4000)
11771da177e4SLinus Torvalds 		freq = 4000;
11781da177e4SLinus Torvalds 
11791da177e4SLinus Torvalds 	freq = snd_es1968_compute_rate(chip, freq);
11801da177e4SLinus Torvalds 
11811da177e4SLinus Torvalds 	/* Load the frequency, turn on 6dB */
11821da177e4SLinus Torvalds 	snd_es1968_apu_set_freq(chip, es->apu[0], freq);
11831da177e4SLinus Torvalds 	snd_es1968_apu_set_freq(chip, es->apu[1], freq);
11841da177e4SLinus Torvalds 
11851da177e4SLinus Torvalds 	/* fix mixer rate at 48khz.  and its _must_ be 0x10000. */
11861da177e4SLinus Torvalds 	freq = 0x10000;
11871da177e4SLinus Torvalds 	snd_es1968_apu_set_freq(chip, es->apu[2], freq);
11881da177e4SLinus Torvalds 	snd_es1968_apu_set_freq(chip, es->apu[3], freq);
11891da177e4SLinus Torvalds 
11901da177e4SLinus Torvalds 	spin_lock_irqsave(&chip->reg_lock, flags);
11911da177e4SLinus Torvalds 	/* clear WP interrupts */
11921da177e4SLinus Torvalds 	outw(1, chip->io_port + 0x04);
11931da177e4SLinus Torvalds 	/* enable WP ints */
11941da177e4SLinus Torvalds 	outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ);
11951da177e4SLinus Torvalds 	spin_unlock_irqrestore(&chip->reg_lock, flags);
11961da177e4SLinus Torvalds }
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds /*******************
11991da177e4SLinus Torvalds  *  ALSA Interface *
12001da177e4SLinus Torvalds  *******************/
12011da177e4SLinus Torvalds 
snd_es1968_pcm_prepare(struct snd_pcm_substream * substream)1202969165a8STakashi Iwai static int snd_es1968_pcm_prepare(struct snd_pcm_substream *substream)
12031da177e4SLinus Torvalds {
1204969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1205969165a8STakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
1206969165a8STakashi Iwai 	struct esschan *es = runtime->private_data;
12071da177e4SLinus Torvalds 
12081da177e4SLinus Torvalds 	es->dma_size = snd_pcm_lib_buffer_bytes(substream);
12091da177e4SLinus Torvalds 	es->frag_size = snd_pcm_lib_period_bytes(substream);
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	es->wav_shift = 1; /* maestro handles always 16bit */
12121da177e4SLinus Torvalds 	es->fmt = 0;
12131da177e4SLinus Torvalds 	if (snd_pcm_format_width(runtime->format) == 16)
12141da177e4SLinus Torvalds 		es->fmt |= ESS_FMT_16BIT;
12151da177e4SLinus Torvalds 	if (runtime->channels > 1) {
12161da177e4SLinus Torvalds 		es->fmt |= ESS_FMT_STEREO;
12171da177e4SLinus Torvalds 		if (es->fmt & ESS_FMT_16BIT) /* 8bit is already word shifted */
12181da177e4SLinus Torvalds 			es->wav_shift++;
12191da177e4SLinus Torvalds 	}
12201da177e4SLinus Torvalds 	es->bob_freq = snd_es1968_calc_bob_rate(chip, es, runtime);
12211da177e4SLinus Torvalds 
12221da177e4SLinus Torvalds 	switch (es->mode) {
12231da177e4SLinus Torvalds 	case ESM_MODE_PLAY:
12241da177e4SLinus Torvalds 		snd_es1968_playback_setup(chip, es, runtime);
12251da177e4SLinus Torvalds 		break;
12261da177e4SLinus Torvalds 	case ESM_MODE_CAPTURE:
12271da177e4SLinus Torvalds 		snd_es1968_capture_setup(chip, es, runtime);
12281da177e4SLinus Torvalds 		break;
12291da177e4SLinus Torvalds 	}
12301da177e4SLinus Torvalds 
12311da177e4SLinus Torvalds 	return 0;
12321da177e4SLinus Torvalds }
12331da177e4SLinus Torvalds 
snd_es1968_pcm_trigger(struct snd_pcm_substream * substream,int cmd)1234969165a8STakashi Iwai static int snd_es1968_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
12351da177e4SLinus Torvalds {
1236969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1237969165a8STakashi Iwai 	struct esschan *es = substream->runtime->private_data;
12381da177e4SLinus Torvalds 
12391da177e4SLinus Torvalds 	spin_lock(&chip->substream_lock);
12401da177e4SLinus Torvalds 	switch (cmd) {
12411da177e4SLinus Torvalds 	case SNDRV_PCM_TRIGGER_START:
12421da177e4SLinus Torvalds 	case SNDRV_PCM_TRIGGER_RESUME:
12431da177e4SLinus Torvalds 		if (es->running)
12441da177e4SLinus Torvalds 			break;
12451da177e4SLinus Torvalds 		snd_es1968_bob_inc(chip, es->bob_freq);
12461da177e4SLinus Torvalds 		es->count = 0;
12471da177e4SLinus Torvalds 		es->hwptr = 0;
12481da177e4SLinus Torvalds 		snd_es1968_pcm_start(chip, es);
12491da177e4SLinus Torvalds 		es->running = 1;
12501da177e4SLinus Torvalds 		break;
12511da177e4SLinus Torvalds 	case SNDRV_PCM_TRIGGER_STOP:
12521da177e4SLinus Torvalds 	case SNDRV_PCM_TRIGGER_SUSPEND:
12531da177e4SLinus Torvalds 		if (! es->running)
12541da177e4SLinus Torvalds 			break;
12551da177e4SLinus Torvalds 		snd_es1968_pcm_stop(chip, es);
12561da177e4SLinus Torvalds 		es->running = 0;
12571da177e4SLinus Torvalds 		snd_es1968_bob_dec(chip);
12581da177e4SLinus Torvalds 		break;
12591da177e4SLinus Torvalds 	}
12601da177e4SLinus Torvalds 	spin_unlock(&chip->substream_lock);
12611da177e4SLinus Torvalds 	return 0;
12621da177e4SLinus Torvalds }
12631da177e4SLinus Torvalds 
snd_es1968_pcm_pointer(struct snd_pcm_substream * substream)1264969165a8STakashi Iwai static snd_pcm_uframes_t snd_es1968_pcm_pointer(struct snd_pcm_substream *substream)
12651da177e4SLinus Torvalds {
1266969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1267969165a8STakashi Iwai 	struct esschan *es = substream->runtime->private_data;
12681da177e4SLinus Torvalds 	unsigned int ptr;
12691da177e4SLinus Torvalds 
12701da177e4SLinus Torvalds 	ptr = snd_es1968_get_dma_ptr(chip, es) << es->wav_shift;
12711da177e4SLinus Torvalds 
12721da177e4SLinus Torvalds 	return bytes_to_frames(substream->runtime, ptr % es->dma_size);
12731da177e4SLinus Torvalds }
12741da177e4SLinus Torvalds 
1275dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_es1968_playback = {
12761da177e4SLinus Torvalds 	.info =			(SNDRV_PCM_INFO_MMAP |
12771da177e4SLinus Torvalds                		         SNDRV_PCM_INFO_MMAP_VALID |
12781da177e4SLinus Torvalds 				 SNDRV_PCM_INFO_INTERLEAVED |
12791da177e4SLinus Torvalds 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
12801da177e4SLinus Torvalds 				 /*SNDRV_PCM_INFO_PAUSE |*/
12811da177e4SLinus Torvalds 				 SNDRV_PCM_INFO_RESUME),
12821da177e4SLinus Torvalds 	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
12831da177e4SLinus Torvalds 	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
12841da177e4SLinus Torvalds 	.rate_min =		4000,
12851da177e4SLinus Torvalds 	.rate_max =		48000,
12861da177e4SLinus Torvalds 	.channels_min =		1,
12871da177e4SLinus Torvalds 	.channels_max =		2,
12881da177e4SLinus Torvalds 	.buffer_bytes_max =	65536,
12891da177e4SLinus Torvalds 	.period_bytes_min =	256,
12901da177e4SLinus Torvalds 	.period_bytes_max =	65536,
12911da177e4SLinus Torvalds 	.periods_min =		1,
12921da177e4SLinus Torvalds 	.periods_max =		1024,
12931da177e4SLinus Torvalds 	.fifo_size =		0,
12941da177e4SLinus Torvalds };
12951da177e4SLinus Torvalds 
1296dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_es1968_capture = {
12971da177e4SLinus Torvalds 	.info =			(SNDRV_PCM_INFO_NONINTERLEAVED |
12981da177e4SLinus Torvalds 				 SNDRV_PCM_INFO_MMAP |
12991da177e4SLinus Torvalds 				 SNDRV_PCM_INFO_MMAP_VALID |
13001da177e4SLinus Torvalds 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
13011da177e4SLinus Torvalds 				 /*SNDRV_PCM_INFO_PAUSE |*/
13021da177e4SLinus Torvalds 				 SNDRV_PCM_INFO_RESUME),
13031da177e4SLinus Torvalds 	.formats =		/*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE,
13041da177e4SLinus Torvalds 	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
13051da177e4SLinus Torvalds 	.rate_min =		4000,
13061da177e4SLinus Torvalds 	.rate_max =		48000,
13071da177e4SLinus Torvalds 	.channels_min =		1,
13081da177e4SLinus Torvalds 	.channels_max =		2,
13091da177e4SLinus Torvalds 	.buffer_bytes_max =	65536,
13101da177e4SLinus Torvalds 	.period_bytes_min =	256,
13111da177e4SLinus Torvalds 	.period_bytes_max =	65536,
13121da177e4SLinus Torvalds 	.periods_min =		1,
13131da177e4SLinus Torvalds 	.periods_max =		1024,
13141da177e4SLinus Torvalds 	.fifo_size =		0,
13151da177e4SLinus Torvalds };
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds /* *************************
13181da177e4SLinus Torvalds    * DMA memory management *
13191da177e4SLinus Torvalds    *************************/
13201da177e4SLinus Torvalds 
13211da177e4SLinus Torvalds /* Because the Maestro can only take addresses relative to the PCM base address
13221da177e4SLinus Torvalds    register :( */
13231da177e4SLinus Torvalds 
calc_available_memory_size(struct es1968 * chip)1324969165a8STakashi Iwai static int calc_available_memory_size(struct es1968 *chip)
13251da177e4SLinus Torvalds {
13261da177e4SLinus Torvalds 	int max_size = 0;
132750f47ff1SMatthias Kaehlcke 	struct esm_memory *buf;
13281da177e4SLinus Torvalds 
132962932df8SIngo Molnar 	mutex_lock(&chip->memory_mutex);
133050f47ff1SMatthias Kaehlcke 	list_for_each_entry(buf, &chip->buf_list, list) {
13311da177e4SLinus Torvalds 		if (buf->empty && buf->buf.bytes > max_size)
13321da177e4SLinus Torvalds 			max_size = buf->buf.bytes;
13331da177e4SLinus Torvalds 	}
133462932df8SIngo Molnar 	mutex_unlock(&chip->memory_mutex);
13351da177e4SLinus Torvalds 	if (max_size >= 128*1024)
13361da177e4SLinus Torvalds 		max_size = 127*1024;
13371da177e4SLinus Torvalds 	return max_size;
13381da177e4SLinus Torvalds }
13391da177e4SLinus Torvalds 
13401da177e4SLinus Torvalds /* allocate a new memory chunk with the specified size */
snd_es1968_new_memory(struct es1968 * chip,int size)1341969165a8STakashi Iwai static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size)
13421da177e4SLinus Torvalds {
1343969165a8STakashi Iwai 	struct esm_memory *buf;
13441da177e4SLinus Torvalds 
13457ab39926SClemens Ladisch 	size = ALIGN(size, ESM_MEM_ALIGN);
134662932df8SIngo Molnar 	mutex_lock(&chip->memory_mutex);
134750f47ff1SMatthias Kaehlcke 	list_for_each_entry(buf, &chip->buf_list, list) {
13481da177e4SLinus Torvalds 		if (buf->empty && buf->buf.bytes >= size)
13491da177e4SLinus Torvalds 			goto __found;
13501da177e4SLinus Torvalds 	}
135162932df8SIngo Molnar 	mutex_unlock(&chip->memory_mutex);
13521da177e4SLinus Torvalds 	return NULL;
13531da177e4SLinus Torvalds 
13541da177e4SLinus Torvalds __found:
13551da177e4SLinus Torvalds 	if (buf->buf.bytes > size) {
1356969165a8STakashi Iwai 		struct esm_memory *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
13571da177e4SLinus Torvalds 		if (chunk == NULL) {
135862932df8SIngo Molnar 			mutex_unlock(&chip->memory_mutex);
13591da177e4SLinus Torvalds 			return NULL;
13601da177e4SLinus Torvalds 		}
13611da177e4SLinus Torvalds 		chunk->buf = buf->buf;
13621da177e4SLinus Torvalds 		chunk->buf.bytes -= size;
13631da177e4SLinus Torvalds 		chunk->buf.area += size;
13641da177e4SLinus Torvalds 		chunk->buf.addr += size;
13651da177e4SLinus Torvalds 		chunk->empty = 1;
13661da177e4SLinus Torvalds 		buf->buf.bytes = size;
13671da177e4SLinus Torvalds 		list_add(&chunk->list, &buf->list);
13681da177e4SLinus Torvalds 	}
13691da177e4SLinus Torvalds 	buf->empty = 0;
137062932df8SIngo Molnar 	mutex_unlock(&chip->memory_mutex);
13711da177e4SLinus Torvalds 	return buf;
13721da177e4SLinus Torvalds }
13731da177e4SLinus Torvalds 
13741da177e4SLinus Torvalds /* free a memory chunk */
snd_es1968_free_memory(struct es1968 * chip,struct esm_memory * buf)1375969165a8STakashi Iwai static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf)
13761da177e4SLinus Torvalds {
1377969165a8STakashi Iwai 	struct esm_memory *chunk;
13781da177e4SLinus Torvalds 
137962932df8SIngo Molnar 	mutex_lock(&chip->memory_mutex);
13801da177e4SLinus Torvalds 	buf->empty = 1;
13811da177e4SLinus Torvalds 	if (buf->list.prev != &chip->buf_list) {
1382969165a8STakashi Iwai 		chunk = list_entry(buf->list.prev, struct esm_memory, list);
13831da177e4SLinus Torvalds 		if (chunk->empty) {
13841da177e4SLinus Torvalds 			chunk->buf.bytes += buf->buf.bytes;
13851da177e4SLinus Torvalds 			list_del(&buf->list);
13861da177e4SLinus Torvalds 			kfree(buf);
13871da177e4SLinus Torvalds 			buf = chunk;
13881da177e4SLinus Torvalds 		}
13891da177e4SLinus Torvalds 	}
13901da177e4SLinus Torvalds 	if (buf->list.next != &chip->buf_list) {
1391969165a8STakashi Iwai 		chunk = list_entry(buf->list.next, struct esm_memory, list);
13921da177e4SLinus Torvalds 		if (chunk->empty) {
13931da177e4SLinus Torvalds 			buf->buf.bytes += chunk->buf.bytes;
13941da177e4SLinus Torvalds 			list_del(&chunk->list);
13951da177e4SLinus Torvalds 			kfree(chunk);
13961da177e4SLinus Torvalds 		}
13971da177e4SLinus Torvalds 	}
139862932df8SIngo Molnar 	mutex_unlock(&chip->memory_mutex);
13991da177e4SLinus Torvalds }
14001da177e4SLinus Torvalds 
snd_es1968_free_dmabuf(struct es1968 * chip)1401969165a8STakashi Iwai static void snd_es1968_free_dmabuf(struct es1968 *chip)
14021da177e4SLinus Torvalds {
14031da177e4SLinus Torvalds 	struct list_head *p;
14041da177e4SLinus Torvalds 
14051da177e4SLinus Torvalds 	if (! chip->dma.area)
14061da177e4SLinus Torvalds 		return;
140747d98c02STakashi Iwai 	snd_dma_free_pages(&chip->dma);
14081da177e4SLinus Torvalds 	while ((p = chip->buf_list.next) != &chip->buf_list) {
1409969165a8STakashi Iwai 		struct esm_memory *chunk = list_entry(p, struct esm_memory, list);
14101da177e4SLinus Torvalds 		list_del(p);
14111da177e4SLinus Torvalds 		kfree(chunk);
14121da177e4SLinus Torvalds 	}
14131da177e4SLinus Torvalds }
14141da177e4SLinus Torvalds 
1415e23e7a14SBill Pemberton static int
snd_es1968_init_dmabuf(struct es1968 * chip)1416969165a8STakashi Iwai snd_es1968_init_dmabuf(struct es1968 *chip)
14171da177e4SLinus Torvalds {
14181da177e4SLinus Torvalds 	int err;
1419969165a8STakashi Iwai 	struct esm_memory *chunk;
14201da177e4SLinus Torvalds 
14211da177e4SLinus Torvalds 	err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
1422af7153a2STakashi Iwai 					   &chip->pci->dev,
14231da177e4SLinus Torvalds 					   chip->total_bufsize, &chip->dma);
14241da177e4SLinus Torvalds 	if (err < 0 || ! chip->dma.area) {
142586cd372fSTakashi Iwai 		dev_err(chip->card->dev,
142686cd372fSTakashi Iwai 			"can't allocate dma pages for size %d\n",
14271da177e4SLinus Torvalds 			   chip->total_bufsize);
14281da177e4SLinus Torvalds 		return -ENOMEM;
14291da177e4SLinus Torvalds 	}
14301da177e4SLinus Torvalds 	if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
14311da177e4SLinus Torvalds 		snd_dma_free_pages(&chip->dma);
143286cd372fSTakashi Iwai 		dev_err(chip->card->dev, "DMA buffer beyond 256MB.\n");
14331da177e4SLinus Torvalds 		return -ENOMEM;
14341da177e4SLinus Torvalds 	}
14351da177e4SLinus Torvalds 
14361da177e4SLinus Torvalds 	INIT_LIST_HEAD(&chip->buf_list);
14371da177e4SLinus Torvalds 	/* allocate an empty chunk */
14381da177e4SLinus Torvalds 	chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
14391da177e4SLinus Torvalds 	if (chunk == NULL) {
14401da177e4SLinus Torvalds 		snd_es1968_free_dmabuf(chip);
14411da177e4SLinus Torvalds 		return -ENOMEM;
14421da177e4SLinus Torvalds 	}
14431da177e4SLinus Torvalds 	memset(chip->dma.area, 0, ESM_MEM_ALIGN);
14441da177e4SLinus Torvalds 	chunk->buf = chip->dma;
14451da177e4SLinus Torvalds 	chunk->buf.area += ESM_MEM_ALIGN;
14461da177e4SLinus Torvalds 	chunk->buf.addr += ESM_MEM_ALIGN;
14471da177e4SLinus Torvalds 	chunk->buf.bytes -= ESM_MEM_ALIGN;
14481da177e4SLinus Torvalds 	chunk->empty = 1;
14491da177e4SLinus Torvalds 	list_add(&chunk->list, &chip->buf_list);
14501da177e4SLinus Torvalds 
14511da177e4SLinus Torvalds 	return 0;
14521da177e4SLinus Torvalds }
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds /* setup the dma_areas */
14551da177e4SLinus Torvalds /* buffer is extracted from the pre-allocated memory chunk */
snd_es1968_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)1456969165a8STakashi Iwai static int snd_es1968_hw_params(struct snd_pcm_substream *substream,
1457969165a8STakashi Iwai 				struct snd_pcm_hw_params *hw_params)
14581da177e4SLinus Torvalds {
1459969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1460969165a8STakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
1461969165a8STakashi Iwai 	struct esschan *chan = runtime->private_data;
14621da177e4SLinus Torvalds 	int size = params_buffer_bytes(hw_params);
14631da177e4SLinus Torvalds 
14641da177e4SLinus Torvalds 	if (chan->memory) {
14651da177e4SLinus Torvalds 		if (chan->memory->buf.bytes >= size) {
14661da177e4SLinus Torvalds 			runtime->dma_bytes = size;
14671da177e4SLinus Torvalds 			return 0;
14681da177e4SLinus Torvalds 		}
14691da177e4SLinus Torvalds 		snd_es1968_free_memory(chip, chan->memory);
14701da177e4SLinus Torvalds 	}
14711da177e4SLinus Torvalds 	chan->memory = snd_es1968_new_memory(chip, size);
14721da177e4SLinus Torvalds 	if (chan->memory == NULL) {
147386cd372fSTakashi Iwai 		dev_dbg(chip->card->dev,
147486cd372fSTakashi Iwai 			"cannot allocate dma buffer: size = %d\n", size);
14751da177e4SLinus Torvalds 		return -ENOMEM;
14761da177e4SLinus Torvalds 	}
14771da177e4SLinus Torvalds 	snd_pcm_set_runtime_buffer(substream, &chan->memory->buf);
14781da177e4SLinus Torvalds 	return 1; /* area was changed */
14791da177e4SLinus Torvalds }
14801da177e4SLinus Torvalds 
14811da177e4SLinus Torvalds /* remove dma areas if allocated */
snd_es1968_hw_free(struct snd_pcm_substream * substream)1482969165a8STakashi Iwai static int snd_es1968_hw_free(struct snd_pcm_substream *substream)
14831da177e4SLinus Torvalds {
1484969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1485969165a8STakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
1486969165a8STakashi Iwai 	struct esschan *chan;
14871da177e4SLinus Torvalds 
14881da177e4SLinus Torvalds 	if (runtime->private_data == NULL)
14891da177e4SLinus Torvalds 		return 0;
14901da177e4SLinus Torvalds 	chan = runtime->private_data;
14911da177e4SLinus Torvalds 	if (chan->memory) {
14921da177e4SLinus Torvalds 		snd_es1968_free_memory(chip, chan->memory);
14931da177e4SLinus Torvalds 		chan->memory = NULL;
14941da177e4SLinus Torvalds 	}
14951da177e4SLinus Torvalds 	return 0;
14961da177e4SLinus Torvalds }
14971da177e4SLinus Torvalds 
14981da177e4SLinus Torvalds 
14991da177e4SLinus Torvalds /*
15001da177e4SLinus Torvalds  * allocate APU pair
15011da177e4SLinus Torvalds  */
snd_es1968_alloc_apu_pair(struct es1968 * chip,int type)1502969165a8STakashi Iwai static int snd_es1968_alloc_apu_pair(struct es1968 *chip, int type)
15031da177e4SLinus Torvalds {
15041da177e4SLinus Torvalds 	int apu;
15051da177e4SLinus Torvalds 
15061da177e4SLinus Torvalds 	for (apu = 0; apu < NR_APUS; apu += 2) {
15071da177e4SLinus Torvalds 		if (chip->apu[apu] == ESM_APU_FREE &&
15081da177e4SLinus Torvalds 		    chip->apu[apu + 1] == ESM_APU_FREE) {
15091da177e4SLinus Torvalds 			chip->apu[apu] = chip->apu[apu + 1] = type;
15101da177e4SLinus Torvalds 			return apu;
15111da177e4SLinus Torvalds 		}
15121da177e4SLinus Torvalds 	}
15131da177e4SLinus Torvalds 	return -EBUSY;
15141da177e4SLinus Torvalds }
15151da177e4SLinus Torvalds 
15161da177e4SLinus Torvalds /*
15171da177e4SLinus Torvalds  * release APU pair
15181da177e4SLinus Torvalds  */
snd_es1968_free_apu_pair(struct es1968 * chip,int apu)1519969165a8STakashi Iwai static void snd_es1968_free_apu_pair(struct es1968 *chip, int apu)
15201da177e4SLinus Torvalds {
15211da177e4SLinus Torvalds 	chip->apu[apu] = chip->apu[apu + 1] = ESM_APU_FREE;
15221da177e4SLinus Torvalds }
15231da177e4SLinus Torvalds 
15241da177e4SLinus Torvalds 
15251da177e4SLinus Torvalds /******************
15261da177e4SLinus Torvalds  * PCM open/close *
15271da177e4SLinus Torvalds  ******************/
15281da177e4SLinus Torvalds 
snd_es1968_playback_open(struct snd_pcm_substream * substream)1529969165a8STakashi Iwai static int snd_es1968_playback_open(struct snd_pcm_substream *substream)
15301da177e4SLinus Torvalds {
1531969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1532969165a8STakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
1533969165a8STakashi Iwai 	struct esschan *es;
15341da177e4SLinus Torvalds 	int apu1;
15351da177e4SLinus Torvalds 
15361da177e4SLinus Torvalds 	/* search 2 APUs */
15371da177e4SLinus Torvalds 	apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY);
15381da177e4SLinus Torvalds 	if (apu1 < 0)
15391da177e4SLinus Torvalds 		return apu1;
15401da177e4SLinus Torvalds 
1541e560d8d8STakashi Iwai 	es = kzalloc(sizeof(*es), GFP_KERNEL);
15421da177e4SLinus Torvalds 	if (!es) {
15431da177e4SLinus Torvalds 		snd_es1968_free_apu_pair(chip, apu1);
15441da177e4SLinus Torvalds 		return -ENOMEM;
15451da177e4SLinus Torvalds 	}
15461da177e4SLinus Torvalds 
15471da177e4SLinus Torvalds 	es->apu[0] = apu1;
15481da177e4SLinus Torvalds 	es->apu[1] = apu1 + 1;
15491da177e4SLinus Torvalds 	es->apu_mode[0] = 0;
15501da177e4SLinus Torvalds 	es->apu_mode[1] = 0;
15511da177e4SLinus Torvalds 	es->running = 0;
15521da177e4SLinus Torvalds 	es->substream = substream;
15531da177e4SLinus Torvalds 	es->mode = ESM_MODE_PLAY;
15541da177e4SLinus Torvalds 
15551da177e4SLinus Torvalds 	runtime->private_data = es;
15561da177e4SLinus Torvalds 	runtime->hw = snd_es1968_playback;
15571da177e4SLinus Torvalds 	runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
15581da177e4SLinus Torvalds 		calc_available_memory_size(chip);
1559b942cf81SRene Herman 
15601da177e4SLinus Torvalds 	spin_lock_irq(&chip->substream_lock);
15611da177e4SLinus Torvalds 	list_add(&es->list, &chip->substream_list);
15621da177e4SLinus Torvalds 	spin_unlock_irq(&chip->substream_lock);
15631da177e4SLinus Torvalds 
15641da177e4SLinus Torvalds 	return 0;
15651da177e4SLinus Torvalds }
15661da177e4SLinus Torvalds 
snd_es1968_capture_open(struct snd_pcm_substream * substream)1567969165a8STakashi Iwai static int snd_es1968_capture_open(struct snd_pcm_substream *substream)
15681da177e4SLinus Torvalds {
1569969165a8STakashi Iwai 	struct snd_pcm_runtime *runtime = substream->runtime;
1570969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1571969165a8STakashi Iwai 	struct esschan *es;
15721da177e4SLinus Torvalds 	int apu1, apu2;
15731da177e4SLinus Torvalds 
15741da177e4SLinus Torvalds 	apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE);
15751da177e4SLinus Torvalds 	if (apu1 < 0)
15761da177e4SLinus Torvalds 		return apu1;
15771da177e4SLinus Torvalds 	apu2 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_RATECONV);
15781da177e4SLinus Torvalds 	if (apu2 < 0) {
15791da177e4SLinus Torvalds 		snd_es1968_free_apu_pair(chip, apu1);
15801da177e4SLinus Torvalds 		return apu2;
15811da177e4SLinus Torvalds 	}
15821da177e4SLinus Torvalds 
1583e560d8d8STakashi Iwai 	es = kzalloc(sizeof(*es), GFP_KERNEL);
15841da177e4SLinus Torvalds 	if (!es) {
15851da177e4SLinus Torvalds 		snd_es1968_free_apu_pair(chip, apu1);
15861da177e4SLinus Torvalds 		snd_es1968_free_apu_pair(chip, apu2);
15871da177e4SLinus Torvalds 		return -ENOMEM;
15881da177e4SLinus Torvalds 	}
15891da177e4SLinus Torvalds 
15901da177e4SLinus Torvalds 	es->apu[0] = apu1;
15911da177e4SLinus Torvalds 	es->apu[1] = apu1 + 1;
15921da177e4SLinus Torvalds 	es->apu[2] = apu2;
15931da177e4SLinus Torvalds 	es->apu[3] = apu2 + 1;
15941da177e4SLinus Torvalds 	es->apu_mode[0] = 0;
15951da177e4SLinus Torvalds 	es->apu_mode[1] = 0;
15961da177e4SLinus Torvalds 	es->apu_mode[2] = 0;
15971da177e4SLinus Torvalds 	es->apu_mode[3] = 0;
15981da177e4SLinus Torvalds 	es->running = 0;
15991da177e4SLinus Torvalds 	es->substream = substream;
16001da177e4SLinus Torvalds 	es->mode = ESM_MODE_CAPTURE;
16011da177e4SLinus Torvalds 
16021da177e4SLinus Torvalds 	/* get mixbuffer */
160348cab474STakashi Iwai 	es->mixbuf = snd_es1968_new_memory(chip, ESM_MIXBUF_SIZE);
160448cab474STakashi Iwai 	if (!es->mixbuf) {
16051da177e4SLinus Torvalds 		snd_es1968_free_apu_pair(chip, apu1);
16061da177e4SLinus Torvalds 		snd_es1968_free_apu_pair(chip, apu2);
16071da177e4SLinus Torvalds 		kfree(es);
16081da177e4SLinus Torvalds                 return -ENOMEM;
16091da177e4SLinus Torvalds         }
16101da177e4SLinus Torvalds 	memset(es->mixbuf->buf.area, 0, ESM_MIXBUF_SIZE);
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds 	runtime->private_data = es;
16131da177e4SLinus Torvalds 	runtime->hw = snd_es1968_capture;
16141da177e4SLinus Torvalds 	runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
16151da177e4SLinus Torvalds 		calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */
1616b942cf81SRene Herman 	snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
1617b942cf81SRene Herman 
16181da177e4SLinus Torvalds 	spin_lock_irq(&chip->substream_lock);
16191da177e4SLinus Torvalds 	list_add(&es->list, &chip->substream_list);
16201da177e4SLinus Torvalds 	spin_unlock_irq(&chip->substream_lock);
16211da177e4SLinus Torvalds 
16221da177e4SLinus Torvalds 	return 0;
16231da177e4SLinus Torvalds }
16241da177e4SLinus Torvalds 
snd_es1968_playback_close(struct snd_pcm_substream * substream)1625969165a8STakashi Iwai static int snd_es1968_playback_close(struct snd_pcm_substream *substream)
16261da177e4SLinus Torvalds {
1627969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1628969165a8STakashi Iwai 	struct esschan *es;
16291da177e4SLinus Torvalds 
16301da177e4SLinus Torvalds 	if (substream->runtime->private_data == NULL)
16311da177e4SLinus Torvalds 		return 0;
16321da177e4SLinus Torvalds 	es = substream->runtime->private_data;
16331da177e4SLinus Torvalds 	spin_lock_irq(&chip->substream_lock);
16341da177e4SLinus Torvalds 	list_del(&es->list);
16351da177e4SLinus Torvalds 	spin_unlock_irq(&chip->substream_lock);
16361da177e4SLinus Torvalds 	snd_es1968_free_apu_pair(chip, es->apu[0]);
16371da177e4SLinus Torvalds 	kfree(es);
16381da177e4SLinus Torvalds 
16391da177e4SLinus Torvalds 	return 0;
16401da177e4SLinus Torvalds }
16411da177e4SLinus Torvalds 
snd_es1968_capture_close(struct snd_pcm_substream * substream)1642969165a8STakashi Iwai static int snd_es1968_capture_close(struct snd_pcm_substream *substream)
16431da177e4SLinus Torvalds {
1644969165a8STakashi Iwai 	struct es1968 *chip = snd_pcm_substream_chip(substream);
1645969165a8STakashi Iwai 	struct esschan *es;
16461da177e4SLinus Torvalds 
16471da177e4SLinus Torvalds 	if (substream->runtime->private_data == NULL)
16481da177e4SLinus Torvalds 		return 0;
16491da177e4SLinus Torvalds 	es = substream->runtime->private_data;
16501da177e4SLinus Torvalds 	spin_lock_irq(&chip->substream_lock);
16511da177e4SLinus Torvalds 	list_del(&es->list);
16521da177e4SLinus Torvalds 	spin_unlock_irq(&chip->substream_lock);
16531da177e4SLinus Torvalds 	snd_es1968_free_memory(chip, es->mixbuf);
16541da177e4SLinus Torvalds 	snd_es1968_free_apu_pair(chip, es->apu[0]);
16551da177e4SLinus Torvalds 	snd_es1968_free_apu_pair(chip, es->apu[2]);
16561da177e4SLinus Torvalds 	kfree(es);
16571da177e4SLinus Torvalds 
16581da177e4SLinus Torvalds 	return 0;
16591da177e4SLinus Torvalds }
16601da177e4SLinus Torvalds 
16616769e988SJulia Lawall static const struct snd_pcm_ops snd_es1968_playback_ops = {
16621da177e4SLinus Torvalds 	.open =		snd_es1968_playback_open,
16631da177e4SLinus Torvalds 	.close =	snd_es1968_playback_close,
16641da177e4SLinus Torvalds 	.hw_params =	snd_es1968_hw_params,
16651da177e4SLinus Torvalds 	.hw_free =	snd_es1968_hw_free,
16661da177e4SLinus Torvalds 	.prepare =	snd_es1968_pcm_prepare,
16671da177e4SLinus Torvalds 	.trigger =	snd_es1968_pcm_trigger,
16681da177e4SLinus Torvalds 	.pointer =	snd_es1968_pcm_pointer,
16691da177e4SLinus Torvalds };
16701da177e4SLinus Torvalds 
16716769e988SJulia Lawall static const struct snd_pcm_ops snd_es1968_capture_ops = {
16721da177e4SLinus Torvalds 	.open =		snd_es1968_capture_open,
16731da177e4SLinus Torvalds 	.close =	snd_es1968_capture_close,
16741da177e4SLinus Torvalds 	.hw_params =	snd_es1968_hw_params,
16751da177e4SLinus Torvalds 	.hw_free =	snd_es1968_hw_free,
16761da177e4SLinus Torvalds 	.prepare =	snd_es1968_pcm_prepare,
16771da177e4SLinus Torvalds 	.trigger =	snd_es1968_pcm_trigger,
16781da177e4SLinus Torvalds 	.pointer =	snd_es1968_pcm_pointer,
16791da177e4SLinus Torvalds };
16801da177e4SLinus Torvalds 
16811da177e4SLinus Torvalds 
16821da177e4SLinus Torvalds /*
16831da177e4SLinus Torvalds  * measure clock
16841da177e4SLinus Torvalds  */
16851da177e4SLinus Torvalds #define CLOCK_MEASURE_BUFSIZE	16768	/* enough large for a single shot */
16861da177e4SLinus Torvalds 
es1968_measure_clock(struct es1968 * chip)1687e23e7a14SBill Pemberton static void es1968_measure_clock(struct es1968 *chip)
16881da177e4SLinus Torvalds {
16891da177e4SLinus Torvalds 	int i, apu;
16901da177e4SLinus Torvalds 	unsigned int pa, offset, t;
1691969165a8STakashi Iwai 	struct esm_memory *memory;
1692eafe8404STina Ruchandani 	ktime_t start_time, stop_time;
1693eafe8404STina Ruchandani 	ktime_t diff;
16941da177e4SLinus Torvalds 
16951da177e4SLinus Torvalds 	if (chip->clock == 0)
16961da177e4SLinus Torvalds 		chip->clock = 48000; /* default clock value */
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds 	/* search 2 APUs (although one apu is enough) */
169948cab474STakashi Iwai 	apu = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY);
170048cab474STakashi Iwai 	if (apu < 0) {
170186cd372fSTakashi Iwai 		dev_err(chip->card->dev, "Hmm, cannot find empty APU pair!?\n");
17021da177e4SLinus Torvalds 		return;
17031da177e4SLinus Torvalds 	}
170448cab474STakashi Iwai 	memory = snd_es1968_new_memory(chip, CLOCK_MEASURE_BUFSIZE);
170548cab474STakashi Iwai 	if (!memory) {
170686cd372fSTakashi Iwai 		dev_warn(chip->card->dev,
170786cd372fSTakashi Iwai 			 "cannot allocate dma buffer - using default clock %d\n",
170886cd372fSTakashi Iwai 			 chip->clock);
17091da177e4SLinus Torvalds 		snd_es1968_free_apu_pair(chip, apu);
17101da177e4SLinus Torvalds 		return;
17111da177e4SLinus Torvalds 	}
17121da177e4SLinus Torvalds 
17131da177e4SLinus Torvalds 	memset(memory->buf.area, 0, CLOCK_MEASURE_BUFSIZE);
17141da177e4SLinus Torvalds 
17151da177e4SLinus Torvalds 	wave_set_register(chip, apu << 3, (memory->buf.addr - 0x10) & 0xfff8);
17161da177e4SLinus Torvalds 
17171da177e4SLinus Torvalds 	pa = (unsigned int)((memory->buf.addr - chip->dma.addr) >> 1);
17181da177e4SLinus Torvalds 	pa |= 0x00400000;	/* System RAM (Bit 22) */
17191da177e4SLinus Torvalds 
17201da177e4SLinus Torvalds 	/* initialize apu */
17211da177e4SLinus Torvalds 	for (i = 0; i < 16; i++)
17221da177e4SLinus Torvalds 		apu_set_register(chip, apu, i, 0x0000);
17231da177e4SLinus Torvalds 
17241da177e4SLinus Torvalds 	apu_set_register(chip, apu, 0, 0x400f);
17251da177e4SLinus Torvalds 	apu_set_register(chip, apu, 4, ((pa >> 16) & 0xff) << 8);
17261da177e4SLinus Torvalds 	apu_set_register(chip, apu, 5, pa & 0xffff);
17271da177e4SLinus Torvalds 	apu_set_register(chip, apu, 6, (pa + CLOCK_MEASURE_BUFSIZE/2) & 0xffff);
17281da177e4SLinus Torvalds 	apu_set_register(chip, apu, 7, CLOCK_MEASURE_BUFSIZE/2);
17291da177e4SLinus Torvalds 	apu_set_register(chip, apu, 8, 0x0000);
17301da177e4SLinus Torvalds 	apu_set_register(chip, apu, 9, 0xD000);
17311da177e4SLinus Torvalds 	apu_set_register(chip, apu, 10, 0x8F08);
17321da177e4SLinus Torvalds 	apu_set_register(chip, apu, 11, 0x0000);
17331da177e4SLinus Torvalds 	spin_lock_irq(&chip->reg_lock);
17341da177e4SLinus Torvalds 	outw(1, chip->io_port + 0x04); /* clear WP interrupts */
17351da177e4SLinus Torvalds 	outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); /* enable WP ints */
17361da177e4SLinus Torvalds 	spin_unlock_irq(&chip->reg_lock);
17371da177e4SLinus Torvalds 
17381da177e4SLinus Torvalds 	snd_es1968_apu_set_freq(chip, apu, ((unsigned int)48000 << 16) / chip->clock); /* 48000 Hz */
17391da177e4SLinus Torvalds 
17401da177e4SLinus Torvalds 	chip->in_measurement = 1;
17411da177e4SLinus Torvalds 	chip->measure_apu = apu;
17421da177e4SLinus Torvalds 	spin_lock_irq(&chip->reg_lock);
17431da177e4SLinus Torvalds 	snd_es1968_bob_inc(chip, ESM_BOB_FREQ);
17441da177e4SLinus Torvalds 	__apu_set_register(chip, apu, 5, pa & 0xffff);
17451da177e4SLinus Torvalds 	snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR);
1746eafe8404STina Ruchandani 	start_time = ktime_get();
17471da177e4SLinus Torvalds 	spin_unlock_irq(&chip->reg_lock);
1748ef21ca24SNishanth Aravamudan 	msleep(50);
17491da177e4SLinus Torvalds 	spin_lock_irq(&chip->reg_lock);
17501da177e4SLinus Torvalds 	offset = __apu_get_register(chip, apu, 5);
1751eafe8404STina Ruchandani 	stop_time = ktime_get();
17521da177e4SLinus Torvalds 	snd_es1968_trigger_apu(chip, apu, 0); /* stop */
17531da177e4SLinus Torvalds 	snd_es1968_bob_dec(chip);
17541da177e4SLinus Torvalds 	chip->in_measurement = 0;
17551da177e4SLinus Torvalds 	spin_unlock_irq(&chip->reg_lock);
17561da177e4SLinus Torvalds 
17571da177e4SLinus Torvalds 	/* check the current position */
17581da177e4SLinus Torvalds 	offset -= (pa & 0xffff);
17591da177e4SLinus Torvalds 	offset &= 0xfffe;
17601da177e4SLinus Torvalds 	offset += chip->measure_count * (CLOCK_MEASURE_BUFSIZE/2);
17611da177e4SLinus Torvalds 
1762eafe8404STina Ruchandani 	diff = ktime_sub(stop_time, start_time);
1763eafe8404STina Ruchandani 	t = ktime_to_us(diff);
17641da177e4SLinus Torvalds 	if (t == 0) {
176586cd372fSTakashi Iwai 		dev_err(chip->card->dev, "?? calculation error..\n");
17661da177e4SLinus Torvalds 	} else {
17671da177e4SLinus Torvalds 		offset *= 1000;
17681da177e4SLinus Torvalds 		offset = (offset / t) * 1000 + ((offset % t) * 1000) / t;
17691da177e4SLinus Torvalds 		if (offset < 47500 || offset > 48500) {
17701da177e4SLinus Torvalds 			if (offset >= 40000 && offset <= 50000)
17711da177e4SLinus Torvalds 				chip->clock = (chip->clock * offset) / 48000;
17721da177e4SLinus Torvalds 		}
177386cd372fSTakashi Iwai 		dev_info(chip->card->dev, "clocking to %d\n", chip->clock);
17741da177e4SLinus Torvalds 	}
17751da177e4SLinus Torvalds 	snd_es1968_free_memory(chip, memory);
17761da177e4SLinus Torvalds 	snd_es1968_free_apu_pair(chip, apu);
17771da177e4SLinus Torvalds }
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 
17801da177e4SLinus Torvalds /*
17811da177e4SLinus Torvalds  */
17821da177e4SLinus Torvalds 
snd_es1968_pcm_free(struct snd_pcm * pcm)1783969165a8STakashi Iwai static void snd_es1968_pcm_free(struct snd_pcm *pcm)
17841da177e4SLinus Torvalds {
1785969165a8STakashi Iwai 	struct es1968 *esm = pcm->private_data;
17861da177e4SLinus Torvalds 	snd_es1968_free_dmabuf(esm);
17871da177e4SLinus Torvalds 	esm->pcm = NULL;
17881da177e4SLinus Torvalds }
17891da177e4SLinus Torvalds 
1790e23e7a14SBill Pemberton static int
snd_es1968_pcm(struct es1968 * chip,int device)1791969165a8STakashi Iwai snd_es1968_pcm(struct es1968 *chip, int device)
17921da177e4SLinus Torvalds {
1793969165a8STakashi Iwai 	struct snd_pcm *pcm;
17941da177e4SLinus Torvalds 	int err;
17951da177e4SLinus Torvalds 
17961da177e4SLinus Torvalds 	/* get DMA buffer */
179748cab474STakashi Iwai 	err = snd_es1968_init_dmabuf(chip);
179848cab474STakashi Iwai 	if (err < 0)
17991da177e4SLinus Torvalds 		return err;
18001da177e4SLinus Torvalds 
18011da177e4SLinus Torvalds 	/* set PCMBAR */
18021da177e4SLinus Torvalds 	wave_set_register(chip, 0x01FC, chip->dma.addr >> 12);
18031da177e4SLinus Torvalds 	wave_set_register(chip, 0x01FD, chip->dma.addr >> 12);
18041da177e4SLinus Torvalds 	wave_set_register(chip, 0x01FE, chip->dma.addr >> 12);
18051da177e4SLinus Torvalds 	wave_set_register(chip, 0x01FF, chip->dma.addr >> 12);
18061da177e4SLinus Torvalds 
180748cab474STakashi Iwai 	err = snd_pcm_new(chip->card, "ESS Maestro", device,
18081da177e4SLinus Torvalds 			  chip->playback_streams,
180948cab474STakashi Iwai 			  chip->capture_streams, &pcm);
181048cab474STakashi Iwai 	if (err < 0)
18111da177e4SLinus Torvalds 		return err;
18121da177e4SLinus Torvalds 
18131da177e4SLinus Torvalds 	pcm->private_data = chip;
18141da177e4SLinus Torvalds 	pcm->private_free = snd_es1968_pcm_free;
18151da177e4SLinus Torvalds 
18161da177e4SLinus Torvalds 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1968_playback_ops);
18171da177e4SLinus Torvalds 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1968_capture_ops);
18181da177e4SLinus Torvalds 
18191da177e4SLinus Torvalds 	pcm->info_flags = 0;
18201da177e4SLinus Torvalds 
18211da177e4SLinus Torvalds 	strcpy(pcm->name, "ESS Maestro");
18221da177e4SLinus Torvalds 
18231da177e4SLinus Torvalds 	chip->pcm = pcm;
18241da177e4SLinus Torvalds 
18251da177e4SLinus Torvalds 	return 0;
18261da177e4SLinus Torvalds }
1827f24bfa53SAndreas Mueller /*
1828f24bfa53SAndreas Mueller  * suppress jitter on some maestros when playing stereo
1829f24bfa53SAndreas Mueller  */
snd_es1968_suppress_jitter(struct es1968 * chip,struct esschan * es)1830f24bfa53SAndreas Mueller static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es)
1831f24bfa53SAndreas Mueller {
1832f24bfa53SAndreas Mueller 	unsigned int cp1;
1833f24bfa53SAndreas Mueller 	unsigned int cp2;
1834f24bfa53SAndreas Mueller 	unsigned int diff;
1835f24bfa53SAndreas Mueller 
1836f24bfa53SAndreas Mueller 	cp1 = __apu_get_register(chip, 0, 5);
1837f24bfa53SAndreas Mueller 	cp2 = __apu_get_register(chip, 1, 5);
1838f24bfa53SAndreas Mueller 	diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
1839f24bfa53SAndreas Mueller 
184066c9aa60SAndrew Morton 	if (diff > 1)
1841f24bfa53SAndreas Mueller 		__maestro_write(chip, IDR0_DATA_PORT, cp1);
1842f24bfa53SAndreas Mueller }
18431da177e4SLinus Torvalds 
18441da177e4SLinus Torvalds /*
18451da177e4SLinus Torvalds  * update pointer
18461da177e4SLinus Torvalds  */
snd_es1968_update_pcm(struct es1968 * chip,struct esschan * es)1847969165a8STakashi Iwai static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es)
18481da177e4SLinus Torvalds {
18491da177e4SLinus Torvalds 	unsigned int hwptr;
18501da177e4SLinus Torvalds 	unsigned int diff;
1851969165a8STakashi Iwai 	struct snd_pcm_substream *subs = es->substream;
18521da177e4SLinus Torvalds 
18531da177e4SLinus Torvalds 	if (subs == NULL || !es->running)
18541da177e4SLinus Torvalds 		return;
18551da177e4SLinus Torvalds 
18561da177e4SLinus Torvalds 	hwptr = snd_es1968_get_dma_ptr(chip, es) << es->wav_shift;
18571da177e4SLinus Torvalds 	hwptr %= es->dma_size;
18581da177e4SLinus Torvalds 
18591da177e4SLinus Torvalds 	diff = (es->dma_size + hwptr - es->hwptr) % es->dma_size;
18601da177e4SLinus Torvalds 
18611da177e4SLinus Torvalds 	es->hwptr = hwptr;
18621da177e4SLinus Torvalds 	es->count += diff;
18631da177e4SLinus Torvalds 
18641da177e4SLinus Torvalds 	if (es->count > es->frag_size) {
18651da177e4SLinus Torvalds 		spin_unlock(&chip->substream_lock);
18661da177e4SLinus Torvalds 		snd_pcm_period_elapsed(subs);
18671da177e4SLinus Torvalds 		spin_lock(&chip->substream_lock);
18681da177e4SLinus Torvalds 		es->count %= es->frag_size;
18691da177e4SLinus Torvalds 	}
18701da177e4SLinus Torvalds }
18711da177e4SLinus Torvalds 
18725a5e02e5SHans de Goede /* The hardware volume works by incrementing / decrementing 2 counters
18735a5e02e5SHans de Goede    (without wrap around) in response to volume button presses and then
18745a5e02e5SHans de Goede    generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
18755a5e02e5SHans de Goede    of a byte wide register. The meaning of bits 0 and 4 is unknown. */
es1968_update_hw_volume(struct work_struct * work)187630bdee02STakashi Iwai static void es1968_update_hw_volume(struct work_struct *work)
18771da177e4SLinus Torvalds {
187830bdee02STakashi Iwai 	struct es1968 *chip = container_of(work, struct es1968, hwvol_work);
18791da177e4SLinus Torvalds 	int x, val;
18801da177e4SLinus Torvalds 
18811da177e4SLinus Torvalds 	/* Figure out which volume control button was pushed,
18821da177e4SLinus Torvalds 	   based on differences from the default register
18831da177e4SLinus Torvalds 	   values. */
1884679e28eeSVille Syrjala 	x = inb(chip->io_port + 0x1c) & 0xee;
18851da177e4SLinus Torvalds 	/* Reset the volume control registers. */
18861da177e4SLinus Torvalds 	outb(0x88, chip->io_port + 0x1c);
18871da177e4SLinus Torvalds 	outb(0x88, chip->io_port + 0x1d);
18881da177e4SLinus Torvalds 	outb(0x88, chip->io_port + 0x1e);
18891da177e4SLinus Torvalds 	outb(0x88, chip->io_port + 0x1f);
18901da177e4SLinus Torvalds 
18911da177e4SLinus Torvalds 	if (chip->in_suspend)
18921da177e4SLinus Torvalds 		return;
18931da177e4SLinus Torvalds 
18945a5e02e5SHans de Goede #ifndef CONFIG_SND_ES1968_INPUT
18951da177e4SLinus Torvalds 	if (! chip->master_switch || ! chip->master_volume)
18961da177e4SLinus Torvalds 		return;
18971da177e4SLinus Torvalds 
189830bdee02STakashi Iwai 	val = snd_ac97_read(chip->ac97, AC97_MASTER);
1899679e28eeSVille Syrjala 	switch (x) {
1900679e28eeSVille Syrjala 	case 0x88:
19011da177e4SLinus Torvalds 		/* mute */
19021da177e4SLinus Torvalds 		val ^= 0x8000;
1903679e28eeSVille Syrjala 		break;
1904679e28eeSVille Syrjala 	case 0xaa:
19051da177e4SLinus Torvalds 		/* volume up */
1906679e28eeSVille Syrjala 		if ((val & 0x7f) > 0)
19071da177e4SLinus Torvalds 			val--;
1908679e28eeSVille Syrjala 		if ((val & 0x7f00) > 0)
19091da177e4SLinus Torvalds 			val -= 0x0100;
1910679e28eeSVille Syrjala 		break;
1911679e28eeSVille Syrjala 	case 0x66:
1912679e28eeSVille Syrjala 		/* volume down */
1913679e28eeSVille Syrjala 		if ((val & 0x7f) < 0x1f)
1914679e28eeSVille Syrjala 			val++;
1915679e28eeSVille Syrjala 		if ((val & 0x7f00) < 0x1f00)
1916679e28eeSVille Syrjala 			val += 0x0100;
1917679e28eeSVille Syrjala 		break;
19181da177e4SLinus Torvalds 	}
191930bdee02STakashi Iwai 	if (snd_ac97_update(chip->ac97, AC97_MASTER, val))
192030bdee02STakashi Iwai 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
192130bdee02STakashi Iwai 			       &chip->master_volume->id);
19225a5e02e5SHans de Goede #else
19235a5e02e5SHans de Goede 	if (!chip->input_dev)
19245a5e02e5SHans de Goede 		return;
19255a5e02e5SHans de Goede 
19265a5e02e5SHans de Goede 	val = 0;
19275a5e02e5SHans de Goede 	switch (x) {
19285a5e02e5SHans de Goede 	case 0x88:
19295a5e02e5SHans de Goede 		/* The counters have not changed, yet we've received a HV
19305a5e02e5SHans de Goede 		   interrupt. According to tests run by various people this
19315a5e02e5SHans de Goede 		   happens when pressing the mute button. */
19325a5e02e5SHans de Goede 		val = KEY_MUTE;
19335a5e02e5SHans de Goede 		break;
19345a5e02e5SHans de Goede 	case 0xaa:
19355a5e02e5SHans de Goede 		/* counters increased by 1 -> volume up */
19365a5e02e5SHans de Goede 		val = KEY_VOLUMEUP;
19375a5e02e5SHans de Goede 		break;
19385a5e02e5SHans de Goede 	case 0x66:
19395a5e02e5SHans de Goede 		/* counters decreased by 1 -> volume down */
19405a5e02e5SHans de Goede 		val = KEY_VOLUMEDOWN;
19415a5e02e5SHans de Goede 		break;
19425a5e02e5SHans de Goede 	}
19435a5e02e5SHans de Goede 
19445a5e02e5SHans de Goede 	if (val) {
19455a5e02e5SHans de Goede 		input_report_key(chip->input_dev, val, 1);
19465a5e02e5SHans de Goede 		input_sync(chip->input_dev);
19475a5e02e5SHans de Goede 		input_report_key(chip->input_dev, val, 0);
19485a5e02e5SHans de Goede 		input_sync(chip->input_dev);
19495a5e02e5SHans de Goede 	}
19505a5e02e5SHans de Goede #endif
19511da177e4SLinus Torvalds }
19521da177e4SLinus Torvalds 
19531da177e4SLinus Torvalds /*
19541da177e4SLinus Torvalds  * interrupt handler
19551da177e4SLinus Torvalds  */
snd_es1968_interrupt(int irq,void * dev_id)19567d12e780SDavid Howells static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
19571da177e4SLinus Torvalds {
1958969165a8STakashi Iwai 	struct es1968 *chip = dev_id;
19591da177e4SLinus Torvalds 	u32 event;
19601da177e4SLinus Torvalds 
196148cab474STakashi Iwai 	event = inb(chip->io_port + 0x1A);
196248cab474STakashi Iwai 	if (!event)
19631da177e4SLinus Torvalds 		return IRQ_NONE;
19641da177e4SLinus Torvalds 
19651da177e4SLinus Torvalds 	outw(inw(chip->io_port + 4) & 1, chip->io_port + 4);
19661da177e4SLinus Torvalds 
19671da177e4SLinus Torvalds 	if (event & ESM_HWVOL_IRQ)
196830bdee02STakashi Iwai 		schedule_work(&chip->hwvol_work);
19691da177e4SLinus Torvalds 
19701da177e4SLinus Torvalds 	/* else ack 'em all, i imagine */
19711da177e4SLinus Torvalds 	outb(0xFF, chip->io_port + 0x1A);
19721da177e4SLinus Torvalds 
19731da177e4SLinus Torvalds 	if ((event & ESM_MPU401_IRQ) && chip->rmidi) {
19747d12e780SDavid Howells 		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
19751da177e4SLinus Torvalds 	}
19761da177e4SLinus Torvalds 
19771da177e4SLinus Torvalds 	if (event & ESM_SOUND_IRQ) {
197850f47ff1SMatthias Kaehlcke 		struct esschan *es;
19791da177e4SLinus Torvalds 		spin_lock(&chip->substream_lock);
198050f47ff1SMatthias Kaehlcke 		list_for_each_entry(es, &chip->substream_list, list) {
1981f24bfa53SAndreas Mueller 			if (es->running) {
19821da177e4SLinus Torvalds 				snd_es1968_update_pcm(chip, es);
1983f24bfa53SAndreas Mueller 				if (es->fmt & ESS_FMT_STEREO)
1984f24bfa53SAndreas Mueller 					snd_es1968_suppress_jitter(chip, es);
1985f24bfa53SAndreas Mueller 			}
19861da177e4SLinus Torvalds 		}
19871da177e4SLinus Torvalds 		spin_unlock(&chip->substream_lock);
19881da177e4SLinus Torvalds 		if (chip->in_measurement) {
19891da177e4SLinus Torvalds 			unsigned int curp = __apu_get_register(chip, chip->measure_apu, 5);
19901da177e4SLinus Torvalds 			if (curp < chip->measure_lastpos)
19911da177e4SLinus Torvalds 				chip->measure_count++;
19921da177e4SLinus Torvalds 			chip->measure_lastpos = curp;
19931da177e4SLinus Torvalds 		}
19941da177e4SLinus Torvalds 	}
19951da177e4SLinus Torvalds 
19961da177e4SLinus Torvalds 	return IRQ_HANDLED;
19971da177e4SLinus Torvalds }
19981da177e4SLinus Torvalds 
19991da177e4SLinus Torvalds /*
20001da177e4SLinus Torvalds  *  Mixer stuff
20011da177e4SLinus Torvalds  */
20021da177e4SLinus Torvalds 
2003e23e7a14SBill Pemberton static int
snd_es1968_mixer(struct es1968 * chip)2004969165a8STakashi Iwai snd_es1968_mixer(struct es1968 *chip)
20051da177e4SLinus Torvalds {
2006969165a8STakashi Iwai 	struct snd_ac97_bus *pbus;
2007969165a8STakashi Iwai 	struct snd_ac97_template ac97;
20081da177e4SLinus Torvalds 	int err;
200951055da5STakashi Iwai 	static const struct snd_ac97_bus_ops ops = {
20101da177e4SLinus Torvalds 		.write = snd_es1968_ac97_write,
20111da177e4SLinus Torvalds 		.read = snd_es1968_ac97_read,
20121da177e4SLinus Torvalds 	};
20131da177e4SLinus Torvalds 
201448cab474STakashi Iwai 	err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus);
201548cab474STakashi Iwai 	if (err < 0)
20161da177e4SLinus Torvalds 		return err;
20171da177e4SLinus Torvalds 	pbus->no_vra = 1; /* ES1968 doesn't need VRA */
20181da177e4SLinus Torvalds 
20191da177e4SLinus Torvalds 	memset(&ac97, 0, sizeof(ac97));
20201da177e4SLinus Torvalds 	ac97.private_data = chip;
202148cab474STakashi Iwai 	err = snd_ac97_mixer(pbus, &ac97, &chip->ac97);
202248cab474STakashi Iwai 	if (err < 0)
20231da177e4SLinus Torvalds 		return err;
20241da177e4SLinus Torvalds 
20255a5e02e5SHans de Goede #ifndef CONFIG_SND_ES1968_INPUT
20261da177e4SLinus Torvalds 	/* attach master switch / volumes for h/w volume control */
2027*5f2a937bSTakashi Iwai 	chip->master_switch = snd_ctl_find_id_mixer(chip->card,
2028*5f2a937bSTakashi Iwai 						    "Master Playback Switch");
2029*5f2a937bSTakashi Iwai 	chip->master_volume = snd_ctl_find_id_mixer(chip->card,
2030*5f2a937bSTakashi Iwai 						    "Master Playback Volume");
20315a5e02e5SHans de Goede #endif
20321da177e4SLinus Torvalds 
20331da177e4SLinus Torvalds 	return 0;
20341da177e4SLinus Torvalds }
20351da177e4SLinus Torvalds 
20361da177e4SLinus Torvalds /*
20371da177e4SLinus Torvalds  * reset ac97 codec
20381da177e4SLinus Torvalds  */
20391da177e4SLinus Torvalds 
snd_es1968_ac97_reset(struct es1968 * chip)2040969165a8STakashi Iwai static void snd_es1968_ac97_reset(struct es1968 *chip)
20411da177e4SLinus Torvalds {
20421da177e4SLinus Torvalds 	unsigned long ioaddr = chip->io_port;
20431da177e4SLinus Torvalds 
20441da177e4SLinus Torvalds 	unsigned short save_ringbus_a;
20451da177e4SLinus Torvalds 	unsigned short save_68;
20461da177e4SLinus Torvalds 	unsigned short w;
20471da177e4SLinus Torvalds 	unsigned int vend;
20481da177e4SLinus Torvalds 
20491da177e4SLinus Torvalds 	/* save configuration */
20501da177e4SLinus Torvalds 	save_ringbus_a = inw(ioaddr + 0x36);
20511da177e4SLinus Torvalds 
20521da177e4SLinus Torvalds 	//outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); /* clear second codec id? */
20531da177e4SLinus Torvalds 	/* set command/status address i/o to 1st codec */
20541da177e4SLinus Torvalds 	outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a);
20551da177e4SLinus Torvalds 	outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c);
20561da177e4SLinus Torvalds 
20571da177e4SLinus Torvalds 	/* disable ac link */
20581da177e4SLinus Torvalds 	outw(0x0000, ioaddr + 0x36);
20591da177e4SLinus Torvalds 	save_68 = inw(ioaddr + 0x68);
20601da177e4SLinus Torvalds 	pci_read_config_word(chip->pci, 0x58, &w);	/* something magical with gpio and bus arb. */
20611da177e4SLinus Torvalds 	pci_read_config_dword(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend);
20621da177e4SLinus Torvalds 	if (w & 1)
20631da177e4SLinus Torvalds 		save_68 |= 0x10;
20641da177e4SLinus Torvalds 	outw(0xfffe, ioaddr + 0x64);	/* unmask gpio 0 */
20651da177e4SLinus Torvalds 	outw(0x0001, ioaddr + 0x68);	/* gpio write */
20661da177e4SLinus Torvalds 	outw(0x0000, ioaddr + 0x60);	/* write 0 to gpio 0 */
20671da177e4SLinus Torvalds 	udelay(20);
20681da177e4SLinus Torvalds 	outw(0x0001, ioaddr + 0x60);	/* write 1 to gpio 1 */
2069ef21ca24SNishanth Aravamudan 	msleep(20);
20701da177e4SLinus Torvalds 
20711da177e4SLinus Torvalds 	outw(save_68 | 0x1, ioaddr + 0x68);	/* now restore .. */
20721da177e4SLinus Torvalds 	outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38);
20731da177e4SLinus Torvalds 	outw((inw(ioaddr + 0x3a) & 0xfffc) | 0x1, ioaddr + 0x3a);
20741da177e4SLinus Torvalds 	outw((inw(ioaddr + 0x3c) & 0xfffc) | 0x1, ioaddr + 0x3c);
20751da177e4SLinus Torvalds 
20761da177e4SLinus Torvalds 	/* now the second codec */
20771da177e4SLinus Torvalds 	/* disable ac link */
20781da177e4SLinus Torvalds 	outw(0x0000, ioaddr + 0x36);
20791da177e4SLinus Torvalds 	outw(0xfff7, ioaddr + 0x64);	/* unmask gpio 3 */
20801da177e4SLinus Torvalds 	save_68 = inw(ioaddr + 0x68);
20811da177e4SLinus Torvalds 	outw(0x0009, ioaddr + 0x68);	/* gpio write 0 & 3 ?? */
20821da177e4SLinus Torvalds 	outw(0x0001, ioaddr + 0x60);	/* write 1 to gpio */
20831da177e4SLinus Torvalds 	udelay(20);
20841da177e4SLinus Torvalds 	outw(0x0009, ioaddr + 0x60);	/* write 9 to gpio */
2085ef21ca24SNishanth Aravamudan 	msleep(500);
20861da177e4SLinus Torvalds 	//outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38);
20871da177e4SLinus Torvalds 	outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a);
20881da177e4SLinus Torvalds 	outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c);
20891da177e4SLinus Torvalds 
20901da177e4SLinus Torvalds #if 0				/* the loop here needs to be much better if we want it.. */
209186cd372fSTakashi Iwai 	dev_info(chip->card->dev, "trying software reset\n");
20921da177e4SLinus Torvalds 	/* try and do a software reset */
20931da177e4SLinus Torvalds 	outb(0x80 | 0x7c, ioaddr + 0x30);
20941da177e4SLinus Torvalds 	for (w = 0;; w++) {
20951da177e4SLinus Torvalds 		if ((inw(ioaddr + 0x30) & 1) == 0) {
20961da177e4SLinus Torvalds 			if (inb(ioaddr + 0x32) != 0)
20971da177e4SLinus Torvalds 				break;
20981da177e4SLinus Torvalds 
20991da177e4SLinus Torvalds 			outb(0x80 | 0x7d, ioaddr + 0x30);
21001da177e4SLinus Torvalds 			if (((inw(ioaddr + 0x30) & 1) == 0)
21011da177e4SLinus Torvalds 			    && (inb(ioaddr + 0x32) != 0))
21021da177e4SLinus Torvalds 				break;
21031da177e4SLinus Torvalds 			outb(0x80 | 0x7f, ioaddr + 0x30);
21041da177e4SLinus Torvalds 			if (((inw(ioaddr + 0x30) & 1) == 0)
21051da177e4SLinus Torvalds 			    && (inb(ioaddr + 0x32) != 0))
21061da177e4SLinus Torvalds 				break;
21071da177e4SLinus Torvalds 		}
21081da177e4SLinus Torvalds 
21091da177e4SLinus Torvalds 		if (w > 10000) {
21101da177e4SLinus Torvalds 			outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37);	/* do a software reset */
2111ef21ca24SNishanth Aravamudan 			msleep(500);	/* oh my.. */
21121da177e4SLinus Torvalds 			outb(inb(ioaddr + 0x37) & ~0x08,
21131da177e4SLinus Torvalds 				ioaddr + 0x37);
21141da177e4SLinus Torvalds 			udelay(1);
21151da177e4SLinus Torvalds 			outw(0x80, ioaddr + 0x30);
21161da177e4SLinus Torvalds 			for (w = 0; w < 10000; w++) {
21171da177e4SLinus Torvalds 				if ((inw(ioaddr + 0x30) & 1) == 0)
21181da177e4SLinus Torvalds 					break;
21191da177e4SLinus Torvalds 			}
21201da177e4SLinus Torvalds 		}
21211da177e4SLinus Torvalds 	}
21221da177e4SLinus Torvalds #endif
21231da177e4SLinus Torvalds 	if (vend == NEC_VERSA_SUBID1 || vend == NEC_VERSA_SUBID2) {
21241da177e4SLinus Torvalds 		/* turn on external amp? */
21251da177e4SLinus Torvalds 		outw(0xf9ff, ioaddr + 0x64);
21261da177e4SLinus Torvalds 		outw(inw(ioaddr + 0x68) | 0x600, ioaddr + 0x68);
21271da177e4SLinus Torvalds 		outw(0x0209, ioaddr + 0x60);
21281da177e4SLinus Torvalds 	}
21291da177e4SLinus Torvalds 
21301da177e4SLinus Torvalds 	/* restore.. */
21311da177e4SLinus Torvalds 	outw(save_ringbus_a, ioaddr + 0x36);
21321da177e4SLinus Torvalds 
21331da177e4SLinus Torvalds 	/* Turn on the 978 docking chip.
21341da177e4SLinus Torvalds 	   First frob the "master output enable" bit,
21351da177e4SLinus Torvalds 	   then set most of the playback volume control registers to max. */
21361da177e4SLinus Torvalds 	outb(inb(ioaddr+0xc0)|(1<<5), ioaddr+0xc0);
21371da177e4SLinus Torvalds 	outb(0xff, ioaddr+0xc3);
21381da177e4SLinus Torvalds 	outb(0xff, ioaddr+0xc4);
21391da177e4SLinus Torvalds 	outb(0xff, ioaddr+0xc6);
21401da177e4SLinus Torvalds 	outb(0xff, ioaddr+0xc8);
21411da177e4SLinus Torvalds 	outb(0x3f, ioaddr+0xcf);
21421da177e4SLinus Torvalds 	outb(0x3f, ioaddr+0xd0);
21431da177e4SLinus Torvalds }
21441da177e4SLinus Torvalds 
snd_es1968_reset(struct es1968 * chip)2145969165a8STakashi Iwai static void snd_es1968_reset(struct es1968 *chip)
21461da177e4SLinus Torvalds {
21471da177e4SLinus Torvalds 	/* Reset */
21481da177e4SLinus Torvalds 	outw(ESM_RESET_MAESTRO | ESM_RESET_DIRECTSOUND,
21491da177e4SLinus Torvalds 	     chip->io_port + ESM_PORT_HOST_IRQ);
21501da177e4SLinus Torvalds 	udelay(10);
21511da177e4SLinus Torvalds 	outw(0x0000, chip->io_port + ESM_PORT_HOST_IRQ);
21521da177e4SLinus Torvalds 	udelay(10);
21531da177e4SLinus Torvalds }
21541da177e4SLinus Torvalds 
21551da177e4SLinus Torvalds /*
21561da177e4SLinus Torvalds  * initialize maestro chip
21571da177e4SLinus Torvalds  */
snd_es1968_chip_init(struct es1968 * chip)2158969165a8STakashi Iwai static void snd_es1968_chip_init(struct es1968 *chip)
21591da177e4SLinus Torvalds {
21601da177e4SLinus Torvalds 	struct pci_dev *pci = chip->pci;
21611da177e4SLinus Torvalds 	int i;
21621da177e4SLinus Torvalds 	unsigned long iobase  = chip->io_port;
21631da177e4SLinus Torvalds 	u16 w;
21641da177e4SLinus Torvalds 	u32 n;
21651da177e4SLinus Torvalds 
21661da177e4SLinus Torvalds 	/* We used to muck around with pci config space that
21671da177e4SLinus Torvalds 	 * we had no business messing with.  We don't know enough
21681da177e4SLinus Torvalds 	 * about the machine to know which DMA mode is appropriate,
21691da177e4SLinus Torvalds 	 * etc.  We were guessing wrong on some machines and making
21701da177e4SLinus Torvalds 	 * them unhappy.  We now trust in the BIOS to do things right,
21711da177e4SLinus Torvalds 	 * which almost certainly means a new host of problems will
21721da177e4SLinus Torvalds 	 * arise with broken BIOS implementations.  screw 'em.
21731da177e4SLinus Torvalds 	 * We're already intolerant of machines that don't assign
21741da177e4SLinus Torvalds 	 * IRQs.
21751da177e4SLinus Torvalds 	 */
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds 	/* Config Reg A */
21781da177e4SLinus Torvalds 	pci_read_config_word(pci, ESM_CONFIG_A, &w);
21791da177e4SLinus Torvalds 
21801da177e4SLinus Torvalds 	w &= ~DMA_CLEAR;	/* Clear DMA bits */
21811da177e4SLinus Torvalds 	w &= ~(PIC_SNOOP1 | PIC_SNOOP2);	/* Clear Pic Snoop Mode Bits */
21821da177e4SLinus Torvalds 	w &= ~SAFEGUARD;	/* Safeguard off */
21831da177e4SLinus Torvalds 	w |= POST_WRITE;	/* Posted write */
2184607da7f8SRene Herman 	w |= PCI_TIMING;	/* PCI timing on */
21851da177e4SLinus Torvalds 	/* XXX huh?  claims to be reserved.. */
21861da177e4SLinus Torvalds 	w &= ~SWAP_LR;		/* swap left/right
21871da177e4SLinus Torvalds 				   seems to only have effect on SB
21881da177e4SLinus Torvalds 				   Emulation */
21891da177e4SLinus Torvalds 	w &= ~SUBTR_DECODE;	/* Subtractive decode off */
21901da177e4SLinus Torvalds 
21911da177e4SLinus Torvalds 	pci_write_config_word(pci, ESM_CONFIG_A, w);
21921da177e4SLinus Torvalds 
21931da177e4SLinus Torvalds 	/* Config Reg B */
21941da177e4SLinus Torvalds 
21951da177e4SLinus Torvalds 	pci_read_config_word(pci, ESM_CONFIG_B, &w);
21961da177e4SLinus Torvalds 
21971da177e4SLinus Torvalds 	w &= ~(1 << 15);	/* Turn off internal clock multiplier */
21981da177e4SLinus Torvalds 	/* XXX how do we know which to use? */
21991da177e4SLinus Torvalds 	w &= ~(1 << 14);	/* External clock */
22001da177e4SLinus Torvalds 
22011da177e4SLinus Torvalds 	w &= ~SPDIF_CONFB;	/* disable S/PDIF output */
22021da177e4SLinus Torvalds 	w |= HWV_CONFB;		/* HWV on */
22031da177e4SLinus Torvalds 	w |= DEBOUNCE;		/* Debounce off: easier to push the HW buttons */
22041da177e4SLinus Torvalds 	w &= ~GPIO_CONFB;	/* GPIO 4:5 */
22051da177e4SLinus Torvalds 	w |= CHI_CONFB;		/* Disconnect from the CHI.  Enabling this made a dell 7500 work. */
22061da177e4SLinus Torvalds 	w &= ~IDMA_CONFB;	/* IDMA off (undocumented) */
22071da177e4SLinus Torvalds 	w &= ~MIDI_FIX;		/* MIDI fix off (undoc) */
22081da177e4SLinus Torvalds 	w &= ~(1 << 1);		/* reserved, always write 0 */
22091da177e4SLinus Torvalds 	w &= ~IRQ_TO_ISA;	/* IRQ to ISA off (undoc) */
22101da177e4SLinus Torvalds 
22111da177e4SLinus Torvalds 	pci_write_config_word(pci, ESM_CONFIG_B, w);
22121da177e4SLinus Torvalds 
22131da177e4SLinus Torvalds 	/* DDMA off */
22141da177e4SLinus Torvalds 
22151da177e4SLinus Torvalds 	pci_read_config_word(pci, ESM_DDMA, &w);
22161da177e4SLinus Torvalds 	w &= ~(1 << 0);
22171da177e4SLinus Torvalds 	pci_write_config_word(pci, ESM_DDMA, w);
22181da177e4SLinus Torvalds 
22191da177e4SLinus Torvalds 	/*
22201da177e4SLinus Torvalds 	 *	Legacy mode
22211da177e4SLinus Torvalds 	 */
22221da177e4SLinus Torvalds 
22231da177e4SLinus Torvalds 	pci_read_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, &w);
22241da177e4SLinus Torvalds 
2225607da7f8SRene Herman 	w |= ESS_DISABLE_AUDIO;	/* Disable Legacy Audio */
22261da177e4SLinus Torvalds 	w &= ~ESS_ENABLE_SERIAL_IRQ;	/* Disable SIRQ */
22271da177e4SLinus Torvalds 	w &= ~(0x1f);		/* disable mpu irq/io, game port, fm, SB */
22281da177e4SLinus Torvalds 
22291da177e4SLinus Torvalds 	pci_write_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, w);
22301da177e4SLinus Torvalds 
22311da177e4SLinus Torvalds 	/* Set up 978 docking control chip. */
22321da177e4SLinus Torvalds 	pci_read_config_word(pci, 0x58, &w);
22331da177e4SLinus Torvalds 	w|=1<<2;	/* Enable 978. */
22341da177e4SLinus Torvalds 	w|=1<<3;	/* Turn on 978 hardware volume control. */
22351da177e4SLinus Torvalds 	w&=~(1<<11);	/* Turn on 978 mixer volume control. */
22361da177e4SLinus Torvalds 	pci_write_config_word(pci, 0x58, w);
22371da177e4SLinus Torvalds 
22381da177e4SLinus Torvalds 	/* Sound Reset */
22391da177e4SLinus Torvalds 
22401da177e4SLinus Torvalds 	snd_es1968_reset(chip);
22411da177e4SLinus Torvalds 
22421da177e4SLinus Torvalds 	/*
22431da177e4SLinus Torvalds 	 *	Ring Bus Setup
22441da177e4SLinus Torvalds 	 */
22451da177e4SLinus Torvalds 
22461da177e4SLinus Torvalds 	/* setup usual 0x34 stuff.. 0x36 may be chip specific */
22471da177e4SLinus Torvalds 	outw(0xC090, iobase + ESM_RING_BUS_DEST); /* direct sound, stereo */
22481da177e4SLinus Torvalds 	udelay(20);
22491da177e4SLinus Torvalds 	outw(0x3000, iobase + ESM_RING_BUS_CONTR_A); /* enable ringbus/serial */
22501da177e4SLinus Torvalds 	udelay(20);
22511da177e4SLinus Torvalds 
22521da177e4SLinus Torvalds 	/*
22531da177e4SLinus Torvalds 	 *	Reset the CODEC
22541da177e4SLinus Torvalds 	 */
22551da177e4SLinus Torvalds 
22561da177e4SLinus Torvalds 	snd_es1968_ac97_reset(chip);
22571da177e4SLinus Torvalds 
22581da177e4SLinus Torvalds 	/* Ring Bus Control B */
22591da177e4SLinus Torvalds 
22601da177e4SLinus Torvalds 	n = inl(iobase + ESM_RING_BUS_CONTR_B);
22611da177e4SLinus Torvalds 	n &= ~RINGB_EN_SPDIF;	/* SPDIF off */
22621da177e4SLinus Torvalds 	//w |= RINGB_EN_2CODEC;	/* enable 2nd codec */
22631da177e4SLinus Torvalds 	outl(n, iobase + ESM_RING_BUS_CONTR_B);
22641da177e4SLinus Torvalds 
22651da177e4SLinus Torvalds 	/* Set hardware volume control registers to midpoints.
22661da177e4SLinus Torvalds 	   We can tell which button was pushed based on how they change. */
22671da177e4SLinus Torvalds 	outb(0x88, iobase+0x1c);
22681da177e4SLinus Torvalds 	outb(0x88, iobase+0x1d);
22691da177e4SLinus Torvalds 	outb(0x88, iobase+0x1e);
22701da177e4SLinus Torvalds 	outb(0x88, iobase+0x1f);
22711da177e4SLinus Torvalds 
22721da177e4SLinus Torvalds 	/* it appears some maestros (dell 7500) only work if these are set,
227348fc7f7eSAdam Buchbinder 	   regardless of whether we use the assp or not. */
22741da177e4SLinus Torvalds 
22751da177e4SLinus Torvalds 	outb(0, iobase + ASSP_CONTROL_B);
22761da177e4SLinus Torvalds 	outb(3, iobase + ASSP_CONTROL_A);	/* M: Reserved bits... */
22771da177e4SLinus Torvalds 	outb(0, iobase + ASSP_CONTROL_C);	/* M: Disable ASSP, ASSP IRQ's and FM Port */
22781da177e4SLinus Torvalds 
22791da177e4SLinus Torvalds 	/*
22801da177e4SLinus Torvalds 	 * set up wavecache
22811da177e4SLinus Torvalds 	 */
22821da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
22831da177e4SLinus Torvalds 		/* Write 0 into the buffer area 0x1E0->1EF */
22841da177e4SLinus Torvalds 		outw(0x01E0 + i, iobase + WC_INDEX);
22851da177e4SLinus Torvalds 		outw(0x0000, iobase + WC_DATA);
22861da177e4SLinus Torvalds 
22871da177e4SLinus Torvalds 		/* The 1.10 test program seem to write 0 into the buffer area
22881da177e4SLinus Torvalds 		 * 0x1D0-0x1DF too.*/
22891da177e4SLinus Torvalds 		outw(0x01D0 + i, iobase + WC_INDEX);
22901da177e4SLinus Torvalds 		outw(0x0000, iobase + WC_DATA);
22911da177e4SLinus Torvalds 	}
22921da177e4SLinus Torvalds 	wave_set_register(chip, IDR7_WAVE_ROMRAM,
22931da177e4SLinus Torvalds 			  (wave_get_register(chip, IDR7_WAVE_ROMRAM) & 0xFF00));
22941da177e4SLinus Torvalds 	wave_set_register(chip, IDR7_WAVE_ROMRAM,
22951da177e4SLinus Torvalds 			  wave_get_register(chip, IDR7_WAVE_ROMRAM) | 0x100);
22961da177e4SLinus Torvalds 	wave_set_register(chip, IDR7_WAVE_ROMRAM,
22971da177e4SLinus Torvalds 			  wave_get_register(chip, IDR7_WAVE_ROMRAM) & ~0x200);
22981da177e4SLinus Torvalds 	wave_set_register(chip, IDR7_WAVE_ROMRAM,
22991da177e4SLinus Torvalds 			  wave_get_register(chip, IDR7_WAVE_ROMRAM) | ~0x400);
23001da177e4SLinus Torvalds 
23011da177e4SLinus Torvalds 
23021da177e4SLinus Torvalds 	maestro_write(chip, IDR2_CRAM_DATA, 0x0000);
23031da177e4SLinus Torvalds 	/* Now back to the DirectSound stuff */
23041da177e4SLinus Torvalds 	/* audio serial configuration.. ? */
23051da177e4SLinus Torvalds 	maestro_write(chip, 0x08, 0xB004);
23061da177e4SLinus Torvalds 	maestro_write(chip, 0x09, 0x001B);
23071da177e4SLinus Torvalds 	maestro_write(chip, 0x0A, 0x8000);
23081da177e4SLinus Torvalds 	maestro_write(chip, 0x0B, 0x3F37);
23091da177e4SLinus Torvalds 	maestro_write(chip, 0x0C, 0x0098);
23101da177e4SLinus Torvalds 
23111da177e4SLinus Torvalds 	/* parallel in, has something to do with recording :) */
23121da177e4SLinus Torvalds 	maestro_write(chip, 0x0C,
23131da177e4SLinus Torvalds 		      (maestro_read(chip, 0x0C) & ~0xF000) | 0x8000);
23141da177e4SLinus Torvalds 	/* parallel out */
23151da177e4SLinus Torvalds 	maestro_write(chip, 0x0C,
23161da177e4SLinus Torvalds 		      (maestro_read(chip, 0x0C) & ~0x0F00) | 0x0500);
23171da177e4SLinus Torvalds 
23181da177e4SLinus Torvalds 	maestro_write(chip, 0x0D, 0x7632);
23191da177e4SLinus Torvalds 
23201da177e4SLinus Torvalds 	/* Wave cache control on - test off, sg off,
23211da177e4SLinus Torvalds 	   enable, enable extra chans 1Mb */
23221da177e4SLinus Torvalds 
23231da177e4SLinus Torvalds 	w = inw(iobase + WC_CONTROL);
23241da177e4SLinus Torvalds 
23251da177e4SLinus Torvalds 	w &= ~0xFA00;		/* Seems to be reserved? I don't know */
23261da177e4SLinus Torvalds 	w |= 0xA000;		/* reserved... I don't know */
23271da177e4SLinus Torvalds 	w &= ~0x0200;		/* Channels 56,57,58,59 as Extra Play,Rec Channel enable
23281da177e4SLinus Torvalds 				   Seems to crash the Computer if enabled... */
23291da177e4SLinus Torvalds 	w |= 0x0100;		/* Wave Cache Operation Enabled */
23301da177e4SLinus Torvalds 	w |= 0x0080;		/* Channels 60/61 as Placback/Record enabled */
23311da177e4SLinus Torvalds 	w &= ~0x0060;		/* Clear Wavtable Size */
23321da177e4SLinus Torvalds 	w |= 0x0020;		/* Wavetable Size : 1MB */
23331da177e4SLinus Torvalds 	/* Bit 4 is reserved */
23341da177e4SLinus Torvalds 	w &= ~0x000C;		/* DMA Stuff? I don't understand what the datasheet means */
23351da177e4SLinus Torvalds 	/* Bit 1 is reserved */
23361da177e4SLinus Torvalds 	w &= ~0x0001;		/* Test Mode off */
23371da177e4SLinus Torvalds 
23381da177e4SLinus Torvalds 	outw(w, iobase + WC_CONTROL);
23391da177e4SLinus Torvalds 
23401da177e4SLinus Torvalds 	/* Now clear the APU control ram */
23411da177e4SLinus Torvalds 	for (i = 0; i < NR_APUS; i++) {
23421da177e4SLinus Torvalds 		for (w = 0; w < NR_APU_REGS; w++)
23431da177e4SLinus Torvalds 			apu_set_register(chip, i, w, 0);
23441da177e4SLinus Torvalds 
23451da177e4SLinus Torvalds 	}
23461da177e4SLinus Torvalds }
23471da177e4SLinus Torvalds 
23481da177e4SLinus Torvalds /* Enable IRQ's */
snd_es1968_start_irq(struct es1968 * chip)2349969165a8STakashi Iwai static void snd_es1968_start_irq(struct es1968 *chip)
23501da177e4SLinus Torvalds {
23511da177e4SLinus Torvalds 	unsigned short w;
23521da177e4SLinus Torvalds 	w = ESM_HIRQ_DSIE | ESM_HIRQ_HW_VOLUME;
23531da177e4SLinus Torvalds 	if (chip->rmidi)
23541da177e4SLinus Torvalds 		w |= ESM_HIRQ_MPU401;
23556895b526SVille Syrjälä 	outb(w, chip->io_port + 0x1A);
23561da177e4SLinus Torvalds 	outw(w, chip->io_port + ESM_PORT_HOST_IRQ);
23571da177e4SLinus Torvalds }
23581da177e4SLinus Torvalds 
2359c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
23601da177e4SLinus Torvalds /*
23611da177e4SLinus Torvalds  * PM support
23621da177e4SLinus Torvalds  */
es1968_suspend(struct device * dev)236368cb2b55STakashi Iwai static int es1968_suspend(struct device *dev)
23641da177e4SLinus Torvalds {
236568cb2b55STakashi Iwai 	struct snd_card *card = dev_get_drvdata(dev);
23661d4b822bSTakashi Iwai 	struct es1968 *chip = card->private_data;
23671da177e4SLinus Torvalds 
23681da177e4SLinus Torvalds 	if (! chip->do_pm)
23691da177e4SLinus Torvalds 		return 0;
23701da177e4SLinus Torvalds 
23711da177e4SLinus Torvalds 	chip->in_suspend = 1;
237230bdee02STakashi Iwai 	cancel_work_sync(&chip->hwvol_work);
23731d4b822bSTakashi Iwai 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
23741da177e4SLinus Torvalds 	snd_ac97_suspend(chip->ac97);
23751da177e4SLinus Torvalds 	snd_es1968_bob_stop(chip);
23761da177e4SLinus Torvalds 	return 0;
23771da177e4SLinus Torvalds }
23781da177e4SLinus Torvalds 
es1968_resume(struct device * dev)237968cb2b55STakashi Iwai static int es1968_resume(struct device *dev)
23801da177e4SLinus Torvalds {
238168cb2b55STakashi Iwai 	struct snd_card *card = dev_get_drvdata(dev);
23821d4b822bSTakashi Iwai 	struct es1968 *chip = card->private_data;
238350f47ff1SMatthias Kaehlcke 	struct esschan *es;
23841da177e4SLinus Torvalds 
23851da177e4SLinus Torvalds 	if (! chip->do_pm)
23861da177e4SLinus Torvalds 		return 0;
23871da177e4SLinus Torvalds 
23881da177e4SLinus Torvalds 	snd_es1968_chip_init(chip);
23891da177e4SLinus Torvalds 
23901da177e4SLinus Torvalds 	/* need to restore the base pointers.. */
23911da177e4SLinus Torvalds 	if (chip->dma.addr) {
23921da177e4SLinus Torvalds 		/* set PCMBAR */
23931da177e4SLinus Torvalds 		wave_set_register(chip, 0x01FC, chip->dma.addr >> 12);
23941da177e4SLinus Torvalds 	}
23951da177e4SLinus Torvalds 
23961da177e4SLinus Torvalds 	snd_es1968_start_irq(chip);
23971da177e4SLinus Torvalds 
23981da177e4SLinus Torvalds 	/* restore ac97 state */
23991da177e4SLinus Torvalds 	snd_ac97_resume(chip->ac97);
24001da177e4SLinus Torvalds 
240150f47ff1SMatthias Kaehlcke 	list_for_each_entry(es, &chip->substream_list, list) {
24021da177e4SLinus Torvalds 		switch (es->mode) {
24031da177e4SLinus Torvalds 		case ESM_MODE_PLAY:
24041da177e4SLinus Torvalds 			snd_es1968_playback_setup(chip, es, es->substream->runtime);
24051da177e4SLinus Torvalds 			break;
24061da177e4SLinus Torvalds 		case ESM_MODE_CAPTURE:
24071da177e4SLinus Torvalds 			snd_es1968_capture_setup(chip, es, es->substream->runtime);
24081da177e4SLinus Torvalds 			break;
24091da177e4SLinus Torvalds 		}
24101da177e4SLinus Torvalds 	}
24111da177e4SLinus Torvalds 
24121da177e4SLinus Torvalds 	/* start timer again */
24131da177e4SLinus Torvalds 	if (chip->bobclient)
24141da177e4SLinus Torvalds 		snd_es1968_bob_start(chip);
24151da177e4SLinus Torvalds 
24161d4b822bSTakashi Iwai 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
24171da177e4SLinus Torvalds 	chip->in_suspend = 0;
24181da177e4SLinus Torvalds 	return 0;
24191da177e4SLinus Torvalds }
242068cb2b55STakashi Iwai 
242168cb2b55STakashi Iwai static SIMPLE_DEV_PM_OPS(es1968_pm, es1968_suspend, es1968_resume);
242268cb2b55STakashi Iwai #define ES1968_PM_OPS	&es1968_pm
242368cb2b55STakashi Iwai #else
242468cb2b55STakashi Iwai #define ES1968_PM_OPS	NULL
2425c7561cd8STakashi Iwai #endif /* CONFIG_PM_SLEEP */
24261da177e4SLinus Torvalds 
24271da177e4SLinus Torvalds #ifdef SUPPORT_JOYSTICK
24281da177e4SLinus Torvalds #define JOYSTICK_ADDR	0x200
snd_es1968_create_gameport(struct es1968 * chip,int dev)2429e23e7a14SBill Pemberton static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
24301da177e4SLinus Torvalds {
24311da177e4SLinus Torvalds 	struct gameport *gp;
24321da177e4SLinus Torvalds 	struct resource *r;
24331da177e4SLinus Torvalds 	u16 val;
24341da177e4SLinus Torvalds 
24351da177e4SLinus Torvalds 	if (!joystick[dev])
24361da177e4SLinus Torvalds 		return -ENODEV;
24371da177e4SLinus Torvalds 
2438a7b4cbfdSTakashi Iwai 	r = devm_request_region(&chip->pci->dev, JOYSTICK_ADDR, 8,
2439a7b4cbfdSTakashi Iwai 				"ES1968 gameport");
24401da177e4SLinus Torvalds 	if (!r)
24411da177e4SLinus Torvalds 		return -EBUSY;
24421da177e4SLinus Torvalds 
24431da177e4SLinus Torvalds 	chip->gameport = gp = gameport_allocate_port();
24441da177e4SLinus Torvalds 	if (!gp) {
244586cd372fSTakashi Iwai 		dev_err(chip->card->dev,
244686cd372fSTakashi Iwai 			"cannot allocate memory for gameport\n");
24471da177e4SLinus Torvalds 		return -ENOMEM;
24481da177e4SLinus Torvalds 	}
24491da177e4SLinus Torvalds 
24501da177e4SLinus Torvalds 	pci_read_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, &val);
24511da177e4SLinus Torvalds 	pci_write_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04);
24521da177e4SLinus Torvalds 
24531da177e4SLinus Torvalds 	gameport_set_name(gp, "ES1968 Gameport");
24541da177e4SLinus Torvalds 	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
24551da177e4SLinus Torvalds 	gameport_set_dev_parent(gp, &chip->pci->dev);
24561da177e4SLinus Torvalds 	gp->io = JOYSTICK_ADDR;
24571da177e4SLinus Torvalds 
24581da177e4SLinus Torvalds 	gameport_register_port(gp);
24591da177e4SLinus Torvalds 
24601da177e4SLinus Torvalds 	return 0;
24611da177e4SLinus Torvalds }
24621da177e4SLinus Torvalds 
snd_es1968_free_gameport(struct es1968 * chip)2463969165a8STakashi Iwai static void snd_es1968_free_gameport(struct es1968 *chip)
24641da177e4SLinus Torvalds {
24651da177e4SLinus Torvalds 	if (chip->gameport) {
24661da177e4SLinus Torvalds 		gameport_unregister_port(chip->gameport);
24671da177e4SLinus Torvalds 		chip->gameport = NULL;
24681da177e4SLinus Torvalds 	}
24691da177e4SLinus Torvalds }
24701da177e4SLinus Torvalds #else
snd_es1968_create_gameport(struct es1968 * chip,int dev)2471969165a8STakashi Iwai static inline int snd_es1968_create_gameport(struct es1968 *chip, int dev) { return -ENOSYS; }
snd_es1968_free_gameport(struct es1968 * chip)2472969165a8STakashi Iwai static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
24731da177e4SLinus Torvalds #endif
24741da177e4SLinus Torvalds 
24755a5e02e5SHans de Goede #ifdef CONFIG_SND_ES1968_INPUT
snd_es1968_input_register(struct es1968 * chip)2476e23e7a14SBill Pemberton static int snd_es1968_input_register(struct es1968 *chip)
24775a5e02e5SHans de Goede {
24785a5e02e5SHans de Goede 	struct input_dev *input_dev;
24795a5e02e5SHans de Goede 	int err;
24805a5e02e5SHans de Goede 
2481a7b4cbfdSTakashi Iwai 	input_dev = devm_input_allocate_device(&chip->pci->dev);
24825a5e02e5SHans de Goede 	if (!input_dev)
24835a5e02e5SHans de Goede 		return -ENOMEM;
24845a5e02e5SHans de Goede 
24855a5e02e5SHans de Goede 	snprintf(chip->phys, sizeof(chip->phys), "pci-%s/input0",
24865a5e02e5SHans de Goede 		 pci_name(chip->pci));
24875a5e02e5SHans de Goede 
24885a5e02e5SHans de Goede 	input_dev->name = chip->card->driver;
24895a5e02e5SHans de Goede 	input_dev->phys = chip->phys;
24905a5e02e5SHans de Goede 	input_dev->id.bustype = BUS_PCI;
24915a5e02e5SHans de Goede 	input_dev->id.vendor  = chip->pci->vendor;
24925a5e02e5SHans de Goede 	input_dev->id.product = chip->pci->device;
24935a5e02e5SHans de Goede 	input_dev->dev.parent = &chip->pci->dev;
24945a5e02e5SHans de Goede 
24955a5e02e5SHans de Goede 	__set_bit(EV_KEY, input_dev->evbit);
24965a5e02e5SHans de Goede 	__set_bit(KEY_MUTE, input_dev->keybit);
24975a5e02e5SHans de Goede 	__set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
24985a5e02e5SHans de Goede 	__set_bit(KEY_VOLUMEUP, input_dev->keybit);
24995a5e02e5SHans de Goede 
25005a5e02e5SHans de Goede 	err = input_register_device(input_dev);
2501a7b4cbfdSTakashi Iwai 	if (err)
25025a5e02e5SHans de Goede 		return err;
25035a5e02e5SHans de Goede 
25045a5e02e5SHans de Goede 	chip->input_dev = input_dev;
25055a5e02e5SHans de Goede 	return 0;
25065a5e02e5SHans de Goede }
25075a5e02e5SHans de Goede #endif /* CONFIG_SND_ES1968_INPUT */
25085a5e02e5SHans de Goede 
25091872f589SOndrej Zary #ifdef CONFIG_SND_ES1968_RADIO
25101872f589SOndrej Zary #define GPIO_DATA	0x60
25111872f589SOndrej Zary #define IO_MASK		4      /* mask      register offset from GPIO_DATA
25121872f589SOndrej Zary 				bits 1=unmask write to given bit */
25131872f589SOndrej Zary #define IO_DIR		8      /* direction register offset from GPIO_DATA
25141872f589SOndrej Zary 				bits 0/1=read/write direction */
25158e0d7043SOndrej Zary 
25168e0d7043SOndrej Zary /* GPIO to TEA575x maps */
25178e0d7043SOndrej Zary struct snd_es1968_tea575x_gpio {
25188e0d7043SOndrej Zary 	u8 data, clk, wren, most;
25198e0d7043SOndrej Zary 	char *name;
25208e0d7043SOndrej Zary };
25218e0d7043SOndrej Zary 
2522cd6e0312STakashi Iwai static const struct snd_es1968_tea575x_gpio snd_es1968_tea575x_gpios[] = {
25238e0d7043SOndrej Zary 	{ .data = 6, .clk = 7, .wren = 8, .most = 9, .name = "SF64-PCE2" },
25248e0d7043SOndrej Zary 	{ .data = 7, .clk = 8, .wren = 6, .most = 10, .name = "M56VAP" },
25258e0d7043SOndrej Zary };
25268e0d7043SOndrej Zary 
25278e0d7043SOndrej Zary #define get_tea575x_gpio(chip) \
25288e0d7043SOndrej Zary 	(&snd_es1968_tea575x_gpios[(chip)->tea575x_tuner])
25298e0d7043SOndrej Zary 
25301872f589SOndrej Zary 
snd_es1968_tea575x_set_pins(struct snd_tea575x * tea,u8 pins)253172587173SOndrej Zary static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
25321872f589SOndrej Zary {
25331872f589SOndrej Zary 	struct es1968 *chip = tea->private_data;
25348e0d7043SOndrej Zary 	struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip);
253572587173SOndrej Zary 	u16 val = 0;
25361872f589SOndrej Zary 
25378e0d7043SOndrej Zary 	val |= (pins & TEA575X_DATA) ? (1 << gpio.data) : 0;
25388e0d7043SOndrej Zary 	val |= (pins & TEA575X_CLK)  ? (1 << gpio.clk)  : 0;
25398e0d7043SOndrej Zary 	val |= (pins & TEA575X_WREN) ? (1 << gpio.wren) : 0;
254072587173SOndrej Zary 
25418e0d7043SOndrej Zary 	outw(val, chip->io_port + GPIO_DATA);
254272587173SOndrej Zary }
254372587173SOndrej Zary 
snd_es1968_tea575x_get_pins(struct snd_tea575x * tea)254472587173SOndrej Zary static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
254572587173SOndrej Zary {
254672587173SOndrej Zary 	struct es1968 *chip = tea->private_data;
25478e0d7043SOndrej Zary 	struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip);
25488e0d7043SOndrej Zary 	u16 val = inw(chip->io_port + GPIO_DATA);
25498e0d7043SOndrej Zary 	u8 ret = 0;
255072587173SOndrej Zary 
25518e0d7043SOndrej Zary 	if (val & (1 << gpio.data))
2552d2153a15SDan Carpenter 		ret |= TEA575X_DATA;
25538e0d7043SOndrej Zary 	if (val & (1 << gpio.most))
2554d2153a15SDan Carpenter 		ret |= TEA575X_MOST;
25558e0d7043SOndrej Zary 
2556d2153a15SDan Carpenter 	return ret;
255772587173SOndrej Zary }
255872587173SOndrej Zary 
snd_es1968_tea575x_set_direction(struct snd_tea575x * tea,bool output)255972587173SOndrej Zary static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output)
256072587173SOndrej Zary {
256172587173SOndrej Zary 	struct es1968 *chip = tea->private_data;
256272587173SOndrej Zary 	unsigned long io = chip->io_port + GPIO_DATA;
256372587173SOndrej Zary 	u16 odir = inw(io + IO_DIR);
25648e0d7043SOndrej Zary 	struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip);
256572587173SOndrej Zary 
256672587173SOndrej Zary 	if (output) {
25678e0d7043SOndrej Zary 		outw(~((1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren)),
25688e0d7043SOndrej Zary 			io + IO_MASK);
25698e0d7043SOndrej Zary 		outw(odir | (1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren),
25708e0d7043SOndrej Zary 			io + IO_DIR);
257172587173SOndrej Zary 	} else {
25728e0d7043SOndrej Zary 		outw(~((1 << gpio.clk) | (1 << gpio.wren) | (1 << gpio.data) | (1 << gpio.most)),
25738e0d7043SOndrej Zary 			io + IO_MASK);
25748e0d7043SOndrej Zary 		outw((odir & ~((1 << gpio.data) | (1 << gpio.most)))
25758e0d7043SOndrej Zary 			| (1 << gpio.clk) | (1 << gpio.wren), io + IO_DIR);
25761872f589SOndrej Zary 	}
25771872f589SOndrej Zary }
25781872f589SOndrej Zary 
257922dbec26SJulia Lawall static const struct snd_tea575x_ops snd_es1968_tea_ops = {
258072587173SOndrej Zary 	.set_pins = snd_es1968_tea575x_set_pins,
258172587173SOndrej Zary 	.get_pins = snd_es1968_tea575x_get_pins,
258272587173SOndrej Zary 	.set_direction = snd_es1968_tea575x_set_direction,
25831872f589SOndrej Zary };
25841872f589SOndrej Zary #endif
25851872f589SOndrej Zary 
snd_es1968_free(struct snd_card * card)2586a7b4cbfdSTakashi Iwai static void snd_es1968_free(struct snd_card *card)
25871da177e4SLinus Torvalds {
2588a7b4cbfdSTakashi Iwai 	struct es1968 *chip = card->private_data;
2589a7b4cbfdSTakashi Iwai 
259030bdee02STakashi Iwai 	cancel_work_sync(&chip->hwvol_work);
25915a5e02e5SHans de Goede 
25921da177e4SLinus Torvalds 	if (chip->io_port) {
25931da177e4SLinus Torvalds 		outw(1, chip->io_port + 0x04); /* clear WP interrupts */
25941da177e4SLinus Torvalds 		outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
25951da177e4SLinus Torvalds 	}
25961da177e4SLinus Torvalds 
25971872f589SOndrej Zary #ifdef CONFIG_SND_ES1968_RADIO
25981872f589SOndrej Zary 	snd_tea575x_exit(&chip->tea);
2599d4ecc83bSHans Verkuil 	v4l2_device_unregister(&chip->v4l2_dev);
26001872f589SOndrej Zary #endif
26011872f589SOndrej Zary 
26021da177e4SLinus Torvalds 	snd_es1968_free_gameport(chip);
26031da177e4SLinus Torvalds }
26041da177e4SLinus Torvalds 
26051da177e4SLinus Torvalds struct ess_device_list {
26061da177e4SLinus Torvalds 	unsigned short type;	/* chip type */
26071da177e4SLinus Torvalds 	unsigned short vendor;	/* subsystem vendor id */
26081da177e4SLinus Torvalds };
26091da177e4SLinus Torvalds 
2610abe092aeSTakashi Iwai static const struct ess_device_list pm_allowlist[] = {
26111da177e4SLinus Torvalds 	{ TYPE_MAESTRO2E, 0x0e11 },	/* Compaq Armada */
26121da177e4SLinus Torvalds 	{ TYPE_MAESTRO2E, 0x1028 },
26131da177e4SLinus Torvalds 	{ TYPE_MAESTRO2E, 0x103c },
26141da177e4SLinus Torvalds 	{ TYPE_MAESTRO2E, 0x1179 },
26151da177e4SLinus Torvalds 	{ TYPE_MAESTRO2E, 0x14c0 },	/* HP omnibook 4150 */
2616e6e514faSTakashi Iwai 	{ TYPE_MAESTRO2E, 0x1558 },
26175c0ee949SOndrej Zary 	{ TYPE_MAESTRO2E, 0x125d },	/* a PCI card, e.g. Terratec DMX */
26185c0ee949SOndrej Zary 	{ TYPE_MAESTRO2, 0x125d },	/* a PCI card, e.g. SF64-PCE2 */
26191da177e4SLinus Torvalds };
26201da177e4SLinus Torvalds 
2621abe092aeSTakashi Iwai static const struct ess_device_list mpu_denylist[] = {
26221da177e4SLinus Torvalds 	{ TYPE_MAESTRO2, 0x125d },
26231da177e4SLinus Torvalds };
26241da177e4SLinus Torvalds 
snd_es1968_create(struct snd_card * card,struct pci_dev * pci,int total_bufsize,int play_streams,int capt_streams,int chip_type,int do_pm,int radio_nr)2625e23e7a14SBill Pemberton static int snd_es1968_create(struct snd_card *card,
26261da177e4SLinus Torvalds 			     struct pci_dev *pci,
26271da177e4SLinus Torvalds 			     int total_bufsize,
26281da177e4SLinus Torvalds 			     int play_streams,
26291da177e4SLinus Torvalds 			     int capt_streams,
26301da177e4SLinus Torvalds 			     int chip_type,
26311da177e4SLinus Torvalds 			     int do_pm,
2632a7b4cbfdSTakashi Iwai 			     int radio_nr)
26331da177e4SLinus Torvalds {
2634a7b4cbfdSTakashi Iwai 	struct es1968 *chip = card->private_data;
26351da177e4SLinus Torvalds 	int i, err;
26361da177e4SLinus Torvalds 
26371da177e4SLinus Torvalds 	/* enable PCI device */
2638a7b4cbfdSTakashi Iwai 	err = pcim_enable_device(pci);
263948cab474STakashi Iwai 	if (err < 0)
26401da177e4SLinus Torvalds 		return err;
26411da177e4SLinus Torvalds 	/* check, if we can restrict PCI DMA transfers to 28 bits */
2642669f65eaSTakashi Iwai 	if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
264386cd372fSTakashi Iwai 		dev_err(card->dev,
264486cd372fSTakashi Iwai 			"architecture does not support 28bit PCI busmaster DMA\n");
26451da177e4SLinus Torvalds 		return -ENXIO;
26461da177e4SLinus Torvalds 	}
26471da177e4SLinus Torvalds 
26481da177e4SLinus Torvalds 	/* Set Vars */
26491da177e4SLinus Torvalds 	chip->type = chip_type;
26501da177e4SLinus Torvalds 	spin_lock_init(&chip->reg_lock);
26511da177e4SLinus Torvalds 	spin_lock_init(&chip->substream_lock);
26521da177e4SLinus Torvalds 	INIT_LIST_HEAD(&chip->buf_list);
26531da177e4SLinus Torvalds 	INIT_LIST_HEAD(&chip->substream_list);
265462932df8SIngo Molnar 	mutex_init(&chip->memory_mutex);
265530bdee02STakashi Iwai 	INIT_WORK(&chip->hwvol_work, es1968_update_hw_volume);
26561da177e4SLinus Torvalds 	chip->card = card;
26571da177e4SLinus Torvalds 	chip->pci = pci;
26581da177e4SLinus Torvalds 	chip->irq = -1;
26591da177e4SLinus Torvalds 	chip->total_bufsize = total_bufsize;	/* in bytes */
26601da177e4SLinus Torvalds 	chip->playback_streams = play_streams;
26611da177e4SLinus Torvalds 	chip->capture_streams = capt_streams;
26621da177e4SLinus Torvalds 
266348cab474STakashi Iwai 	err = pci_request_regions(pci, "ESS Maestro");
2664a7b4cbfdSTakashi Iwai 	if (err < 0)
26651da177e4SLinus Torvalds 		return err;
26661da177e4SLinus Torvalds 	chip->io_port = pci_resource_start(pci, 0);
2667a7b4cbfdSTakashi Iwai 	if (devm_request_irq(&pci->dev, pci->irq, snd_es1968_interrupt,
2668a7b4cbfdSTakashi Iwai 			     IRQF_SHARED, KBUILD_MODNAME, chip)) {
266986cd372fSTakashi Iwai 		dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
26701da177e4SLinus Torvalds 		return -EBUSY;
26711da177e4SLinus Torvalds 	}
26721da177e4SLinus Torvalds 	chip->irq = pci->irq;
2673dbb71ab0STakashi Iwai 	card->sync_irq = chip->irq;
2674a7b4cbfdSTakashi Iwai 	card->private_free = snd_es1968_free;
26751da177e4SLinus Torvalds 
26761da177e4SLinus Torvalds 	/* Clear Maestro_map */
26771da177e4SLinus Torvalds 	for (i = 0; i < 32; i++)
26781da177e4SLinus Torvalds 		chip->maestro_map[i] = 0;
26791da177e4SLinus Torvalds 
26801da177e4SLinus Torvalds 	/* Clear Apu Map */
26811da177e4SLinus Torvalds 	for (i = 0; i < NR_APUS; i++)
26821da177e4SLinus Torvalds 		chip->apu[i] = ESM_APU_FREE;
26831da177e4SLinus Torvalds 
26841da177e4SLinus Torvalds 	/* just to be sure */
26851da177e4SLinus Torvalds 	pci_set_master(pci);
26861da177e4SLinus Torvalds 
26871da177e4SLinus Torvalds 	if (do_pm > 1) {
2688abe092aeSTakashi Iwai 		/* disable power-management if not on the allowlist */
26891da177e4SLinus Torvalds 		unsigned short vend;
26901da177e4SLinus Torvalds 		pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend);
2691abe092aeSTakashi Iwai 		for (i = 0; i < (int)ARRAY_SIZE(pm_allowlist); i++) {
2692abe092aeSTakashi Iwai 			if (chip->type == pm_allowlist[i].type &&
2693abe092aeSTakashi Iwai 			    vend == pm_allowlist[i].vendor) {
26941da177e4SLinus Torvalds 				do_pm = 1;
26951da177e4SLinus Torvalds 				break;
26961da177e4SLinus Torvalds 			}
26971da177e4SLinus Torvalds 		}
26981da177e4SLinus Torvalds 		if (do_pm > 1) {
26991da177e4SLinus Torvalds 			/* not matched; disabling pm */
270086cd372fSTakashi Iwai 			dev_info(card->dev, "not attempting power management.\n");
27011da177e4SLinus Torvalds 			do_pm = 0;
27021da177e4SLinus Torvalds 		}
27031da177e4SLinus Torvalds 	}
27041da177e4SLinus Torvalds 	chip->do_pm = do_pm;
27051da177e4SLinus Torvalds 
27061da177e4SLinus Torvalds 	snd_es1968_chip_init(chip);
27071da177e4SLinus Torvalds 
27081872f589SOndrej Zary #ifdef CONFIG_SND_ES1968_RADIO
27098e0d7043SOndrej Zary 	/* don't play with GPIOs on laptops */
27108e0d7043SOndrej Zary 	if (chip->pci->subsystem_vendor != 0x125d)
2711a7b4cbfdSTakashi Iwai 		return 0;
2712d4ecc83bSHans Verkuil 	err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
2713a7b4cbfdSTakashi Iwai 	if (err < 0)
2714d4ecc83bSHans Verkuil 		return err;
2715d4ecc83bSHans Verkuil 	chip->tea.v4l2_dev = &chip->v4l2_dev;
27161872f589SOndrej Zary 	chip->tea.private_data = chip;
2717d4ecc83bSHans Verkuil 	chip->tea.radio_nr = radio_nr;
27181872f589SOndrej Zary 	chip->tea.ops = &snd_es1968_tea_ops;
271910ca7201SOndrej Zary 	sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
27208e0d7043SOndrej Zary 	for (i = 0; i < ARRAY_SIZE(snd_es1968_tea575x_gpios); i++) {
27218e0d7043SOndrej Zary 		chip->tea575x_tuner = i;
27228e0d7043SOndrej Zary 		if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) {
272386cd372fSTakashi Iwai 			dev_info(card->dev, "detected TEA575x radio type %s\n",
27248e0d7043SOndrej Zary 				   get_tea575x_gpio(chip)->name);
272575b1a8f9SJoe Perches 			strscpy(chip->tea.card, get_tea575x_gpio(chip)->name,
27268e0d7043SOndrej Zary 				sizeof(chip->tea.card));
27278e0d7043SOndrej Zary 			break;
27288e0d7043SOndrej Zary 		}
27298e0d7043SOndrej Zary 	}
27301872f589SOndrej Zary #endif
27311da177e4SLinus Torvalds 	return 0;
27321da177e4SLinus Torvalds }
27331da177e4SLinus Torvalds 
27341da177e4SLinus Torvalds 
27351da177e4SLinus Torvalds /*
27361da177e4SLinus Torvalds  */
__snd_es1968_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)2737de9a01bcSTakashi Iwai static int __snd_es1968_probe(struct pci_dev *pci,
27381da177e4SLinus Torvalds 			      const struct pci_device_id *pci_id)
27391da177e4SLinus Torvalds {
27401da177e4SLinus Torvalds 	static int dev;
2741969165a8STakashi Iwai 	struct snd_card *card;
2742969165a8STakashi Iwai 	struct es1968 *chip;
27431da177e4SLinus Torvalds 	unsigned int i;
27441da177e4SLinus Torvalds 	int err;
27451da177e4SLinus Torvalds 
27461da177e4SLinus Torvalds 	if (dev >= SNDRV_CARDS)
27471da177e4SLinus Torvalds 		return -ENODEV;
27481da177e4SLinus Torvalds 	if (!enable[dev]) {
27491da177e4SLinus Torvalds 		dev++;
27501da177e4SLinus Torvalds 		return -ENOENT;
27511da177e4SLinus Torvalds 	}
27521da177e4SLinus Torvalds 
2753a7b4cbfdSTakashi Iwai 	err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
2754a7b4cbfdSTakashi Iwai 				sizeof(*chip), &card);
2755e58de7baSTakashi Iwai 	if (err < 0)
2756e58de7baSTakashi Iwai 		return err;
2757a7b4cbfdSTakashi Iwai 	chip = card->private_data;
27581da177e4SLinus Torvalds 
27591da177e4SLinus Torvalds 	if (total_bufsize[dev] < 128)
27601da177e4SLinus Torvalds 		total_bufsize[dev] = 128;
27611da177e4SLinus Torvalds 	if (total_bufsize[dev] > 4096)
27621da177e4SLinus Torvalds 		total_bufsize[dev] = 4096;
276348cab474STakashi Iwai 	err = snd_es1968_create(card, pci,
27641da177e4SLinus Torvalds 				total_bufsize[dev] * 1024, /* in bytes */
27651da177e4SLinus Torvalds 				pcm_substreams_p[dev],
27661da177e4SLinus Torvalds 				pcm_substreams_c[dev],
27671da177e4SLinus Torvalds 				pci_id->driver_data,
27681da177e4SLinus Torvalds 				use_pm[dev],
2769a7b4cbfdSTakashi Iwai 				radio_nr[dev]);
2770a7b4cbfdSTakashi Iwai 	if (err < 0)
27711da177e4SLinus Torvalds 		return err;
27721da177e4SLinus Torvalds 
27731da177e4SLinus Torvalds 	switch (chip->type) {
27741da177e4SLinus Torvalds 	case TYPE_MAESTRO2E:
27751da177e4SLinus Torvalds 		strcpy(card->driver, "ES1978");
27761da177e4SLinus Torvalds 		strcpy(card->shortname, "ESS ES1978 (Maestro 2E)");
27771da177e4SLinus Torvalds 		break;
27781da177e4SLinus Torvalds 	case TYPE_MAESTRO2:
27791da177e4SLinus Torvalds 		strcpy(card->driver, "ES1968");
27801da177e4SLinus Torvalds 		strcpy(card->shortname, "ESS ES1968 (Maestro 2)");
27811da177e4SLinus Torvalds 		break;
27821da177e4SLinus Torvalds 	case TYPE_MAESTRO:
27831da177e4SLinus Torvalds 		strcpy(card->driver, "ESM1");
27841da177e4SLinus Torvalds 		strcpy(card->shortname, "ESS Maestro 1");
27851da177e4SLinus Torvalds 		break;
27861da177e4SLinus Torvalds 	}
27871da177e4SLinus Torvalds 
278848cab474STakashi Iwai 	err = snd_es1968_pcm(chip, 0);
2789a7b4cbfdSTakashi Iwai 	if (err < 0)
27901da177e4SLinus Torvalds 		return err;
27911da177e4SLinus Torvalds 
279248cab474STakashi Iwai 	err = snd_es1968_mixer(chip);
2793a7b4cbfdSTakashi Iwai 	if (err < 0)
27941da177e4SLinus Torvalds 		return err;
27951da177e4SLinus Torvalds 
27961da177e4SLinus Torvalds 	if (enable_mpu[dev] == 2) {
2797abe092aeSTakashi Iwai 		/* check the deny list */
27981da177e4SLinus Torvalds 		unsigned short vend;
27991da177e4SLinus Torvalds 		pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend);
2800abe092aeSTakashi Iwai 		for (i = 0; i < ARRAY_SIZE(mpu_denylist); i++) {
2801abe092aeSTakashi Iwai 			if (chip->type == mpu_denylist[i].type &&
2802abe092aeSTakashi Iwai 			    vend == mpu_denylist[i].vendor) {
28031da177e4SLinus Torvalds 				enable_mpu[dev] = 0;
28041da177e4SLinus Torvalds 				break;
28051da177e4SLinus Torvalds 			}
28061da177e4SLinus Torvalds 		}
28071da177e4SLinus Torvalds 	}
28081da177e4SLinus Torvalds 	if (enable_mpu[dev]) {
280948cab474STakashi Iwai 		err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
2810302e4c2fSTakashi Iwai 					  chip->io_port + ESM_MPU401_PORT,
2811dba8b469SClemens Ladisch 					  MPU401_INFO_INTEGRATED |
2812dba8b469SClemens Ladisch 					  MPU401_INFO_IRQ_HOOK,
281348cab474STakashi Iwai 					  -1, &chip->rmidi);
281448cab474STakashi Iwai 		if (err < 0)
281586cd372fSTakashi Iwai 			dev_warn(card->dev, "skipping MPU-401 MIDI support..\n");
28161da177e4SLinus Torvalds 	}
28171da177e4SLinus Torvalds 
28181da177e4SLinus Torvalds 	snd_es1968_create_gameport(chip, dev);
28191da177e4SLinus Torvalds 
28205a5e02e5SHans de Goede #ifdef CONFIG_SND_ES1968_INPUT
28215a5e02e5SHans de Goede 	err = snd_es1968_input_register(chip);
28225a5e02e5SHans de Goede 	if (err)
282386cd372fSTakashi Iwai 		dev_warn(card->dev,
282486cd372fSTakashi Iwai 			 "Input device registration failed with error %i", err);
28255a5e02e5SHans de Goede #endif
28265a5e02e5SHans de Goede 
28271da177e4SLinus Torvalds 	snd_es1968_start_irq(chip);
28281da177e4SLinus Torvalds 
28291da177e4SLinus Torvalds 	chip->clock = clock[dev];
28301da177e4SLinus Torvalds 	if (! chip->clock)
28311da177e4SLinus Torvalds 		es1968_measure_clock(chip);
28321da177e4SLinus Torvalds 
28331da177e4SLinus Torvalds 	sprintf(card->longname, "%s at 0x%lx, irq %i",
28341da177e4SLinus Torvalds 		card->shortname, chip->io_port, chip->irq);
28351da177e4SLinus Torvalds 
283648cab474STakashi Iwai 	err = snd_card_register(card);
2837a7b4cbfdSTakashi Iwai 	if (err < 0)
28381da177e4SLinus Torvalds 		return err;
28391da177e4SLinus Torvalds 	pci_set_drvdata(pci, card);
28401da177e4SLinus Torvalds 	dev++;
28411da177e4SLinus Torvalds 	return 0;
28421da177e4SLinus Torvalds }
28431da177e4SLinus Torvalds 
snd_es1968_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)2844de9a01bcSTakashi Iwai static int snd_es1968_probe(struct pci_dev *pci,
2845de9a01bcSTakashi Iwai 			    const struct pci_device_id *pci_id)
2846de9a01bcSTakashi Iwai {
2847de9a01bcSTakashi Iwai 	return snd_card_free_on_error(&pci->dev, __snd_es1968_probe(pci, pci_id));
2848de9a01bcSTakashi Iwai }
2849de9a01bcSTakashi Iwai 
2850e9f66d9bSTakashi Iwai static struct pci_driver es1968_driver = {
28513733e424STakashi Iwai 	.name = KBUILD_MODNAME,
28521da177e4SLinus Torvalds 	.id_table = snd_es1968_ids,
28531da177e4SLinus Torvalds 	.probe = snd_es1968_probe,
285468cb2b55STakashi Iwai 	.driver = {
285568cb2b55STakashi Iwai 		.pm = ES1968_PM_OPS,
285668cb2b55STakashi Iwai 	},
28571da177e4SLinus Torvalds };
28581da177e4SLinus Torvalds 
2859e9f66d9bSTakashi Iwai module_pci_driver(es1968_driver);
2860