]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] PA-RISC sound updates
authorMatthew Wilcox <willy@debian.org>
Sun, 22 Aug 2004 05:30:17 +0000 (22:30 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sun, 22 Aug 2004 05:30:17 +0000 (22:30 -0700)
PA-RISC sound updates:

 - Do a DAC/ADC reset for sampling rate changes in ad1889 (Randolph Chung)
 - Set the ad1889 interrupt configuration properly (Randolph Chung)
 - Fix dependency for the OSS Harmony driver (Thibaut Varene)
 - Forward port Stuart Brady's 2.4 Harmony driver patches (Thibaut Varene)
   - Fix sample skipping (Stuart Brady)
   - Prevent harmony_silence being called wrongly (Stuart Brady)
   - Fix crash caused by buf_to_fill becoming -1 (Stuart Brady)
   - Improve naming of mixer channels (Stuart Brady)
   - Implement SNDCTL_DSP_CHANNELS ioctl (Stuart Brady)
   - Improve toggling the recording source (Stuart Brady)
   - Sanity check MIXER_WRITE volume levels (Stuart Brady)
   - Fix MIXER_READ right_level return (Stuart Brady)
   - Reject AFMT_S16_LE format (Stuart Brady)
 - Fail OSS Harmony initialisation if no irq (Helge Deller)
 - Fix typos in ALSA Harmony (Andy Walker, Grant Grundler, Stuart Brady)

sound/oss/Kconfig
sound/oss/ad1889.c
sound/oss/ad1889.h
sound/oss/harmony.c
sound/parisc/harmony.c

index 05f6bc8ecee8dd2df9246352a8b6f8c29868e8c5..5859ca26ee4cda6fe97fd9b2bf9f0087f12c2acd 100644 (file)
@@ -162,7 +162,10 @@ config SOUND_ICH
 
 config SOUND_HARMONY
        tristate "PA Harmony audio driver"
-       depends on GSC_LASI && SOUND
+       depends on GSC_LASI && SOUND_PRIME!=n
+       help
+         Say 'Y' or 'M' to include support for Harmony soundchip
+         on HP 712, 715/new and many other GSC based machines.
 
 config SOUND_SONICVIBES
        tristate "S3 SonicVibes"
index 2423b1f2d59044e188f72f2c10b484b470fc0a1b..25477365397d6f975f0238c481ef63910726b235 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001 Randolph Chung <tausq@debian.org>
+ *  Copyright 2001-2004 Randolph Chung <tausq@debian.org>
  *
  *  Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
  *
@@ -61,6 +61,7 @@
 #define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
 
 //now 100ms
+/* #define WAIT_10MS() schedule_timeout(HZ/10) */
 #define WAIT_10MS()    do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
 
 /* currently only support a single device */
@@ -69,25 +70,43 @@ static ad1889_dev_t *ad1889_dev = NULL;
 /************************* helper routines ***************************** */
 static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
 {
+       struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+       DBG("Setting WAV rate to %d\n", rate);
        dev->state[AD_WAV_STATE].dmabuf.rate = rate;
        AD1889_WRITEW(dev, AD_DSWAS, rate);
+
+       /* Cycle the DAC to enable the new rate */
+       ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
+       WAIT_10MS();
+       ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
 }
 
 static inline void ad1889_set_adc_rate(ad1889_dev_t *dev, int rate)
 {
+       struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+       DBG("Setting ADC rate to %d\n", rate);
        dev->state[AD_ADC_STATE].dmabuf.rate = rate;
        AD1889_WRITEW(dev, AD_DSRES, rate);
+
+       /* Cycle the ADC to enable the new rate */
+       ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0100);
+       WAIT_10MS();
+       ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
 }
 
 static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
 {
        u16 tmp;
 
+       DBG("Setting WAV format to 0x%x\n", fmt);
+
        tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
-       if (fmt == AFMT_S16_LE) {
+       if (fmt & AFMT_S16_LE) {
                //tmp |= 0x0100; /* set WA16 */
                tmp |= 0x0300; /* set WA16 stereo */
-       } else if (fmt == AFMT_U8) {
+       } else if (fmt & AFMT_U8) {
                tmp &= ~0x0100; /* clear WA16 */
        } 
        AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
@@ -97,10 +116,12 @@ static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
 {
        u16 tmp;
 
+       DBG("Setting ADC format to 0x%x\n", fmt);
+
        tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
-       if (fmt == AFMT_S16_LE) {
+       if (fmt & AFMT_S16_LE) {
                tmp |= 0x0100; /* set WA16 */
-       } else if (fmt == AFMT_U8) {
+       } else if (fmt & AFMT_U8) {
                tmp &= ~0x0100; /* clear WA16 */
        } 
        AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
@@ -133,6 +154,9 @@ static void ad1889_start_wav(ad1889_state_t *state)
        dmabuf->dma_len = cnt;
        dmabuf->ready = 1;
 
+       DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
+           dmabuf->rd_ptr, dmabuf->dma_len);
+
         /* load up the current register set */
        AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
        AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
@@ -243,7 +267,7 @@ static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
                dmabuf->dma_handle = 0;
                dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
                dmabuf->ready = 0;
-               dmabuf->rate = 44100;
+               dmabuf->rate = 48000;
        }
        return dev;
 
@@ -472,7 +496,6 @@ static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t
                long cnt = count;
                unsigned long flags;
 
-
                for (;;) {
                        long used_bytes;
                        long timeout;   /* max time for DMA in jiffies */
@@ -498,17 +521,11 @@ static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t
                        }
 
                        set_current_state(TASK_INTERRUPTIBLE);
-                       if (!schedule_timeout(timeout + 1))
-                               printk(KERN_WARNING "AD1889 timeout(%ld) r/w %lx/%lx len %lx\n",
-                                   timeout+1,
-                                   dmabuf->rd_ptr, dmabuf->wr_ptr,
-                                   dmabuf->dma_len);
-
+                       schedule_timeout(timeout + 1);
                        if (signal_pending(current)) {
                                ret = -ERESTARTSYS;
                                goto err2;
                        }
-
                }
 
                /* watch out for wrapping around static buffer */
@@ -616,6 +633,8 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        audio_buf_info abinfo;
        int __user *p = (int __user *)arg;
 
+       DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
+
        switch (cmd)
        {
        case OSS_GETVERSION:
@@ -674,11 +693,15 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                if (get_user(val, p))
                        return -EFAULT;
 
-               if (file->f_mode & FMODE_READ) 
-                       ad1889_set_adc_fmt(dev, val);
+               if (val == 0) {
+                       if (file->f_mode & FMODE_READ) 
+                               ad1889_set_adc_fmt(dev, val);
 
-               if (file->f_mode & FMODE_WRITE) 
-                       ad1889_set_wav_fmt(dev, val);
+                       if (file->f_mode & FMODE_WRITE) 
+                               ad1889_set_wav_fmt(dev, val);
+               } else {
+                       val = AFMT_S16_LE | AFMT_U8;
+               }
 
                return put_user(val, p);
 
@@ -758,7 +781,7 @@ static int ad1889_open(struct inode *inode, struct file *file)
        
        file->private_data = ad1889_dev;
 
-       ad1889_set_wav_rate(ad1889_dev, 44100);
+       ad1889_set_wav_rate(ad1889_dev, 48000);
        ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
        AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
        return nonseekable_open(inode, file);
@@ -938,7 +961,6 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        ad1889_stop_wav(&dev->state[AD_WAV_STATE]);     /* clean up */
                        ad1889_start_wav(&dev->state[AD_WAV_STATE]);    /* start new */
                }
-
        }
 
        if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
