ES978 docking support for Maestro 2E - advice requested
PATCH 1/1 ES978 docking support for Maestro 2E - advice requested
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.
drivers/sound/maestro.c renamed from root/linux-2.4.4.clean/drivers/sound/maestro.c +79 -14
@@ -115,6 +115,8 @@* themselves, but we'll see. * * History +* (still kind of v0.14) May 13 2001 - Ben Pfaff <[email protected]> +* Add support for 978 docking and basic hardware volume control * (still kind of v0.14) Nov 23 - Alan Cox <[email protected]> * Add clocking= for people with seriously warped hardware * (still v0.14) Nov 10 2000 - Bartlomiej Zolnierkiewicz <[email protected]>
@@ -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++)
Signature · 4 lines
"Unix... is not so much a product as it is a painstakingly compiled oral history of the hacker subculture." --Neal Stephenson