public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch] ES978 docking support for Maestro 2E - advice requested
@ 2001-05-13 21:22 Ben Pfaff
  0 siblings, 0 replies; only message in thread
From: Ben Pfaff @ 2001-05-13 21:22 UTC (permalink / raw)
  To: linux-kernel

Hi.  I have an Compaq Armada M700 laptop and an ArmadaStation II
laptop.  The laptop has a Maestro 2E sound chipset in it, and the
docking station has the matching ES978 chip which controls
speakers and handles volume up/down/mute buttons on the side of
the docking station.  The maestro.c driver in 2.4.4 doesn't have
support for these, so I wrote some code to do it.  The following
patch adds support.  It does the following:

	* Turns on the docking station speakers and sets the
          playback volume on them to the max.  (Their volume is
          still scaled based on the Maestro's master volume.)

	* Adds basic support for the hardware volume control
          buttons: the up button increases volume by 10%, the
          down button decreases volume by 10%, the mute button
          toggles the master volume on and off.

It doesn't do any of the following:

	* Add the docking station volumes to the mixer--it just
          hard-wires them to the max values.  Should I do this?

	* Make the buttons from the hardware volume control
          available to software.  Should I do this (I assume that
          hard-wiring +/- 10% isn't really acceptable)?  What's
          the best way to do it--create a /dev/es978buttons and a
          daemon, or what?

	* Add any support for the recording features of the
          docking station--just playback.

All comments appreciated.

--- /root/linux-2.4.4.clean/drivers/sound/maestro.c	Fri Mar  2 14:12:11 2001
+++ linux-2.4.5pre1/drivers/sound/maestro.c	Sun May 13 17:14:07 2001
@@ -115,6 +115,8 @@
  *	themselves, but we'll see.  
  *	
  * History
+ *  (still kind of v0.14) May 13 2001 - Ben Pfaff <pfaffben@msu.edu>
+ *      Add support for 978 docking and basic hardware volume control
  *  (still kind of v0.14) Nov 23 - Alan Cox <alan@redhat.com>
  *	Add clocking= for people with seriously warped hardware
  *  (still v0.14) Nov 10 2000 - Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
@@ -189,7 +191,7 @@
  *	fix bob frequency
  *	endianness
  *	do smart things with ac97 2.0 bits.
- *	docking and dual codecs and 978?
+ *	dual codecs
  *	leave 54->61 open
  *
  *	it also would be fun to have a mode that would not use pci dma at all
@@ -483,8 +485,12 @@
 
 	int bob_freq;
 	char dsps_open;
+
+	int dock_mute_vol;
 };
 
+static void set_mixer(struct ess_card *card,unsigned int mixer, unsigned int val );
+
 static unsigned 
 ld2(unsigned int x)
 {
@@ -983,6 +989,17 @@
 		outw(inw(ioaddr+0x68) | 0x600, ioaddr + 0x68);
 		outw(0x0209, ioaddr + 0x60);
 	}
+
+	/* Turn on the 978 docking chip.
+	   First frob the "master output enable" bit,
+	   then set most of the playback volume control registers to max. */
+	outb(inb(ioaddr+0xc0)|(1<<5), ioaddr+0xc0);
+	outb(0xff, ioaddr+0xc3);
+	outb(0xff, ioaddr+0xc4);
+	outb(0xff, ioaddr+0xc6);
+	outb(0xff, ioaddr+0xc8);
+	outb(0x3f, ioaddr+0xcf);
+	outb(0x3f, ioaddr+0xd0);
 }
 /*
  *	Indirect register access. Not all registers are readable so we
@@ -1895,19 +1912,52 @@
 	outw(inw(c->iobase+4)&1, c->iobase+4);
 
 /*	M_printk("maestro int: %x\n",event);*/
