Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Hewlett-Packard Harmony audio driver
0003  *
0004  *   This is a driver for the Harmony audio chipset found
0005  *   on the LASI ASIC of various early HP PA-RISC workstations.
0006  *
0007  *   Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}>
0008  *
0009  *     Based on the previous Harmony incarnations by,
0010  *       Copyright 2000 (c) Linuxcare Canada, Alex deVries
0011  *       Copyright 2000-2003 (c) Helge Deller
0012  *       Copyright 2001 (c) Matthieu Delahaye
0013  *       Copyright 2001 (c) Jean-Christophe Vaugeois
0014  *       Copyright 2003 (c) Laurent Canet
0015  *       Copyright 2004 (c) Stuart Brady
0016  *
0017  * Notes:
0018  *   - graveyard and silence buffers last for lifetime of
0019  *     the driver. playback and capture buffers are allocated
0020  *     per _open()/_close().
0021  * 
0022  * TODO:
0023  */
0024 
0025 #include <linux/init.h>
0026 #include <linux/slab.h>
0027 #include <linux/time.h>
0028 #include <linux/wait.h>
0029 #include <linux/delay.h>
0030 #include <linux/module.h>
0031 #include <linux/interrupt.h>
0032 #include <linux/spinlock.h>
0033 #include <linux/dma-mapping.h>
0034 #include <linux/io.h>
0035 
0036 #include <sound/core.h>
0037 #include <sound/pcm.h>
0038 #include <sound/control.h>
0039 #include <sound/rawmidi.h>
0040 #include <sound/initval.h>
0041 #include <sound/info.h>
0042 
0043 #include <asm/hardware.h>
0044 #include <asm/parisc-device.h>
0045 
0046 #include "harmony.h"
0047 
0048 static int index = SNDRV_DEFAULT_IDX1;  /* Index 0-MAX */
0049 static char *id = SNDRV_DEFAULT_STR1;   /* ID for this card */
0050 module_param(index, int, 0444);
0051 MODULE_PARM_DESC(index, "Index value for Harmony driver.");
0052 module_param(id, charp, 0444);
0053 MODULE_PARM_DESC(id, "ID string for Harmony driver.");
0054 
0055 
0056 static const struct parisc_device_id snd_harmony_devtable[] __initconst = {
0057     /* bushmaster / flounder */
0058     { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, 
0059     /* 712 / 715 */
0060     { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, 
0061     /* pace */
0062     { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, 
0063     /* outfield / coral II */
0064     { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F },
0065     { 0, }
0066 };
0067 
0068 MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable);
0069 
0070 #define NAME "harmony"
0071 #define PFX  NAME ": "
0072 
0073 static const unsigned int snd_harmony_rates[] = {
0074     5512, 6615, 8000, 9600,
0075     11025, 16000, 18900, 22050,
0076     27428, 32000, 33075, 37800,
0077     44100, 48000
0078 };
0079 
0080 static const unsigned int rate_bits[14] = {
0081     HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ,
0082     HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ,
0083     HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ,
0084     HARMONY_SR_32KHZ, HARMONY_SR_33KHZ, HARMONY_SR_37KHZ,
0085     HARMONY_SR_44KHZ, HARMONY_SR_48KHZ
0086 };
0087 
0088 static const struct snd_pcm_hw_constraint_list hw_constraint_rates = {
0089     .count = ARRAY_SIZE(snd_harmony_rates),
0090     .list = snd_harmony_rates,
0091     .mask = 0,
0092 };
0093 
0094 static inline unsigned long
0095 harmony_read(struct snd_harmony *h, unsigned r)
0096 {
0097     return __raw_readl(h->iobase + r);
0098 }
0099 
0100 static inline void
0101 harmony_write(struct snd_harmony *h, unsigned r, unsigned long v)
0102 {
0103     __raw_writel(v, h->iobase + r);
0104 }
0105 
0106 static inline void
0107 harmony_wait_for_control(struct snd_harmony *h)
0108 {
0109     while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ;
0110 }
0111 
0112 static inline void
0113 harmony_reset(struct snd_harmony *h)
0114 {
0115     harmony_write(h, HARMONY_RESET, 1);
0116     mdelay(50);
0117     harmony_write(h, HARMONY_RESET, 0);
0118 }
0119 
0120 static void
0121 harmony_disable_interrupts(struct snd_harmony *h)
0122 {
0123     u32 dstatus;
0124     harmony_wait_for_control(h);
0125     dstatus = harmony_read(h, HARMONY_DSTATUS);
0126     dstatus &= ~HARMONY_DSTATUS_IE;
0127     harmony_write(h, HARMONY_DSTATUS, dstatus);
0128 }
0129 
0130 static void
0131 harmony_enable_interrupts(struct snd_harmony *h)
0132 {
0133     u32 dstatus;
0134     harmony_wait_for_control(h);
0135     dstatus = harmony_read(h, HARMONY_DSTATUS);
0136     dstatus |= HARMONY_DSTATUS_IE;
0137     harmony_write(h, HARMONY_DSTATUS, dstatus);
0138 }
0139 
0140 static void
0141 harmony_mute(struct snd_harmony *h)
0142 {
0143     unsigned long flags;
0144 
0145     spin_lock_irqsave(&h->mixer_lock, flags);
0146     harmony_wait_for_control(h);
0147     harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE);
0148     spin_unlock_irqrestore(&h->mixer_lock, flags);
0149 }
0150 
0151 static void
0152 harmony_unmute(struct snd_harmony *h)
0153 {
0154     unsigned long flags;
0155 
0156     spin_lock_irqsave(&h->mixer_lock, flags);
0157     harmony_wait_for_control(h);
0158     harmony_write(h, HARMONY_GAINCTL, h->st.gain);
0159     spin_unlock_irqrestore(&h->mixer_lock, flags);
0160 }
0161 
0162 static void
0163 harmony_set_control(struct snd_harmony *h)
0164 {
0165     u32 ctrl;
0166     unsigned long flags;
0167 
0168     spin_lock_irqsave(&h->lock, flags);
0169 
0170     ctrl = (HARMONY_CNTL_C      |
0171         (h->st.format << 6) |
0172         (h->st.stereo << 5) |
0173         (h->st.rate));
0174 
0175     harmony_wait_for_control(h);
0176     harmony_write(h, HARMONY_CNTL, ctrl);
0177 
0178     spin_unlock_irqrestore(&h->lock, flags);
0179 }
0180 
0181 static irqreturn_t
0182 snd_harmony_interrupt(int irq, void *dev)
0183 {
0184     u32 dstatus;
0185     struct snd_harmony *h = dev;
0186 
0187     spin_lock(&h->lock);
0188     harmony_disable_interrupts(h);
0189     harmony_wait_for_control(h);
0190     dstatus = harmony_read(h, HARMONY_DSTATUS);
0191     spin_unlock(&h->lock);
0192 
0193     if (dstatus & HARMONY_DSTATUS_PN) {
0194         if (h->psubs && h->st.playing) {
0195             spin_lock(&h->lock);
0196             h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */
0197             h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */
0198 
0199             harmony_write(h, HARMONY_PNXTADD, 
0200                       h->pbuf.addr + h->pbuf.buf);
0201             h->stats.play_intr++;
0202             spin_unlock(&h->lock);
0203                         snd_pcm_period_elapsed(h->psubs);
0204         } else {
0205             spin_lock(&h->lock);
0206             harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
0207             h->stats.silence_intr++;
0208             spin_unlock(&h->lock);
0209         }
0210     }
0211 
0212     if (dstatus & HARMONY_DSTATUS_RN) {
0213         if (h->csubs && h->st.capturing) {
0214             spin_lock(&h->lock);
0215             h->cbuf.buf += h->cbuf.count;
0216             h->cbuf.buf %= h->cbuf.size;
0217 
0218             harmony_write(h, HARMONY_RNXTADD,
0219                       h->cbuf.addr + h->cbuf.buf);
0220             h->stats.rec_intr++;
0221             spin_unlock(&h->lock);
0222                         snd_pcm_period_elapsed(h->csubs);
0223         } else {
0224             spin_lock(&h->lock);
0225             harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
0226             h->stats.graveyard_intr++;
0227             spin_unlock(&h->lock);
0228         }
0229     }
0230 
0231     spin_lock(&h->lock);
0232     harmony_enable_interrupts(h);
0233     spin_unlock(&h->lock);
0234 
0235     return IRQ_HANDLED;
0236 }
0237 
0238 static unsigned int 
0239 snd_harmony_rate_bits(int rate)
0240 {
0241     unsigned int i;
0242     
0243     for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++)
0244         if (snd_harmony_rates[i] == rate)
0245             return rate_bits[i];
0246 
0247     return HARMONY_SR_44KHZ;
0248 }
0249 
0250 static const struct snd_pcm_hardware snd_harmony_playback =
0251 {
0252     .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 
0253          SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
0254          SNDRV_PCM_INFO_BLOCK_TRANSFER),
0255     .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
0256             SNDRV_PCM_FMTBIT_A_LAW),
0257     .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
0258           SNDRV_PCM_RATE_KNOT),
0259     .rate_min = 5512,
0260     .rate_max = 48000,
0261     .channels_min = 1,
0262     .channels_max = 2,
0263     .buffer_bytes_max = MAX_BUF_SIZE,
0264     .period_bytes_min = BUF_SIZE,
0265     .period_bytes_max = BUF_SIZE,
0266     .periods_min = 1,
0267     .periods_max = MAX_BUFS,
0268     .fifo_size = 0,
0269 };
0270 
0271 static const struct snd_pcm_hardware snd_harmony_capture =
0272 {
0273         .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
0274                  SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
0275                  SNDRV_PCM_INFO_BLOCK_TRANSFER),
0276         .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
0277                     SNDRV_PCM_FMTBIT_A_LAW),
0278         .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
0279           SNDRV_PCM_RATE_KNOT),
0280         .rate_min = 5512,
0281         .rate_max = 48000,
0282         .channels_min = 1,
0283         .channels_max = 2,
0284         .buffer_bytes_max = MAX_BUF_SIZE,
0285         .period_bytes_min = BUF_SIZE,
0286         .period_bytes_max = BUF_SIZE,
0287         .periods_min = 1,
0288         .periods_max = MAX_BUFS,
0289         .fifo_size = 0,
0290 };
0291 
0292 static int
0293 snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd)
0294 {
0295     struct snd_harmony *h = snd_pcm_substream_chip(ss);
0296 
0297     if (h->st.capturing)
0298         return -EBUSY;
0299 
0300     spin_lock(&h->lock);
0301     switch (cmd) {
0302     case SNDRV_PCM_TRIGGER_START:
0303         h->st.playing = 1;
0304         harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr);
0305         harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
0306         harmony_unmute(h);
0307         harmony_enable_interrupts(h);
0308         break;
0309     case SNDRV_PCM_TRIGGER_STOP:
0310         h->st.playing = 0;
0311         harmony_mute(h);
0312         harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
0313         harmony_disable_interrupts(h);
0314         break;
0315     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0316     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0317     case SNDRV_PCM_TRIGGER_SUSPEND:
0318     default:
0319         spin_unlock(&h->lock);
0320         snd_BUG();
0321         return -EINVAL;
0322     }
0323     spin_unlock(&h->lock);
0324     
0325     return 0;
0326 }
0327 
0328 static int
0329 snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd)
0330 {
0331         struct snd_harmony *h = snd_pcm_substream_chip(ss);
0332 
0333     if (h->st.playing)
0334         return -EBUSY;
0335 
0336     spin_lock(&h->lock);
0337         switch (cmd) {
0338         case SNDRV_PCM_TRIGGER_START:
0339         h->st.capturing = 1;
0340                 harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
0341                 harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr);
0342         harmony_unmute(h);
0343                 harmony_enable_interrupts(h);
0344         break;
0345         case SNDRV_PCM_TRIGGER_STOP:
0346         h->st.capturing = 0;
0347         harmony_mute(h);
0348         harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
0349         harmony_disable_interrupts(h);
0350         break;
0351         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0352         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0353         case SNDRV_PCM_TRIGGER_SUSPEND:
0354     default:
0355         spin_unlock(&h->lock);
0356         snd_BUG();
0357                 return -EINVAL;
0358         }
0359     spin_unlock(&h->lock);
0360         
0361         return 0;
0362 }
0363 
0364 static int
0365 snd_harmony_set_data_format(struct snd_harmony *h, int fmt, int force)
0366 {
0367     int o = h->st.format;
0368     int n;
0369 
0370     switch(fmt) {
0371     case SNDRV_PCM_FORMAT_S16_BE:
0372         n = HARMONY_DF_16BIT_LINEAR;
0373         break;
0374     case SNDRV_PCM_FORMAT_A_LAW:
0375         n = HARMONY_DF_8BIT_ALAW;
0376         break;
0377     case SNDRV_PCM_FORMAT_MU_LAW:
0378         n = HARMONY_DF_8BIT_ULAW;
0379         break;
0380     default:
0381         n = HARMONY_DF_16BIT_LINEAR;
0382         break;
0383     }
0384 
0385     if (force || o != n) {
0386         snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ / 
0387                        (snd_pcm_format_physical_width(fmt)
0388                         / 8));
0389     }
0390 
0391     return n;
0392 }
0393 
0394 static int
0395 snd_harmony_playback_prepare(struct snd_pcm_substream *ss)
0396 {
0397     struct snd_harmony *h = snd_pcm_substream_chip(ss);
0398     struct snd_pcm_runtime *rt = ss->runtime;
0399     
0400     if (h->st.capturing)
0401         return -EBUSY;
0402     
0403     h->pbuf.size = snd_pcm_lib_buffer_bytes(ss);
0404     h->pbuf.count = snd_pcm_lib_period_bytes(ss);
0405     if (h->pbuf.buf >= h->pbuf.size)
0406         h->pbuf.buf = 0;
0407     h->st.playing = 0;
0408 
0409     h->st.rate = snd_harmony_rate_bits(rt->rate);
0410     h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
0411     
0412     if (rt->channels == 2)
0413         h->st.stereo = HARMONY_SS_STEREO;
0414     else
0415         h->st.stereo = HARMONY_SS_MONO;
0416 
0417     harmony_set_control(h);
0418 
0419     h->pbuf.addr = rt->dma_addr;
0420 
0421     return 0;
0422 }
0423 
0424 static int
0425 snd_harmony_capture_prepare(struct snd_pcm_substream *ss)
0426 {
0427         struct snd_harmony *h = snd_pcm_substream_chip(ss);
0428         struct snd_pcm_runtime *rt = ss->runtime;
0429 
0430     if (h->st.playing)
0431         return -EBUSY;
0432 
0433         h->cbuf.size = snd_pcm_lib_buffer_bytes(ss);
0434         h->cbuf.count = snd_pcm_lib_period_bytes(ss);
0435     if (h->cbuf.buf >= h->cbuf.size)
0436             h->cbuf.buf = 0;
0437     h->st.capturing = 0;
0438 
0439         h->st.rate = snd_harmony_rate_bits(rt->rate);
0440         h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
0441 
0442         if (rt->channels == 2)
0443                 h->st.stereo = HARMONY_SS_STEREO;
0444         else
0445                 h->st.stereo = HARMONY_SS_MONO;
0446 
0447         harmony_set_control(h);
0448 
0449         h->cbuf.addr = rt->dma_addr;
0450 
0451         return 0;
0452 }
0453 
0454 static snd_pcm_uframes_t 
0455 snd_harmony_playback_pointer(struct snd_pcm_substream *ss)
0456 {
0457     struct snd_pcm_runtime *rt = ss->runtime;
0458     struct snd_harmony *h = snd_pcm_substream_chip(ss);
0459     unsigned long pcuradd;
0460     unsigned long played;
0461 
0462     if (!(h->st.playing) || (h->psubs == NULL)) 
0463         return 0;
0464 
0465     if ((h->pbuf.addr == 0) || (h->pbuf.size == 0))
0466         return 0;
0467     
0468     pcuradd = harmony_read(h, HARMONY_PCURADD);
0469     played = pcuradd - h->pbuf.addr;
0470 
0471 #ifdef HARMONY_DEBUG
0472     printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n", 
0473            pcuradd, h->pbuf.addr, played);  
0474 #endif
0475 
0476     if (pcuradd > h->pbuf.addr + h->pbuf.size) {
0477         return 0;
0478     }
0479 
0480     return bytes_to_frames(rt, played);
0481 }
0482 
0483 static snd_pcm_uframes_t
0484 snd_harmony_capture_pointer(struct snd_pcm_substream *ss)
0485 {
0486         struct snd_pcm_runtime *rt = ss->runtime;
0487         struct snd_harmony *h = snd_pcm_substream_chip(ss);
0488         unsigned long rcuradd;
0489         unsigned long caught;
0490 
0491         if (!(h->st.capturing) || (h->csubs == NULL))
0492                 return 0;
0493 
0494         if ((h->cbuf.addr == 0) || (h->cbuf.size == 0))
0495                 return 0;
0496 
0497         rcuradd = harmony_read(h, HARMONY_RCURADD);
0498         caught = rcuradd - h->cbuf.addr;
0499 
0500 #ifdef HARMONY_DEBUG
0501         printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n",
0502                rcuradd, h->cbuf.addr, caught);
0503 #endif
0504 
0505         if (rcuradd > h->cbuf.addr + h->cbuf.size) {
0506         return 0;
0507     }
0508 
0509         return bytes_to_frames(rt, caught);
0510 }
0511 
0512 static int 
0513 snd_harmony_playback_open(struct snd_pcm_substream *ss)
0514 {
0515     struct snd_harmony *h = snd_pcm_substream_chip(ss);
0516     struct snd_pcm_runtime *rt = ss->runtime;
0517     int err;
0518     
0519     h->psubs = ss;
0520     rt->hw = snd_harmony_playback;
0521     snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, 
0522                    &hw_constraint_rates);
0523     
0524     err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
0525     if (err < 0)
0526         return err;
0527     
0528     return 0;
0529 }
0530 
0531 static int
0532 snd_harmony_capture_open(struct snd_pcm_substream *ss)
0533 {
0534         struct snd_harmony *h = snd_pcm_substream_chip(ss);
0535         struct snd_pcm_runtime *rt = ss->runtime;
0536         int err;
0537 
0538         h->csubs = ss;
0539         rt->hw = snd_harmony_capture;
0540         snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
0541                                    &hw_constraint_rates);
0542 
0543         err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
0544         if (err < 0)
0545                 return err;
0546 
0547         return 0;
0548 }
0549 
0550 static int 
0551 snd_harmony_playback_close(struct snd_pcm_substream *ss)
0552 {
0553     struct snd_harmony *h = snd_pcm_substream_chip(ss);
0554     h->psubs = NULL;
0555     return 0;
0556 }
0557 
0558 static int
0559 snd_harmony_capture_close(struct snd_pcm_substream *ss)
0560 {
0561         struct snd_harmony *h = snd_pcm_substream_chip(ss);
0562         h->csubs = NULL;
0563         return 0;
0564 }
0565 
0566 static const struct snd_pcm_ops snd_harmony_playback_ops = {
0567     .open = snd_harmony_playback_open,
0568     .close = snd_harmony_playback_close,
0569     .prepare = snd_harmony_playback_prepare,
0570     .trigger = snd_harmony_playback_trigger,
0571     .pointer = snd_harmony_playback_pointer,
0572 };
0573 
0574 static const struct snd_pcm_ops snd_harmony_capture_ops = {
0575         .open = snd_harmony_capture_open,
0576         .close = snd_harmony_capture_close,
0577         .prepare = snd_harmony_capture_prepare,
0578         .trigger = snd_harmony_capture_trigger,
0579         .pointer = snd_harmony_capture_pointer,
0580 };
0581 
0582 static int 
0583 snd_harmony_pcm_init(struct snd_harmony *h)
0584 {
0585     struct snd_pcm *pcm;
0586     int err;
0587 
0588     if (snd_BUG_ON(!h))
0589         return -EINVAL;
0590 
0591     harmony_disable_interrupts(h);
0592     
0593     err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm);
0594     if (err < 0)
0595         return err;
0596     
0597     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 
0598             &snd_harmony_playback_ops);
0599     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
0600             &snd_harmony_capture_ops);
0601 
0602     pcm->private_data = h;
0603     pcm->info_flags = 0;
0604     strcpy(pcm->name, "harmony");
0605     h->pcm = pcm;
0606 
0607     h->psubs = NULL;
0608     h->csubs = NULL;
0609     
0610     /* initialize graveyard buffer */
0611     h->dma.type = SNDRV_DMA_TYPE_DEV;
0612     h->dma.dev = &h->dev->dev;
0613     err = snd_dma_alloc_pages(h->dma.type,
0614                   h->dma.dev,
0615                   BUF_SIZE*GRAVEYARD_BUFS,
0616                   &h->gdma);
0617     if (err < 0) {
0618         printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n");
0619         return err;
0620     }
0621     
0622     /* initialize silence buffers */
0623     err = snd_dma_alloc_pages(h->dma.type,
0624                   h->dma.dev,
0625                   BUF_SIZE*SILENCE_BUFS,
0626                   &h->sdma);
0627     if (err < 0) {
0628         printk(KERN_ERR PFX "cannot allocate silence buffer!\n");
0629         return err;
0630     }
0631 
0632     /* pre-allocate space for DMA */
0633     snd_pcm_set_managed_buffer_all(pcm, h->dma.type, h->dma.dev,
0634                        MAX_BUF_SIZE, MAX_BUF_SIZE);
0635 
0636     h->st.format = snd_harmony_set_data_format(h,
0637         SNDRV_PCM_FORMAT_S16_BE, 1);
0638 
0639     return 0;
0640 }
0641 
0642 static void 
0643 snd_harmony_set_new_gain(struct snd_harmony *h)
0644 {
0645     harmony_wait_for_control(h);
0646     harmony_write(h, HARMONY_GAINCTL, h->st.gain);
0647 }
0648 
0649 static int 
0650 snd_harmony_mixercontrol_info(struct snd_kcontrol *kc, 
0651                   struct snd_ctl_elem_info *uinfo)
0652 {
0653     int mask = (kc->private_value >> 16) & 0xff;
0654     int left_shift = (kc->private_value) & 0xff;
0655     int right_shift = (kc->private_value >> 8) & 0xff;
0656     
0657     uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : 
0658                SNDRV_CTL_ELEM_TYPE_INTEGER;
0659     uinfo->count = left_shift == right_shift ? 1 : 2;
0660     uinfo->value.integer.min = 0;
0661     uinfo->value.integer.max = mask;
0662 
0663     return 0;
0664 }
0665 
0666 static int 
0667 snd_harmony_volume_get(struct snd_kcontrol *kc, 
0668                struct snd_ctl_elem_value *ucontrol)
0669 {
0670     struct snd_harmony *h = snd_kcontrol_chip(kc);
0671     int shift_left = (kc->private_value) & 0xff;
0672     int shift_right = (kc->private_value >> 8) & 0xff;
0673     int mask = (kc->private_value >> 16) & 0xff;
0674     int invert = (kc->private_value >> 24) & 0xff;
0675     int left, right;
0676     
0677     spin_lock_irq(&h->mixer_lock);
0678 
0679     left = (h->st.gain >> shift_left) & mask;
0680     right = (h->st.gain >> shift_right) & mask;
0681     if (invert) {
0682         left = mask - left;
0683         right = mask - right;
0684     }
0685     
0686     ucontrol->value.integer.value[0] = left;
0687     if (shift_left != shift_right)
0688         ucontrol->value.integer.value[1] = right;
0689 
0690     spin_unlock_irq(&h->mixer_lock);
0691 
0692     return 0;
0693 }  
0694 
0695 static int 
0696 snd_harmony_volume_put(struct snd_kcontrol *kc, 
0697                struct snd_ctl_elem_value *ucontrol)
0698 {
0699     struct snd_harmony *h = snd_kcontrol_chip(kc);
0700     int shift_left = (kc->private_value) & 0xff;
0701     int shift_right = (kc->private_value >> 8) & 0xff;
0702     int mask = (kc->private_value >> 16) & 0xff;
0703     int invert = (kc->private_value >> 24) & 0xff;
0704     int left, right;
0705     int old_gain = h->st.gain;
0706     
0707     spin_lock_irq(&h->mixer_lock);
0708 
0709     left = ucontrol->value.integer.value[0] & mask;
0710     if (invert)
0711         left = mask - left;
0712     h->st.gain &= ~( (mask << shift_left ) );
0713     h->st.gain |= (left << shift_left);
0714 
0715     if (shift_left != shift_right) {
0716         right = ucontrol->value.integer.value[1] & mask;
0717         if (invert)
0718             right = mask - right;
0719         h->st.gain &= ~( (mask << shift_right) );
0720         h->st.gain |= (right << shift_right);
0721     }
0722 
0723     snd_harmony_set_new_gain(h);
0724 
0725     spin_unlock_irq(&h->mixer_lock);
0726     
0727     return h->st.gain != old_gain;
0728 }
0729 
0730 static int 
0731 snd_harmony_captureroute_info(struct snd_kcontrol *kc, 
0732                   struct snd_ctl_elem_info *uinfo)
0733 {
0734     static const char * const texts[2] = { "Line", "Mic" };
0735 
0736     return snd_ctl_enum_info(uinfo, 1, 2, texts);
0737 }
0738 
0739 static int 
0740 snd_harmony_captureroute_get(struct snd_kcontrol *kc, 
0741                  struct snd_ctl_elem_value *ucontrol)
0742 {
0743     struct snd_harmony *h = snd_kcontrol_chip(kc);
0744     int value;
0745     
0746     spin_lock_irq(&h->mixer_lock);
0747 
0748     value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1;
0749     ucontrol->value.enumerated.item[0] = value;
0750 
0751     spin_unlock_irq(&h->mixer_lock);
0752 
0753     return 0;
0754 }  
0755 
0756 static int 
0757 snd_harmony_captureroute_put(struct snd_kcontrol *kc, 
0758                  struct snd_ctl_elem_value *ucontrol)
0759 {
0760     struct snd_harmony *h = snd_kcontrol_chip(kc);
0761     int value;
0762     int old_gain = h->st.gain;
0763     
0764     spin_lock_irq(&h->mixer_lock);
0765 
0766     value = ucontrol->value.enumerated.item[0] & 1;
0767     h->st.gain &= ~HARMONY_GAIN_IS_MASK;
0768     h->st.gain |= value << HARMONY_GAIN_IS_SHIFT;
0769 
0770     snd_harmony_set_new_gain(h);
0771 
0772     spin_unlock_irq(&h->mixer_lock);
0773     
0774     return h->st.gain != old_gain;
0775 }
0776 
0777 #define HARMONY_CONTROLS    ARRAY_SIZE(snd_harmony_controls)
0778 
0779 #define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
0780 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,                \
0781   .info = snd_harmony_mixercontrol_info,                             \
0782   .get = snd_harmony_volume_get, .put = snd_harmony_volume_put,      \
0783   .private_value = ((left_shift) | ((right_shift) << 8) |            \
0784                    ((mask) << 16) | ((invert) << 24)) }
0785 
0786 static const struct snd_kcontrol_new snd_harmony_controls[] = {
0787     HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT, 
0788                HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
0789     HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
0790                HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0),
0791     HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT,
0792                HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1),
0793     {
0794         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0795         .name = "Input Route",
0796         .info = snd_harmony_captureroute_info,
0797         .get = snd_harmony_captureroute_get,
0798         .put = snd_harmony_captureroute_put
0799     },
0800     HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT,
0801                HARMONY_GAIN_SE_SHIFT, 1, 0),
0802     HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT,
0803                HARMONY_GAIN_LE_SHIFT, 1, 0),
0804     HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT,
0805                HARMONY_GAIN_HE_SHIFT, 1, 0),
0806 };
0807 
0808 static void
0809 snd_harmony_mixer_reset(struct snd_harmony *h)
0810 {
0811     harmony_mute(h);
0812     harmony_reset(h);
0813     h->st.gain = HARMONY_GAIN_DEFAULT;
0814     harmony_unmute(h);
0815 }
0816 
0817 static int
0818 snd_harmony_mixer_init(struct snd_harmony *h)
0819 {
0820     struct snd_card *card;
0821     int idx, err;
0822 
0823     if (snd_BUG_ON(!h))
0824         return -EINVAL;
0825     card = h->card;
0826     strcpy(card->mixername, "Harmony Gain control interface");
0827 
0828     for (idx = 0; idx < HARMONY_CONTROLS; idx++) {
0829         err = snd_ctl_add(card, 
0830                   snd_ctl_new1(&snd_harmony_controls[idx], h));
0831         if (err < 0)
0832             return err;
0833     }
0834     
0835     snd_harmony_mixer_reset(h);
0836 
0837     return 0;
0838 }
0839 
0840 static int
0841 snd_harmony_free(struct snd_harmony *h)
0842 {
0843         if (h->gdma.addr)
0844                 snd_dma_free_pages(&h->gdma);
0845         if (h->sdma.addr)
0846                 snd_dma_free_pages(&h->sdma);
0847 
0848     if (h->irq >= 0)
0849         free_irq(h->irq, h);
0850 
0851     iounmap(h->iobase);
0852     kfree(h);
0853     return 0;
0854 }
0855 
0856 static int
0857 snd_harmony_dev_free(struct snd_device *dev)
0858 {
0859     struct snd_harmony *h = dev->device_data;
0860     return snd_harmony_free(h);
0861 }
0862 
0863 static int
0864 snd_harmony_create(struct snd_card *card, 
0865            struct parisc_device *padev, 
0866            struct snd_harmony **rchip)
0867 {
0868     int err;
0869     struct snd_harmony *h;
0870     static const struct snd_device_ops ops = {
0871         .dev_free = snd_harmony_dev_free,
0872     };
0873 
0874     *rchip = NULL;
0875 
0876     h = kzalloc(sizeof(*h), GFP_KERNEL);
0877     if (h == NULL)
0878         return -ENOMEM;
0879 
0880     h->hpa = padev->hpa.start;
0881     h->card = card;
0882     h->dev = padev;
0883     h->irq = -1;
0884     h->iobase = ioremap(padev->hpa.start, HARMONY_SIZE);
0885     if (h->iobase == NULL) {
0886         printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
0887                (unsigned long)padev->hpa.start);
0888         err = -EBUSY;
0889         goto free_and_ret;
0890     }
0891         
0892     err = request_irq(padev->irq, snd_harmony_interrupt, 0,
0893               "harmony", h);
0894     if (err) {
0895         printk(KERN_ERR PFX "could not obtain interrupt %d",
0896                padev->irq);
0897         goto free_and_ret;
0898     }
0899     h->irq = padev->irq;
0900 
0901     spin_lock_init(&h->mixer_lock);
0902     spin_lock_init(&h->lock);
0903 
0904     err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, h, &ops);
0905     if (err < 0)
0906         goto free_and_ret;
0907 
0908     *rchip = h;
0909 
0910     return 0;
0911 
0912 free_and_ret:
0913     snd_harmony_free(h);
0914     return err;
0915 }
0916 
0917 static int __init
0918 snd_harmony_probe(struct parisc_device *padev)
0919 {
0920     int err;
0921     struct snd_card *card;
0922     struct snd_harmony *h;
0923 
0924     err = snd_card_new(&padev->dev, index, id, THIS_MODULE, 0, &card);
0925     if (err < 0)
0926         return err;
0927 
0928     err = snd_harmony_create(card, padev, &h);
0929     if (err < 0)
0930         goto free_and_ret;
0931 
0932     err = snd_harmony_pcm_init(h);
0933     if (err < 0)
0934         goto free_and_ret;
0935 
0936     err = snd_harmony_mixer_init(h);
0937     if (err < 0)
0938         goto free_and_ret;
0939 
0940     strcpy(card->driver, "harmony");
0941     strcpy(card->shortname, "Harmony");
0942     sprintf(card->longname, "%s at 0x%lx, irq %i",
0943         card->shortname, h->hpa, h->irq);
0944 
0945     err = snd_card_register(card);
0946     if (err < 0)
0947         goto free_and_ret;
0948 
0949     parisc_set_drvdata(padev, card);
0950     return 0;
0951 
0952 free_and_ret:
0953     snd_card_free(card);
0954     return err;
0955 }
0956 
0957 static void __exit
0958 snd_harmony_remove(struct parisc_device *padev)
0959 {
0960     snd_card_free(parisc_get_drvdata(padev));
0961 }
0962 
0963 static struct parisc_driver snd_harmony_driver __refdata = {
0964     .name = "harmony",
0965     .id_table = snd_harmony_devtable,
0966     .probe = snd_harmony_probe,
0967     .remove = __exit_p(snd_harmony_remove),
0968 };
0969 
0970 static int __init 
0971 alsa_harmony_init(void)
0972 {
0973     return register_parisc_driver(&snd_harmony_driver);
0974 }
0975 
0976 static void __exit
0977 alsa_harmony_fini(void)
0978 {
0979     unregister_parisc_driver(&snd_harmony_driver);
0980 }
0981 
0982 MODULE_LICENSE("GPL");
0983 MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>");
0984 MODULE_DESCRIPTION("Harmony sound driver");
0985 
0986 module_init(alsa_harmony_init);
0987 module_exit(alsa_harmony_fini);