@@ -952,18 +974,19 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 static void ad1889_initcfg(ad1889_dev_t *dev)
 {
-       u16 tmp;
+       u16 tmp16;
+       u32 tmp32;
 
        /* make sure the interrupt bits are setup the way we want */
-       tmp = AD1889_READW(dev, AD_DMAWAVCTRL);
-       tmp &= ~0x00ff; /* flat dma, no sg, mask out the intr bits */
-       tmp |= 0x0004;  /* intr on count, loop */
-       AD1889_WRITEW(dev, AD_DMAWAVCTRL, tmp);
+       tmp32 = AD1889_READL(dev, AD_DMAWAVCTRL);
+       tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
+       tmp32 |= 0x6;  /* intr on count, loop */
+       AD1889_WRITEL(dev, AD_DMAWAVCTRL, tmp32);
 
        /* unmute... */
-       tmp = AD1889_READW(dev, AD_DSWADA);
-       tmp &= ~0x8080;
-       AD1889_WRITEW(dev, AD_DSWADA, tmp);
+       tmp16 = AD1889_READW(dev, AD_DSWADA);
+       tmp16 &= ~0x8080;
+       AD1889_WRITEW(dev, AD_DSWADA, tmp16);
 }
 
 static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
index 5d13ef11d331e9910cf79f13924eb03d1b56fa05..964a6b4d5716aa7b383fb1588cd420340bbe6237 100644 (file)
@@ -34,9 +34,9 @@
 #define AD_DMAWAVICC   0x98    /* WAV interrupt current count */
 #define AD_DMAWAVIBC   0x9c    /* WAV interrupt base count */
 #define AD_DMARESCTRL  0xa0    /* RES PCI control/status */