-
 	if(event&(1<<6))
 	{
-		/* XXX if we have a hw volume control int enable
-			all the ints?  doesn't make sense.. */
-		event = inw(c->iobase+0x18);
-		outb(0xFF, c->iobase+0x1A);
-	}
-	else
-	{
-		/* else ack 'em all, i imagine */
-		outb(0xFF, c->iobase+0x1A);
+		int x;
+		enum {UP_EVT, DOWN_EVT, MUTE_EVT} vol_evt;
+		int volume;
+
+		/* Figure out which volume control button was pushed,
+		   based on differences from the default register
+		   values. */
+		x = inb(c->iobase+0x1c);
+		if (x&1) vol_evt = MUTE_EVT;
+		else if (((x>>1)&7) > 4) vol_evt = UP_EVT;
+		else vol_evt = DOWN_EVT;
+
+		/* Reset the volume control registers. */
+		outb(0x88, c->iobase+0x1c);
+		outb(0x88, c->iobase+0x1d);
+		outb(0x88, c->iobase+0x1e);
+		outb(0x88, c->iobase+0x1f);
+
+		/* Deal with the button press in a hammer-handed
+		   manner by adjusting the master mixer volume. */
+		volume = c->mix.mixer_state[0] & 0xff;
+		if (vol_evt == UP_EVT) {
+			volume += 10;
+			if (volume > 100)
+				volume = 100;
+		}
+		else if (vol_evt == DOWN_EVT) {
+			volume -= 10;
+			if (volume < 0)
+				volume = 0;
+		} else {
+			/* vol_evt == MUTE_EVT */
+			if (volume == 0)
+				volume = c->dock_mute_vol;
+			else {
+				c->dock_mute_vol = volume;
+				volume = 0;
+			}
+		}
+		set_mixer (c, 0, (volume << 8) | volume);
 	}
+
+	/* Ack all the interrupts. */
+	outb(0xFF, c->iobase+0x1A);
 		
 	/*
 	 *	Update the pointers for all APU's we are running.
@@ -3087,8 +3137,8 @@
 	/* XXX how do we know which to use? */
 	w&=~(1<<14);		/* External clock */
 	
-	w&=~(1<<7);		/* HWV off */
-	w&=~(1<<6);		/* Debounce off */
+	w|= (1<<7);		/* Hardware volume control on */
+	w|= (1<<6);		/* Debounce off: easier to push the HWV buttons. */
 	w&=~(1<<5);		/* GPIO 4:5 */
 	w|= (1<<4);             /* Disconnect from the CHI.  Enabling this made a dell 7500 work. */
 	w&=~(1<<2);		/* MIDI fix off (undoc) */
@@ -3106,6 +3156,12 @@
 	 
 	pci_write_config_word(pcidev, 0x40, w);
 
+	/* Set up 978 docking control chip. */
+	pci_read_config_word(pcidev, 0x58, &w);
+	w|=1<<2;	/* Enable 978. */
+	w|=1<<3;	/* Turn on 978 hardware volume control. */
+	w&=~(1<<11);	/* Turn on 978 mixer volume control. */
+	pci_write_config_word(pcidev, 0x58, w);
 	
 	sound_reset(iobase);
 
@@ -3170,7 +3226,7 @@
 	outw(w, iobase+0x18);
 
 	w=inw(iobase+0x18);
-	w&=~(1<<6);		/* Harpo off */
+	w|=1<<6;		/* Hardware volume control interrupt on. */
 	outw(w, iobase+0x18);
 	
 	w=inw(iobase+0x18);
@@ -3193,6 +3249,13 @@
 	w|=(1<<0);		/* SB IRQ on */
 	outw(w, iobase+0x18);
 
+	/* Set hardware volume control registers to midpoints.
+	   We can tell which button was pushed based on how they change. */
+	outb(0x88, iobase+0x1c);
+	outb(0x88, iobase+0x1d);
+	outb(0x88, iobase+0x1e);
+	outb(0x88, iobase+0x1f);
+
 	/* it appears some maestros (dell 7500) only work if these are set,
 		regardless of wether we use the assp or not. */
 
@@ -3366,6 +3429,8 @@
 	spin_lock_init(&card->lock);
 	init_waitqueue_head(&card->suspend_queue);
 	devs = card;
+
+	card->dock_mute_vol = 50;
 	
 	/* init our groups of 6 apus */
 	for(i=0;i<NR_DSPS;i++)

-- 
"Unix... is not so much a product
 as it is a painstakingly compiled oral history
 of the hacker subculture."
--Neal Stephenson

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2001-05-13 21:22 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-05-13 21:22 [patch] ES978 docking support for Maestro 2E - advice requested Ben Pfaff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox