cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

harmony.c (24159B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Hewlett-Packard Harmony audio driver
      3 *
      4 *   This is a driver for the Harmony audio chipset found
      5 *   on the LASI ASIC of various early HP PA-RISC workstations.
      6 *
      7 *   Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}>
      8 *
      9 *     Based on the previous Harmony incarnations by,
     10 *       Copyright 2000 (c) Linuxcare Canada, Alex deVries
     11 *       Copyright 2000-2003 (c) Helge Deller
     12 *       Copyright 2001 (c) Matthieu Delahaye
     13 *       Copyright 2001 (c) Jean-Christophe Vaugeois
     14 *       Copyright 2003 (c) Laurent Canet
     15 *       Copyright 2004 (c) Stuart Brady
     16 *
     17 * Notes:
     18 *   - graveyard and silence buffers last for lifetime of
     19 *     the driver. playback and capture buffers are allocated
     20 *     per _open()/_close().
     21 * 
     22 * TODO:
     23 */
     24
     25#include <linux/init.h>
     26#include <linux/slab.h>
     27#include <linux/time.h>
     28#include <linux/wait.h>
     29#include <linux/delay.h>
     30#include <linux/module.h>
     31#include <linux/interrupt.h>
     32#include <linux/spinlock.h>
     33#include <linux/dma-mapping.h>
     34#include <linux/io.h>
     35
     36#include <sound/core.h>
     37#include <sound/pcm.h>
     38#include <sound/control.h>
     39#include <sound/rawmidi.h>
     40#include <sound/initval.h>
     41#include <sound/info.h>
     42
     43#include <asm/hardware.h>
     44#include <asm/parisc-device.h>
     45
     46#include "harmony.h"
     47
     48static int index = SNDRV_DEFAULT_IDX1;	/* Index 0-MAX */
     49static char *id = SNDRV_DEFAULT_STR1;	/* ID for this card */
     50module_param(index, int, 0444);
     51MODULE_PARM_DESC(index, "Index value for Harmony driver.");
     52module_param(id, charp, 0444);
     53MODULE_PARM_DESC(id, "ID string for Harmony driver.");
     54
     55
     56static const struct parisc_device_id snd_harmony_devtable[] __initconst = {
     57	/* bushmaster / flounder */
     58	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, 
     59	/* 712 / 715 */
     60	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, 
     61	/* pace */
     62	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, 
     63	/* outfield / coral II */
     64	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F },
     65	{ 0, }
     66};
     67
     68MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable);
     69
     70#define NAME "harmony"
     71#define PFX  NAME ": "
     72
     73static const unsigned int snd_harmony_rates[] = {
     74	5512, 6615, 8000, 9600,
     75	11025, 16000, 18900, 22050,
     76	27428, 32000, 33075, 37800,
     77	44100, 48000
     78};
     79
     80static const unsigned int rate_bits[14] = {
     81	HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ,
     82	HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ,
     83	HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ,
     84	HARMONY_SR_32KHZ, HARMONY_SR_33KHZ, HARMONY_SR_37KHZ,
     85	HARMONY_SR_44KHZ, HARMONY_SR_48KHZ
     86};
     87
     88static const struct snd_pcm_hw_constraint_list hw_constraint_rates = {
     89	.count = ARRAY_SIZE(snd_harmony_rates),
     90	.list = snd_harmony_rates,
     91	.mask = 0,
     92};
     93
     94static inline unsigned long
     95harmony_read(struct snd_harmony *h, unsigned r)
     96{
     97	return __raw_readl(h->iobase + r);
     98}
     99
    100static inline void
    101harmony_write(struct snd_harmony *h, unsigned r, unsigned long v)
    102{
    103	__raw_writel(v, h->iobase + r);
    104}
    105
    106static inline void
    107harmony_wait_for_control(struct snd_harmony *h)
    108{
    109	while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ;
    110}
    111
    112static inline void
    113harmony_reset(struct snd_harmony *h)
    114{
    115	harmony_write(h, HARMONY_RESET, 1);
    116	mdelay(50);
    117	harmony_write(h, HARMONY_RESET, 0);
    118}
    119
    120static void
    121harmony_disable_interrupts(struct snd_harmony *h)
    122{
    123	u32 dstatus;
    124	harmony_wait_for_control(h);
    125	dstatus = harmony_read(h, HARMONY_DSTATUS);
    126	dstatus &= ~HARMONY_DSTATUS_IE;
    127	harmony_write(h, HARMONY_DSTATUS, dstatus);
    128}
    129
    130static void
    131harmony_enable_interrupts(struct snd_harmony *h)
    132{
    133	u32 dstatus;
    134	harmony_wait_for_control(h);
    135	dstatus = harmony_read(h, HARMONY_DSTATUS);
    136	dstatus |= HARMONY_DSTATUS_IE;
    137	harmony_write(h, HARMONY_DSTATUS, dstatus);
    138}
    139
    140static void
    141harmony_mute(struct snd_harmony *h)
    142{
    143	unsigned long flags;
    144
    145	spin_lock_irqsave(&h->mixer_lock, flags);
    146	harmony_wait_for_control(h);
    147	harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE);
    148	spin_unlock_irqrestore(&h->mixer_lock, flags);
    149}
    150
    151static void
    152harmony_unmute(struct snd_harmony *h)
    153{
    154	unsigned long flags;
    155
    156	spin_lock_irqsave(&h->mixer_lock, flags);
    157	harmony_wait_for_control(h);
    158	harmony_write(h, HARMONY_GAINCTL, h->st.gain);
    159	spin_unlock_irqrestore(&h->mixer_lock, flags);
    160}
    161
    162static void
    163harmony_set_control(struct snd_harmony *h)
    164{
    165	u32 ctrl;
    166	unsigned long flags;
    167
    168	spin_lock_irqsave(&h->lock, flags);
    169
    170	ctrl = (HARMONY_CNTL_C      |
    171		(h->st.format << 6) |
    172		(h->st.stereo << 5) |
    173		(h->st.rate));
    174
    175	harmony_wait_for_control(h);
    176	harmony_write(h, HARMONY_CNTL, ctrl);
    177
    178	spin_unlock_irqrestore(&h->lock, flags);
    179}
    180
    181static irqreturn_t
    182snd_harmony_interrupt(int irq, void *dev)
    183{
    184	u32 dstatus;
    185	struct snd_harmony *h = dev;
    186
    187	spin_lock(&h->lock);
    188	harmony_disable_interrupts(h);
    189	harmony_wait_for_control(h);
    190	dstatus = harmony_read(h, HARMONY_DSTATUS);
    191	spin_unlock(&h->lock);
    192
    193	if (dstatus & HARMONY_DSTATUS_PN) {
    194		if (h->psubs && h->st.playing) {
    195			spin_lock(&h->lock);
    196			h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */
    197			h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */
    198
    199			harmony_write(h, HARMONY_PNXTADD, 
    200				      h->pbuf.addr + h->pbuf.buf);
    201			h->stats.play_intr++;
    202			spin_unlock(&h->lock);
    203                        snd_pcm_period_elapsed(h->psubs);
    204		} else {
    205			spin_lock(&h->lock);
    206			harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
    207			h->stats.silence_intr++;
    208			spin_unlock(&h->lock);
    209		}
    210	}
    211
    212	if (dstatus & HARMONY_DSTATUS_RN) {
    213		if (h->csubs && h->st.capturing) {
    214			spin_lock(&h->lock);
    215			h->cbuf.buf += h->cbuf.count;
    216			h->cbuf.buf %= h->cbuf.size;
    217
    218			harmony_write(h, HARMONY_RNXTADD,
    219				      h->cbuf.addr + h->cbuf.buf);
    220			h->stats.rec_intr++;
    221			spin_unlock(&h->lock);
    222                        snd_pcm_period_elapsed(h->csubs);
    223		} else {
    224			spin_lock(&h->lock);
    225			harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
    226			h->stats.graveyard_intr++;
    227			spin_unlock(&h->lock);
    228		}
    229	}
    230
    231	spin_lock(&h->lock);
    232	harmony_enable_interrupts(h);
    233	spin_unlock(&h->lock);
    234
    235	return IRQ_HANDLED;
    236}
    237
    238static unsigned int 
    239snd_harmony_rate_bits(int rate)
    240{
    241	unsigned int i;
    242	
    243	for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++)
    244		if (snd_harmony_rates[i] == rate)
    245			return rate_bits[i];
    246
    247	return HARMONY_SR_44KHZ;
    248}
    249
    250static const struct snd_pcm_hardware snd_harmony_playback =
    251{
    252	.info =	(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 
    253		 SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
    254		 SNDRV_PCM_INFO_BLOCK_TRANSFER),
    255	.formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
    256		    SNDRV_PCM_FMTBIT_A_LAW),
    257	.rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
    258		  SNDRV_PCM_RATE_KNOT),
    259	.rate_min = 5512,
    260	.rate_max = 48000,
    261	.channels_min =	1,
    262	.channels_max =	2,
    263	.buffer_bytes_max = MAX_BUF_SIZE,
    264	.period_bytes_min = BUF_SIZE,
    265	.period_bytes_max = BUF_SIZE,
    266	.periods_min = 1,
    267	.periods_max = MAX_BUFS,
    268	.fifo_size = 0,
    269};
    270
    271static const struct snd_pcm_hardware snd_harmony_capture =
    272{
    273        .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
    274                 SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
    275                 SNDRV_PCM_INFO_BLOCK_TRANSFER),
    276        .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
    277                    SNDRV_PCM_FMTBIT_A_LAW),
    278        .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
    279		  SNDRV_PCM_RATE_KNOT),
    280        .rate_min = 5512,
    281        .rate_max = 48000,
    282        .channels_min = 1,
    283        .channels_max = 2,
    284        .buffer_bytes_max = MAX_BUF_SIZE,
    285        .period_bytes_min = BUF_SIZE,
    286        .period_bytes_max = BUF_SIZE,
    287        .periods_min = 1,
    288        .periods_max = MAX_BUFS,
    289        .fifo_size = 0,
    290};
    291
    292static int
    293snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd)
    294{
    295	struct snd_harmony *h = snd_pcm_substream_chip(ss);
    296
    297	if (h->st.capturing)
    298		return -EBUSY;
    299
    300	spin_lock(&h->lock);
    301	switch (cmd) {
    302	case SNDRV_PCM_TRIGGER_START:
    303		h->st.playing = 1;
    304		harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr);
    305		harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
    306		harmony_unmute(h);
    307		harmony_enable_interrupts(h);
    308		break;
    309	case SNDRV_PCM_TRIGGER_STOP:
    310		h->st.playing = 0;
    311		harmony_mute(h);
    312		harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
    313		harmony_disable_interrupts(h);
    314		break;
    315	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    316	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    317	case SNDRV_PCM_TRIGGER_SUSPEND:
    318	default:
    319		spin_unlock(&h->lock);
    320		snd_BUG();
    321		return -EINVAL;
    322	}
    323	spin_unlock(&h->lock);
    324	
    325	return 0;
    326}
    327
    328static int
    329snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd)
    330{
    331        struct snd_harmony *h = snd_pcm_substream_chip(ss);
    332
    333	if (h->st.playing)
    334		return -EBUSY;
    335
    336	spin_lock(&h->lock);
    337        switch (cmd) {
    338        case SNDRV_PCM_TRIGGER_START:
    339		h->st.capturing = 1;
    340                harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
    341                harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr);
    342		harmony_unmute(h);
    343                harmony_enable_interrupts(h);
    344		break;
    345        case SNDRV_PCM_TRIGGER_STOP:
    346		h->st.capturing = 0;
    347		harmony_mute(h);
    348		harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
    349		harmony_disable_interrupts(h);
    350		break;
    351        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    352        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    353        case SNDRV_PCM_TRIGGER_SUSPEND:
    354	default:
    355		spin_unlock(&h->lock);
    356		snd_BUG();
    357                return -EINVAL;
    358        }
    359	spin_unlock(&h->lock);
    360		
    361        return 0;
    362}
    363
    364static int
    365snd_harmony_set_data_format(struct snd_harmony *h, int fmt, int force)
    366{
    367	int o = h->st.format;
    368	int n;
    369
    370	switch(fmt) {
    371	case SNDRV_PCM_FORMAT_S16_BE:
    372		n = HARMONY_DF_16BIT_LINEAR;
    373		break;
    374	case SNDRV_PCM_FORMAT_A_LAW:
    375		n = HARMONY_DF_8BIT_ALAW;
    376		break;
    377	case SNDRV_PCM_FORMAT_MU_LAW:
    378		n = HARMONY_DF_8BIT_ULAW;
    379		break;
    380	default:
    381		n = HARMONY_DF_16BIT_LINEAR;
    382		break;
    383	}
    384
    385	if (force || o != n) {
    386		snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ / 
    387					   (snd_pcm_format_physical_width(fmt)
    388					    / 8));
    389	}
    390
    391	return n;
    392}
    393
    394static int
    395snd_harmony_playback_prepare(struct snd_pcm_substream *ss)
    396{
    397	struct snd_harmony *h = snd_pcm_substream_chip(ss);
    398	struct snd_pcm_runtime *rt = ss->runtime;
    399	
    400	if (h->st.capturing)
    401		return -EBUSY;
    402	
    403	h->pbuf.size = snd_pcm_lib_buffer_bytes(ss);
    404	h->pbuf.count = snd_pcm_lib_period_bytes(ss);
    405	if (h->pbuf.buf >= h->pbuf.size)
    406		h->pbuf.buf = 0;
    407	h->st.playing = 0;
    408
    409	h->st.rate = snd_harmony_rate_bits(rt->rate);
    410	h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
    411	
    412	if (rt->channels == 2)
    413		h->st.stereo = HARMONY_SS_STEREO;
    414	else
    415		h->st.stereo = HARMONY_SS_MONO;
    416
    417	harmony_set_control(h);
    418
    419	h->pbuf.addr = rt->dma_addr;
    420
    421	return 0;
    422}
    423
    424static int
    425snd_harmony_capture_prepare(struct snd_pcm_substream *ss)
    426{
    427        struct snd_harmony *h = snd_pcm_substream_chip(ss);
    428        struct snd_pcm_runtime *rt = ss->runtime;
    429
    430	if (h->st.playing)
    431		return -EBUSY;
    432
    433        h->cbuf.size = snd_pcm_lib_buffer_bytes(ss);
    434        h->cbuf.count = snd_pcm_lib_period_bytes(ss);
    435	if (h->cbuf.buf >= h->cbuf.size)
    436	        h->cbuf.buf = 0;
    437	h->st.capturing = 0;
    438
    439        h->st.rate = snd_harmony_rate_bits(rt->rate);
    440        h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
    441
    442        if (rt->channels == 2)
    443                h->st.stereo = HARMONY_SS_STEREO;
    444        else
    445                h->st.stereo = HARMONY_SS_MONO;
    446
    447        harmony_set_control(h);
    448
    449        h->cbuf.addr = rt->dma_addr;
    450
    451        return 0;
    452}
    453
    454static snd_pcm_uframes_t 
    455snd_harmony_playback_pointer(struct snd_pcm_substream *ss)
    456{
    457	struct snd_pcm_runtime *rt = ss->runtime;
    458	struct snd_harmony *h = snd_pcm_substream_chip(ss);
    459	unsigned long pcuradd;
    460	unsigned long played;
    461
    462	if (!(h->st.playing) || (h->psubs == NULL)) 
    463		return 0;
    464
    465	if ((h->pbuf.addr == 0) || (h->pbuf.size == 0))
    466		return 0;
    467	
    468	pcuradd = harmony_read(h, HARMONY_PCURADD);
    469	played = pcuradd - h->pbuf.addr;
    470
    471#ifdef HARMONY_DEBUG
    472	printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n", 
    473	       pcuradd, h->pbuf.addr, played);	
    474#endif
    475
    476	if (pcuradd > h->pbuf.addr + h->pbuf.size) {
    477		return 0;
    478	}
    479
    480	return bytes_to_frames(rt, played);
    481}
    482
    483static snd_pcm_uframes_t
    484snd_harmony_capture_pointer(struct snd_pcm_substream *ss)
    485{
    486        struct snd_pcm_runtime *rt = ss->runtime;
    487        struct snd_harmony *h = snd_pcm_substream_chip(ss);
    488        unsigned long rcuradd;
    489        unsigned long caught;
    490
    491        if (!(h->st.capturing) || (h->csubs == NULL))
    492                return 0;
    493
    494        if ((h->cbuf.addr == 0) || (h->cbuf.size == 0))
    495                return 0;
    496
    497        rcuradd = harmony_read(h, HARMONY_RCURADD);
    498        caught = rcuradd - h->cbuf.addr;
    499
    500#ifdef HARMONY_DEBUG
    501        printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n",
    502               rcuradd, h->cbuf.addr, caught);
    503#endif
    504
    505        if (rcuradd > h->cbuf.addr + h->cbuf.size) {
    506		return 0;
    507	}
    508
    509        return bytes_to_frames(rt, caught);
    510}
    511
    512static int 
    513snd_harmony_playback_open(struct snd_pcm_substream *ss)
    514{
    515	struct snd_harmony *h = snd_pcm_substream_chip(ss);
    516	struct snd_pcm_runtime *rt = ss->runtime;
    517	int err;
    518	
    519	h->psubs = ss;
    520	rt->hw = snd_harmony_playback;
    521	snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, 
    522				   &hw_constraint_rates);
    523	
    524	err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
    525	if (err < 0)
    526		return err;
    527	
    528	return 0;
    529}
    530
    531static int
    532snd_harmony_capture_open(struct snd_pcm_substream *ss)
    533{
    534        struct snd_harmony *h = snd_pcm_substream_chip(ss);
    535        struct snd_pcm_runtime *rt = ss->runtime;
    536        int err;
    537
    538        h->csubs = ss;
    539        rt->hw = snd_harmony_capture;
    540        snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
    541                                   &hw_constraint_rates);
    542
    543        err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
    544        if (err < 0)
    545                return err;
    546
    547        return 0;
    548}
    549
    550static int 
    551snd_harmony_playback_close(struct snd_pcm_substream *ss)
    552{
    553	struct snd_harmony *h = snd_pcm_substream_chip(ss);
    554	h->psubs = NULL;
    555	return 0;
    556}
    557
    558static int
    559snd_harmony_capture_close(struct snd_pcm_substream *ss)
    560{
    561        struct snd_harmony *h = snd_pcm_substream_chip(ss);
    562        h->csubs = NULL;
    563        return 0;
    564}
    565
    566static const struct snd_pcm_ops snd_harmony_playback_ops = {
    567	.open =	snd_harmony_playback_open,
    568	.close = snd_harmony_playback_close,
    569	.prepare = snd_harmony_playback_prepare,
    570	.trigger = snd_harmony_playback_trigger,
    571 	.pointer = snd_harmony_playback_pointer,
    572};
    573
    574static const struct snd_pcm_ops snd_harmony_capture_ops = {
    575        .open = snd_harmony_capture_open,
    576        .close = snd_harmony_capture_close,
    577        .prepare = snd_harmony_capture_prepare,
    578        .trigger = snd_harmony_capture_trigger,
    579        .pointer = snd_harmony_capture_pointer,
    580};
    581
    582static int 
    583snd_harmony_pcm_init(struct snd_harmony *h)
    584{
    585	struct snd_pcm *pcm;
    586	int err;
    587
    588	if (snd_BUG_ON(!h))
    589		return -EINVAL;
    590
    591	harmony_disable_interrupts(h);
    592	
    593   	err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm);
    594	if (err < 0)
    595		return err;
    596	
    597	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 
    598			&snd_harmony_playback_ops);
    599	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
    600			&snd_harmony_capture_ops);
    601
    602	pcm->private_data = h;
    603	pcm->info_flags = 0;
    604	strcpy(pcm->name, "harmony");
    605	h->pcm = pcm;
    606
    607	h->psubs = NULL;
    608	h->csubs = NULL;
    609	
    610	/* initialize graveyard buffer */
    611	h->dma.type = SNDRV_DMA_TYPE_DEV;
    612	h->dma.dev = &h->dev->dev;
    613	err = snd_dma_alloc_pages(h->dma.type,
    614				  h->dma.dev,
    615				  BUF_SIZE*GRAVEYARD_BUFS,
    616				  &h->gdma);
    617	if (err < 0) {
    618		printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n");
    619		return err;
    620	}
    621	
    622	/* initialize silence buffers */
    623	err = snd_dma_alloc_pages(h->dma.type,
    624				  h->dma.dev,
    625				  BUF_SIZE*SILENCE_BUFS,
    626				  &h->sdma);
    627	if (err < 0) {
    628		printk(KERN_ERR PFX "cannot allocate silence buffer!\n");
    629		return err;
    630	}
    631
    632	/* pre-allocate space for DMA */
    633	snd_pcm_set_managed_buffer_all(pcm, h->dma.type, h->dma.dev,
    634				       MAX_BUF_SIZE, MAX_BUF_SIZE);
    635
    636	h->st.format = snd_harmony_set_data_format(h,
    637		SNDRV_PCM_FORMAT_S16_BE, 1);
    638
    639	return 0;
    640}
    641
    642static void 
    643snd_harmony_set_new_gain(struct snd_harmony *h)
    644{
    645 	harmony_wait_for_control(h);
    646	harmony_write(h, HARMONY_GAINCTL, h->st.gain);
    647}
    648
    649static int 
    650snd_harmony_mixercontrol_info(struct snd_kcontrol *kc, 
    651			      struct snd_ctl_elem_info *uinfo)
    652{
    653	int mask = (kc->private_value >> 16) & 0xff;
    654	int left_shift = (kc->private_value) & 0xff;
    655	int right_shift = (kc->private_value >> 8) & 0xff;
    656	
    657	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : 
    658		       SNDRV_CTL_ELEM_TYPE_INTEGER;
    659	uinfo->count = left_shift == right_shift ? 1 : 2;
    660	uinfo->value.integer.min = 0;
    661	uinfo->value.integer.max = mask;
    662
    663	return 0;
    664}
    665
    666static int 
    667snd_harmony_volume_get(struct snd_kcontrol *kc, 
    668		       struct snd_ctl_elem_value *ucontrol)
    669{
    670	struct snd_harmony *h = snd_kcontrol_chip(kc);
    671	int shift_left = (kc->private_value) & 0xff;
    672	int shift_right = (kc->private_value >> 8) & 0xff;
    673	int mask = (kc->private_value >> 16) & 0xff;
    674	int invert = (kc->private_value >> 24) & 0xff;
    675	int left, right;
    676	
    677	spin_lock_irq(&h->mixer_lock);
    678
    679	left = (h->st.gain >> shift_left) & mask;
    680	right = (h->st.gain >> shift_right) & mask;
    681	if (invert) {
    682		left = mask - left;
    683		right = mask - right;
    684	}
    685	
    686	ucontrol->value.integer.value[0] = left;
    687	if (shift_left != shift_right)
    688		ucontrol->value.integer.value[1] = right;
    689
    690	spin_unlock_irq(&h->mixer_lock);
    691
    692	return 0;
    693}  
    694
    695static int 
    696snd_harmony_volume_put(struct snd_kcontrol *kc, 
    697		       struct snd_ctl_elem_value *ucontrol)
    698{
    699	struct snd_harmony *h = snd_kcontrol_chip(kc);
    700	int shift_left = (kc->private_value) & 0xff;
    701	int shift_right = (kc->private_value >> 8) & 0xff;
    702	int mask = (kc->private_value >> 16) & 0xff;
    703	int invert = (kc->private_value >> 24) & 0xff;
    704	int left, right;
    705	int old_gain = h->st.gain;
    706	
    707	spin_lock_irq(&h->mixer_lock);
    708
    709	left = ucontrol->value.integer.value[0] & mask;
    710	if (invert)
    711		left = mask - left;
    712	h->st.gain &= ~( (mask << shift_left ) );
    713 	h->st.gain |= (left << shift_left);
    714
    715	if (shift_left != shift_right) {
    716		right = ucontrol->value.integer.value[1] & mask;
    717		if (invert)
    718			right = mask - right;
    719		h->st.gain &= ~( (mask << shift_right) );
    720		h->st.gain |= (right << shift_right);
    721	}
    722
    723	snd_harmony_set_new_gain(h);
    724
    725	spin_unlock_irq(&h->mixer_lock);
    726	
    727	return h->st.gain != old_gain;
    728}
    729
    730static int 
    731snd_harmony_captureroute_info(struct snd_kcontrol *kc, 
    732			      struct snd_ctl_elem_info *uinfo)
    733{
    734	static const char * const texts[2] = { "Line", "Mic" };
    735
    736	return snd_ctl_enum_info(uinfo, 1, 2, texts);
    737}
    738
    739static int 
    740snd_harmony_captureroute_get(struct snd_kcontrol *kc, 
    741			     struct snd_ctl_elem_value *ucontrol)
    742{
    743	struct snd_harmony *h = snd_kcontrol_chip(kc);
    744	int value;
    745	
    746	spin_lock_irq(&h->mixer_lock);
    747
    748	value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1;
    749	ucontrol->value.enumerated.item[0] = value;
    750
    751	spin_unlock_irq(&h->mixer_lock);
    752
    753	return 0;
    754}  
    755
    756static int 
    757snd_harmony_captureroute_put(struct snd_kcontrol *kc, 
    758			     struct snd_ctl_elem_value *ucontrol)
    759{
    760	struct snd_harmony *h = snd_kcontrol_chip(kc);
    761	int value;
    762	int old_gain = h->st.gain;
    763	
    764	spin_lock_irq(&h->mixer_lock);
    765
    766	value = ucontrol->value.enumerated.item[0] & 1;
    767	h->st.gain &= ~HARMONY_GAIN_IS_MASK;
    768 	h->st.gain |= value << HARMONY_GAIN_IS_SHIFT;
    769
    770	snd_harmony_set_new_gain(h);
    771
    772	spin_unlock_irq(&h->mixer_lock);
    773	
    774	return h->st.gain != old_gain;
    775}
    776
    777#define HARMONY_CONTROLS	ARRAY_SIZE(snd_harmony_controls)
    778
    779#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
    780{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,                \
    781  .info = snd_harmony_mixercontrol_info,                             \
    782  .get = snd_harmony_volume_get, .put = snd_harmony_volume_put,      \
    783  .private_value = ((left_shift) | ((right_shift) << 8) |            \
    784                   ((mask) << 16) | ((invert) << 24)) }
    785
    786static const struct snd_kcontrol_new snd_harmony_controls[] = {
    787	HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT, 
    788		       HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
    789	HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
    790		       HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0),
    791	HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT,
    792		       HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1),
    793	{
    794		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    795		.name = "Input Route",
    796		.info = snd_harmony_captureroute_info,
    797		.get = snd_harmony_captureroute_get,
    798		.put = snd_harmony_captureroute_put
    799	},
    800	HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT,
    801		       HARMONY_GAIN_SE_SHIFT, 1, 0),
    802	HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT,
    803		       HARMONY_GAIN_LE_SHIFT, 1, 0),
    804	HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT,
    805		       HARMONY_GAIN_HE_SHIFT, 1, 0),
    806};
    807
    808static void
    809snd_harmony_mixer_reset(struct snd_harmony *h)
    810{
    811	harmony_mute(h);
    812	harmony_reset(h);
    813	h->st.gain = HARMONY_GAIN_DEFAULT;
    814	harmony_unmute(h);
    815}
    816
    817static int
    818snd_harmony_mixer_init(struct snd_harmony *h)
    819{
    820	struct snd_card *card;
    821	int idx, err;
    822
    823	if (snd_BUG_ON(!h))
    824		return -EINVAL;
    825	card = h->card;
    826	strcpy(card->mixername, "Harmony Gain control interface");
    827
    828	for (idx = 0; idx < HARMONY_CONTROLS; idx++) {
    829		err = snd_ctl_add(card, 
    830				  snd_ctl_new1(&snd_harmony_controls[idx], h));
    831		if (err < 0)
    832			return err;
    833	}
    834	
    835	snd_harmony_mixer_reset(h);
    836
    837	return 0;
    838}
    839
    840static int
    841snd_harmony_free(struct snd_harmony *h)
    842{
    843        if (h->gdma.addr)
    844                snd_dma_free_pages(&h->gdma);
    845        if (h->sdma.addr)
    846                snd_dma_free_pages(&h->sdma);
    847
    848	if (h->irq >= 0)
    849		free_irq(h->irq, h);
    850
    851	iounmap(h->iobase);
    852	kfree(h);
    853	return 0;
    854}
    855
    856static int
    857snd_harmony_dev_free(struct snd_device *dev)
    858{
    859	struct snd_harmony *h = dev->device_data;
    860	return snd_harmony_free(h);
    861}
    862
    863static int
    864snd_harmony_create(struct snd_card *card, 
    865		   struct parisc_device *padev, 
    866		   struct snd_harmony **rchip)
    867{
    868	int err;
    869	struct snd_harmony *h;
    870	static const struct snd_device_ops ops = {
    871		.dev_free = snd_harmony_dev_free,
    872	};
    873
    874	*rchip = NULL;
    875
    876	h = kzalloc(sizeof(*h), GFP_KERNEL);
    877	if (h == NULL)
    878		return -ENOMEM;
    879
    880	h->hpa = padev->hpa.start;
    881	h->card = card;
    882	h->dev = padev;
    883	h->irq = -1;
    884	h->iobase = ioremap(padev->hpa.start, HARMONY_SIZE);
    885	if (h->iobase == NULL) {
    886		printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
    887		       (unsigned long)padev->hpa.start);
    888		err = -EBUSY;
    889		goto free_and_ret;
    890	}
    891		
    892	err = request_irq(padev->irq, snd_harmony_interrupt, 0,
    893			  "harmony", h);
    894	if (err) {
    895		printk(KERN_ERR PFX "could not obtain interrupt %d",
    896		       padev->irq);
    897		goto free_and_ret;
    898	}
    899	h->irq = padev->irq;
    900
    901	spin_lock_init(&h->mixer_lock);
    902	spin_lock_init(&h->lock);
    903
    904	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, h, &ops);
    905	if (err < 0)
    906		goto free_and_ret;
    907
    908	*rchip = h;
    909
    910	return 0;
    911
    912free_and_ret:
    913	snd_harmony_free(h);
    914	return err;
    915}
    916
    917static int __init
    918snd_harmony_probe(struct parisc_device *padev)
    919{
    920	int err;
    921	struct snd_card *card;
    922	struct snd_harmony *h;
    923
    924	err = snd_card_new(&padev->dev, index, id, THIS_MODULE, 0, &card);
    925	if (err < 0)
    926		return err;
    927
    928	err = snd_harmony_create(card, padev, &h);
    929	if (err < 0)
    930		goto free_and_ret;
    931
    932	err = snd_harmony_pcm_init(h);
    933	if (err < 0)
    934		goto free_and_ret;
    935
    936	err = snd_harmony_mixer_init(h);
    937	if (err < 0)
    938		goto free_and_ret;
    939
    940	strcpy(card->driver, "harmony");
    941	strcpy(card->shortname, "Harmony");
    942	sprintf(card->longname, "%s at 0x%lx, irq %i",
    943		card->shortname, h->hpa, h->irq);
    944
    945	err = snd_card_register(card);
    946	if (err < 0)
    947		goto free_and_ret;
    948
    949	parisc_set_drvdata(padev, card);
    950	return 0;
    951
    952free_and_ret:
    953	snd_card_free(card);
    954	return err;
    955}
    956
    957static void __exit
    958snd_harmony_remove(struct parisc_device *padev)
    959{
    960	snd_card_free(parisc_get_drvdata(padev));
    961}
    962
    963static struct parisc_driver snd_harmony_driver __refdata = {
    964	.name = "harmony",
    965	.id_table = snd_harmony_devtable,
    966	.probe = snd_harmony_probe,
    967	.remove = __exit_p(snd_harmony_remove),
    968};
    969
    970static int __init 
    971alsa_harmony_init(void)
    972{
    973	return register_parisc_driver(&snd_harmony_driver);
    974}
    975
    976static void __exit
    977alsa_harmony_fini(void)
    978{
    979	unregister_parisc_driver(&snd_harmony_driver);
    980}
    981
    982MODULE_LICENSE("GPL");
    983MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>");
    984MODULE_DESCRIPTION("Harmony sound driver");
    985
    986module_init(alsa_harmony_init);
    987module_exit(alsa_harmony_fini);