-#define AD_DMAADCCTRL  0xa8    /* RES PCI control/status */
-#define AD_DMASYNCTRL  0xb0    /* RES PCI control/status */
-#define AD_DMAWAVCTRL  0xb8    /* RES PCI control/status */
+#define AD_DMAADCCTRL  0xa8    /* ADC PCI control/status */
+#define AD_DMASYNCTRL  0xb0    /* SYN PCI control/status */
+#define AD_DMAWAVCTRL  0xb8    /* WAV PCI control/status */
 #define AD_DMADISR     0xc0    /* PCI DMA intr status */
 #define AD_DMACHSS     0xc4    /* PCI DMA channel stop status */
 
index 22f0eff13809158b58147e84347a708e0884f1c8..d253dfea014fc374008179ec84d4aa05bc6c85ab 100644 (file)
@@ -12,6 +12,7 @@
        Copyright 2000-2003 (c) Helge Deller <deller@gmx.de>
        Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr>
        Copyright 2001 (c) Jean-Christophe Vaugeois <vaugeoij@esiee.fr>
+       Copyright 2004 (c) Stuart Brady <sdbrady@ntlworld.com>
 
                                
 TODO:
@@ -124,9 +125,17 @@ TODO:
 #define GAIN_RO_MASK    ( 0x3f << GAIN_RO_SHIFT) 
 
 
-#define MAX_OUTPUT_LEVEL (GAIN_RO_MASK >> GAIN_RO_SHIFT)
-#define MAX_INPUT_LEVEL  (GAIN_RI_MASK >> GAIN_RI_SHIFT)
-#define MAX_VOLUME_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+#define MAX_OUTPUT_LEVEL  (GAIN_RO_MASK >> GAIN_RO_SHIFT)
+#define MAX_INPUT_LEVEL   (GAIN_RI_MASK >> GAIN_RI_SHIFT)
+#define MAX_MONITOR_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+
+#define MIXER_INTERNAL   SOUND_MIXER_LINE1
+#define MIXER_LINEOUT    SOUND_MIXER_LINE2
+#define MIXER_HEADPHONES SOUND_MIXER_LINE3
+
+#define MASK_INTERNAL   SOUND_MASK_LINE1
+#define MASK_LINEOUT    SOUND_MASK_LINE2
+#define MASK_HEADPHONES SOUND_MASK_LINE3
 
 /*
  * Channels Mask in mixer register
@@ -543,6 +552,7 @@ static ssize_t harmony_audio_write(struct file *file,
        int count = 0;
        int frame_size;
        int buf_to_fill;
+       int fresh_buffer;
 
        if (!harmony.format_initialized) {
                if (harmony_format_auto_detect(buffer, total_count))
@@ -564,12 +574,16 @@ static ssize_t harmony_audio_write(struct file *file,
                
                
                buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play); 
-               if (harmony.play_offset)
+               if (harmony.play_offset) {
                        buf_to_fill--;
+                       buf_to_fill += MAX_BUFS;
+               }
                buf_to_fill %= MAX_BUFS;
-
+               
+               fresh_buffer = (harmony.play_offset == 0);
+               
                /* Figure out the size of the frame */
-               if ((total_count-count) > HARMONY_BUF_SIZE - harmony.play_offset) {
+               if ((total_count-count) >= HARMONY_BUF_SIZE - harmony.play_offset) {
                        frame_size = HARMONY_BUF_SIZE - harmony.play_offset;
                } else {
                        frame_size = total_count - count;
@@ -587,7 +601,7 @@ static ssize_t harmony_audio_write(struct file *file,
                CHECK_WBACK_INV_OFFSET(played_buf, (HARMONY_BUF_SIZE*buf_to_fill + harmony.play_offset), 
                                frame_size);
        
-               if (!harmony.play_offset)
+               if (fresh_buffer)
                        harmony.nb_filled_play++;
                
                count += frame_size;
@@ -650,18 +664,17 @@ static int harmony_audio_ioctl(struct inode *inode,
                        switch (ival) {
                        case AFMT_MU_LAW:       new_format = HARMONY_DF_8BIT_ULAW; break;
                        case AFMT_A_LAW:        new_format = HARMONY_DF_8BIT_ALAW; break;
-                       case AFMT_S16_LE:       /* fall through, but not really supported */
-                       case AFMT_S16_BE:       new_format = HARMONY_DF_16BIT_LINEAR;
-                                               ival = AFMT_S16_BE;
-                                               break; 
+                       case AFMT_S16_BE:       new_format = HARMONY_DF_16BIT_LINEAR; break;
                        default: {
                                DPRINTK(KERN_WARNING PFX 
                                        "unsupported sound format 0x%04x requested.\n",
                                        ival);
-                               return -EINVAL;
+                               ival = AFMT_S16_BE;
+                               return put_user(ival, (int *) arg);
                        }
                        }
                        harmony_set_format(new_format);
+                       return 0;
                } else {
                        switch (harmony.data_format) {
                        case HARMONY_DF_8BIT_ULAW:      ival = AFMT_MU_LAW; break;
@@ -669,8 +682,8 @@ static int harmony_audio_ioctl(struct inode *inode,
                        case HARMONY_DF_16BIT_LINEAR:   ival = AFMT_U16_BE; break;
                        default: ival = 0;
                        }
+                       return put_user(ival, (int *) arg);
                }
-               return put_user(ival, (int *) arg);
 
        case SOUND_PCM_READ_RATE:
                ival = harmony.dac_rate;
@@ -689,7 +702,17 @@ static int harmony_audio_ioctl(struct inode *inode,
                if (ival != 0 && ival != 1)
                        return -EINVAL;
                harmony_set_stereo(ival);
-               return put_user(ival, (int *) arg);
+               return 0;
+       case SNDCTL_DSP_CHANNELS:
+               if (get_user(ival, (int *) arg))
+                       return -EFAULT;
+               if (ival != 1 && ival != 2) {
+                       ival = harmony.stereo_select == HARMONY_SS_MONO ? 1 : 2;
+                       return put_user(ival, (int *) arg);
+               }
+               harmony_set_stereo(ival-1);
+               return 0;
 
        case SNDCTL_DSP_GETBLKSIZE:
                ival = HARMONY_BUF_SIZE;
@@ -887,7 +910,7 @@ static int harmony_mixer_get_level(int channel)
        int right_level;
 
        switch (channel) {
-               case SOUND_MIXER_OGAIN:
+               case SOUND_MIXER_VOLUME:
                        left_level  = (harmony.current_gain & GAIN_LO_MASK) >> GAIN_LO_SHIFT;
                        right_level = (harmony.current_gain & GAIN_RO_MASK) >> GAIN_RO_SHIFT;
                        left_level  = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL);
@@ -901,10 +924,10 @@ static int harmony_mixer_get_level(int channel)
                        right_level= to_oss_level(right_level, MAX_INPUT_LEVEL);
                        return (right_level << 8)+left_level;
                        
-               case SOUND_MIXER_VOLUME:
+               case SOUND_MIXER_MONITOR:
                        left_level = (harmony.current_gain & GAIN_MA_MASK) >> GAIN_MA_SHIFT;
-                       left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-                       return left_level;
+                       left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+                       return (left_level << 8)+left_level;
        }
        return -EINVAL;
 }
@@ -926,9 +949,11 @@ static int harmony_mixer_set_level(int channel, int value)
 
        right_level = (value & 0x0000ff00) >> 8;
        left_level = value & 0x000000ff;
+       if (right_level > 100) right_level = 100;
+       if (left_level > 100) left_level = 100;
   
        switch (channel) {
-               case SOUND_MIXER_OGAIN:
+               case SOUND_MIXER_VOLUME:
                        right_level = to_harmony_level(100-right_level, MAX_OUTPUT_LEVEL);
                        left_level  = to_harmony_level(100-left_level, MAX_OUTPUT_LEVEL);
                        new_right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL);
@@ -948,12 +973,12 @@ static int harmony_mixer_set_level(int channel, int value)
                        harmony_mixer_set_gain();
                        return (new_right_level << 8) + new_left_level;
        
-               case SOUND_MIXER_VOLUME:
-                       left_level = to_harmony_level(100-left_level, MAX_VOLUME_LEVEL);
-                       new_left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-                       harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK)| (left_level << GAIN_MA_SHIFT);
+               case SOUND_MIXER_MONITOR:
+                       left_level = to_harmony_level(100-left_level, MAX_MONITOR_LEVEL);
+                       new_left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+                       harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK) | (left_level << GAIN_MA_SHIFT);
                        harmony_mixer_set_gain();
-                       return new_left_level;
+                       return (new_left_level << 8) + new_left_level;
        }
 
        return -EINVAL;
@@ -986,11 +1011,15 @@ static int harmony_mixer_set_recmask(int recmask)
 {
        int new_input_line;
        int new_input_mask;
-
-       if ((recmask & SOUND_MASK_LINE)) {
+       int current_input_line;
+       
+       current_input_line = (harmony.current_gain & GAIN_IS_MASK)
+                                   >> GAIN_IS_SHIFT;
+       if ((current_input_line && ((recmask & SOUND_MASK_LINE) || !(recmask & SOUND_MASK_MIC))) ||
+               (!current_input_line && ((recmask & SOUND_MASK_LINE) && !(recmask & SOUND_MASK_MIC)))) {
                new_input_line = 0;
                new_input_mask = SOUND_MASK_LINE;
-       } else  {
+       } else {
                new_input_line = 1;
                new_input_mask = SOUND_MASK_MIC;
        }
@@ -1009,9 +1038,9 @@ static int harmony_mixer_get_outmask(void)
 {
        int outmask = 0;
        
-       if (harmony.current_gain & GAIN_HE_MASK) outmask |=SOUND_MASK_PHONEOUT;
-       if (harmony.current_gain & GAIN_LE_MASK) outmask |=SOUND_MASK_LINE;
-       if (harmony.current_gain & GAIN_SE_MASK) outmask |=SOUND_MASK_SPEAKER;
+       if (harmony.current_gain & GAIN_SE_MASK) outmask |= MASK_INTERNAL;
+       if (harmony.current_gain & GAIN_LE_MASK) outmask |= MASK_LINEOUT;
+       if (harmony.current_gain & GAIN_HE_MASK) outmask |= MASK_HEADPHONES;
        
        return outmask;
 }
@@ -1019,24 +1048,24 @@ static int harmony_mixer_get_outmask(void)
 
 static int harmony_mixer_set_outmask(int outmask)
 {
-       if (outmask & SOUND_MASK_PHONEOUT
-               harmony.current_gain |= GAIN_HE_MASK; 
+       if (outmask & MASK_INTERNAL
+               harmony.current_gain |= GAIN_SE_MASK;
        else 
-               harmony.current_gain &= ~GAIN_HE_MASK;
+               harmony.current_gain &= ~GAIN_SE_MASK;
        
-       if (outmask & SOUND_MASK_LINE
+       if (outmask & MASK_LINEOUT
                harmony.current_gain |= GAIN_LE_MASK;
        else 
                harmony.current_gain &= ~GAIN_LE_MASK;
        
-       if (outmask & SOUND_MASK_SPEAKER
-               harmony.current_gain |= GAIN_SE_MASK;
+       if (outmask & MASK_HEADPHONES
+               harmony.current_gain |= GAIN_HE_MASK; 
        else 
-               harmony.current_gain &= ~GAIN_SE_MASK;
+               harmony.current_gain &= ~GAIN_HE_MASK;
        
        harmony_mixer_set_gain();
 
-       return (outmask & (SOUND_MASK_PHONEOUT | SOUND_MASK_LINE | SOUND_MASK_SPEAKER));
+       return (outmask & (MASK_INTERNAL | MASK_LINEOUT | MASK_HEADPHONES));
 }
 
 /*
@@ -1074,19 +1103,19 @@ static int harmony_mixer_ioctl(struct inode * inode, struct file * file,
                ret = SOUND_CAP_EXCL_INPUT;
                break;
        case MIXER_READ(SOUND_MIXER_STEREODEVS):
-               ret = SOUND_MASK_IGAIN | SOUND_MASK_OGAIN;
+               ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN;
                break;
                
        case MIXER_READ(SOUND_MIXER_RECMASK):
                ret = SOUND_MASK_MIC | SOUND_MASK_LINE;
                break;
        case MIXER_READ(SOUND_MIXER_DEVMASK):
-               ret = SOUND_MASK_OGAIN | SOUND_MASK_IGAIN |
-                       SOUND_MASK_VOLUME;
+               ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN |
+                       SOUND_MASK_MONITOR;
                break;
        case MIXER_READ(SOUND_MIXER_OUTMASK):
-               ret = SOUND_MASK_SPEAKER | SOUND_MASK_LINE |
-                       SOUND_MASK_PHONEOUT;
+               ret = MASK_INTERNAL | MASK_LINEOUT |
+                       MASK_HEADPHONES;
                break;
                
        case MIXER_WRITE(SOUND_MIXER_RECSRC):
@@ -1103,15 +1132,15 @@ static int harmony_mixer_ioctl(struct inode * inode, struct file * file,
                ret = harmony_mixer_get_outmask();
                break;
        
-       case MIXER_WRITE(SOUND_MIXER_OGAIN):
-       case MIXER_WRITE(SOUND_MIXER_IGAIN):
        case MIXER_WRITE(SOUND_MIXER_VOLUME):
+       case MIXER_WRITE(SOUND_MIXER_IGAIN):
+       case MIXER_WRITE(SOUND_MIXER_MONITOR):
                ret = harmony_mixer_set_level(cmd & 0xff, val);
                break;
 
-       case MIXER_READ(SOUND_MIXER_OGAIN):
-       case MIXER_READ(SOUND_MIXER_IGAIN):
        case MIXER_READ(SOUND_MIXER_VOLUME):
+       case MIXER_READ(SOUND_MIXER_IGAIN):
+       case MIXER_READ(SOUND_MIXER_MONITOR):
                ret = harmony_mixer_get_level(cmd & 0xff);
                break;
 
@@ -1201,16 +1230,15 @@ harmony_driver_probe(struct parisc_device *dev)
                return -EBUSY;
        }
 
-       harmony.dev = dev;
-
-       /* Set the HPA of harmony */
-       harmony.hpa = (struct harmony_hpa *)dev->hpa;
-
-       if (!harmony.dev->irq) {
+       if (!dev->irq) {
                printk(KERN_ERR PFX "no irq found\n");
                return -ENODEV;
        }
 
+       /* Set the HPA of harmony */
+       harmony.hpa = (struct harmony_hpa *)dev->hpa;
+       harmony.dev = dev;
+
        /* Grab the ID and revision from the device */
        id = gsc_readb(&harmony.hpa->id);
        if ((id | 1) != 0x15) {
index 423ab05c0480f0003f2d88375d94543ea6be4061..53ecf3efeb8c02d6e65826a71a1e6303b81fde0f 100644 (file)
@@ -6,7 +6,7 @@
  *
  *     Harmony is found in HP 712s, 715/new and many other GSC based machines.
  *     On older 715 machines you'll find the technically identical chip 
- *     called 'Vivace'. Both Harmony and Vicace are supported by this driver.
+ *     called 'Vivace'. Both Harmony and Vivace are supported by this driver.
  *
  *  this ALSA driver is based on OSS driver by:
  *     Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
@@ -43,7 +43,7 @@
  * to be recorded is put in RNXTADD. There is 2 read-only registers, PCURADD and 
  * RCURADD that provides adress of current page.
  * 
- * Harmony has no way to controll full duplex or half duplex mode. It means
+ * Harmony has no way to control full duplex or half duplex mode. It means
  * that we always need to provide adresses of playback and capture data, even
  * when this is not needed. That's why we statically alloc one graveyard
  * buffer (to put recorded data in play-only mode) and a silence buffer.
@@ -556,7 +556,7 @@ static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream)
        harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 
        /* data format */
-       harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+       harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 
        /* number of channels */
        if (runtime->channels == 2)
@@ -587,7 +587,7 @@ static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream)
        harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
        
        /* data format */
-       harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+       harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
        
        /* number of channels */
        if (runtime->channels == 1)