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

gus_pcm.c (28855B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
      4 *  Routines for control of GF1 chip (PCM things)
      5 *
      6 *  InterWave chips supports interleaved DMA, but this feature isn't used in
      7 *  this code.
      8 *  
      9 *  This code emulates autoinit DMA transfer for playback, recording by GF1
     10 *  chip doesn't support autoinit DMA.
     11 */
     12
     13#include <asm/dma.h>
     14#include <linux/slab.h>
     15#include <linux/sched/signal.h>
     16
     17#include <sound/core.h>
     18#include <sound/control.h>
     19#include <sound/gus.h>
     20#include <sound/pcm_params.h>
     21#include "gus_tables.h"
     22
     23/* maximum rate */
     24
     25#define SNDRV_GF1_PCM_RATE		48000
     26
     27#define SNDRV_GF1_PCM_PFLG_NONE		0
     28#define SNDRV_GF1_PCM_PFLG_ACTIVE	(1<<0)
     29#define SNDRV_GF1_PCM_PFLG_NEUTRAL	(2<<0)
     30
     31struct gus_pcm_private {
     32	struct snd_gus_card * gus;
     33	struct snd_pcm_substream *substream;
     34	spinlock_t lock;
     35	unsigned int voices;
     36	struct snd_gus_voice *pvoices[2];
     37	unsigned int memory;
     38	unsigned short flags;
     39	unsigned char voice_ctrl, ramp_ctrl;
     40	unsigned int bpos;
     41	unsigned int blocks;
     42	unsigned int block_size;
     43	unsigned int dma_size;
     44	wait_queue_head_t sleep;
     45	atomic_t dma_count;
     46	int final_volume;
     47};
     48
     49static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data)
     50{
     51	struct gus_pcm_private *pcmp = private_data;
     52
     53	if (pcmp) {
     54		atomic_dec(&pcmp->dma_count);
     55		wake_up(&pcmp->sleep);
     56	}
     57}
     58
     59static int snd_gf1_pcm_block_change(struct snd_pcm_substream *substream,
     60				    unsigned int offset,
     61				    unsigned int addr,
     62				    unsigned int count)
     63{
     64	struct snd_gf1_dma_block block;
     65	struct snd_pcm_runtime *runtime = substream->runtime;
     66	struct gus_pcm_private *pcmp = runtime->private_data;
     67
     68	count += offset & 31;
     69	offset &= ~31;
     70	/*
     71	snd_printk(KERN_DEBUG "block change - offset = 0x%x, count = 0x%x\n",
     72		   offset, count);
     73	*/
     74	memset(&block, 0, sizeof(block));
     75	block.cmd = SNDRV_GF1_DMA_IRQ;
     76	if (snd_pcm_format_unsigned(runtime->format))
     77		block.cmd |= SNDRV_GF1_DMA_UNSIGNED;
     78	if (snd_pcm_format_width(runtime->format) == 16)
     79		block.cmd |= SNDRV_GF1_DMA_16BIT;
     80	block.addr = addr & ~31;
     81	block.buffer = runtime->dma_area + offset;
     82	block.buf_addr = runtime->dma_addr + offset;
     83	block.count = count;
     84	block.private_data = pcmp;
     85	block.ack = snd_gf1_pcm_block_change_ack;
     86	if (!snd_gf1_dma_transfer_block(pcmp->gus, &block, 0, 0))
     87		atomic_inc(&pcmp->dma_count);
     88	return 0;
     89}
     90
     91static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream)
     92{
     93	struct snd_pcm_runtime *runtime = substream->runtime;
     94	struct gus_pcm_private *pcmp = runtime->private_data;
     95	struct snd_gus_card * gus = pcmp->gus;
     96	unsigned long flags;
     97	unsigned char voice_ctrl, ramp_ctrl;
     98	unsigned short rate;
     99	unsigned int curr, begin, end;
    100	unsigned short vol;
    101	unsigned char pan;
    102	unsigned int voice;
    103
    104	spin_lock_irqsave(&pcmp->lock, flags);
    105	if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) {
    106		spin_unlock_irqrestore(&pcmp->lock, flags);
    107		return;
    108	}
    109	pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE;
    110	pcmp->final_volume = 0;
    111	spin_unlock_irqrestore(&pcmp->lock, flags);
    112	rate = snd_gf1_translate_freq(gus, runtime->rate << 4);
    113	/* enable WAVE IRQ */
    114	voice_ctrl = snd_pcm_format_width(runtime->format) == 16 ? 0x24 : 0x20;
    115	/* enable RAMP IRQ + rollover */
    116	ramp_ctrl = 0x24;
    117	if (pcmp->blocks == 1) {
    118		voice_ctrl |= 0x08;	/* loop enable */
    119		ramp_ctrl &= ~0x04;	/* disable rollover */
    120	}
    121	for (voice = 0; voice < pcmp->voices; voice++) {
    122		begin = pcmp->memory + voice * (pcmp->dma_size / runtime->channels);
    123		curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels;
    124		end = curr + (pcmp->block_size / runtime->channels);
    125		end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1;
    126		/*
    127		snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, "
    128			   "ctrl=0x%x, ramp=0x%x, rate=0x%x\n",
    129			   curr, begin, end, voice_ctrl, ramp_ctrl, rate);
    130		*/
    131		pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8;
    132		vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
    133		spin_lock_irqsave(&gus->reg_lock, flags);
    134		snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
    135		snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, pan);
    136		snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, rate);
    137		snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, begin << 4, voice_ctrl & 4);
    138		snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4);
    139		snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, curr << 4, voice_ctrl & 4);
    140		snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME << 4);
    141		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0x2f);
    142		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET);
    143		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, vol >> 8);
    144		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
    145		if (!gus->gf1.enh_mode) {
    146			snd_gf1_delay(gus);
    147			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
    148		}
    149		spin_unlock_irqrestore(&gus->reg_lock, flags);
    150	}
    151	spin_lock_irqsave(&gus->reg_lock, flags);
    152	for (voice = 0; voice < pcmp->voices; voice++) {
    153		snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
    154		if (gus->gf1.enh_mode)
    155			snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, 0x00);	/* deactivate voice */
    156		snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
    157		voice_ctrl &= ~0x20;
    158	}
    159	voice_ctrl |= 0x20;
    160	if (!gus->gf1.enh_mode) {
    161		snd_gf1_delay(gus);
    162		for (voice = 0; voice < pcmp->voices; voice++) {
    163			snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
    164			snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
    165			voice_ctrl &= ~0x20;	/* disable IRQ for next voice */
    166		}
    167	}
    168	spin_unlock_irqrestore(&gus->reg_lock, flags);
    169}
    170
    171static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus,
    172				       struct snd_gus_voice *pvoice)
    173{
    174	struct gus_pcm_private * pcmp;
    175	struct snd_pcm_runtime *runtime;
    176	unsigned char voice_ctrl, ramp_ctrl;
    177	unsigned int idx;
    178	unsigned int end, step;
    179
    180	if (!pvoice->private_data) {
    181		snd_printd("snd_gf1_pcm: unknown wave irq?\n");
    182		snd_gf1_smart_stop_voice(gus, pvoice->number);
    183		return;
    184	}
    185	pcmp = pvoice->private_data;
    186	if (pcmp == NULL) {
    187		snd_printd("snd_gf1_pcm: unknown wave irq?\n");
    188		snd_gf1_smart_stop_voice(gus, pvoice->number);
    189		return;
    190	}		
    191	gus = pcmp->gus;
    192	runtime = pcmp->substream->runtime;
    193
    194	spin_lock(&gus->reg_lock);
    195	snd_gf1_select_voice(gus, pvoice->number);
    196	voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & ~0x8b;
    197	ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03;
    198#if 0
    199	snd_gf1_select_voice(gus, pvoice->number);
    200	printk(KERN_DEBUG "position = 0x%x\n",
    201	       (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
    202	snd_gf1_select_voice(gus, pcmp->pvoices[1]->number);
    203	printk(KERN_DEBUG "position = 0x%x\n",
    204	       (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
    205	snd_gf1_select_voice(gus, pvoice->number);
    206#endif
    207	pcmp->bpos++;
    208	pcmp->bpos %= pcmp->blocks;
    209	if (pcmp->bpos + 1 >= pcmp->blocks) {	/* last block? */
    210		voice_ctrl |= 0x08;	/* enable loop */
    211	} else {
    212		ramp_ctrl |= 0x04;	/* enable rollover */
    213	}
    214	end = pcmp->memory + (((pcmp->bpos + 1) * pcmp->block_size) / runtime->channels);
    215	end -= voice_ctrl & 4 ? 2 : 1;
    216	step = pcmp->dma_size / runtime->channels;
    217	voice_ctrl |= 0x20;
    218	if (!pcmp->final_volume) {
    219		ramp_ctrl |= 0x20;
    220		ramp_ctrl &= ~0x03;
    221	}
    222	for (idx = 0; idx < pcmp->voices; idx++, end += step) {
    223		snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number);
    224		snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4);
    225		snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
    226		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
    227		voice_ctrl &= ~0x20;
    228	}
    229	if (!gus->gf1.enh_mode) {
    230		snd_gf1_delay(gus);
    231		voice_ctrl |= 0x20;
    232		for (idx = 0; idx < pcmp->voices; idx++) {
    233			snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number);
    234			snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
    235			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
    236			voice_ctrl &= ~0x20;
    237		}
    238	}
    239	spin_unlock(&gus->reg_lock);
    240
    241	snd_pcm_period_elapsed(pcmp->substream);
    242#if 0
    243	if ((runtime->flags & SNDRV_PCM_FLG_MMAP) &&
    244	    *runtime->state == SNDRV_PCM_STATE_RUNNING) {
    245		end = pcmp->bpos * pcmp->block_size;
    246		if (runtime->channels > 1) {
    247			snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + (end / 2), pcmp->block_size / 2);
    248			snd_gf1_pcm_block_change(pcmp->substream, end + (pcmp->block_size / 2), pcmp->memory + (pcmp->dma_size / 2) + (end / 2), pcmp->block_size / 2);
    249		} else {
    250			snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + end, pcmp->block_size);
    251		}
    252	}
    253#endif
    254}
    255
    256static void snd_gf1_pcm_interrupt_volume(struct snd_gus_card * gus,
    257					 struct snd_gus_voice * pvoice)
    258{
    259	unsigned short vol;
    260	int cvoice;
    261	struct gus_pcm_private *pcmp = pvoice->private_data;
    262
    263	/* stop ramp, but leave rollover bit untouched */
    264	spin_lock(&gus->reg_lock);
    265	snd_gf1_select_voice(gus, pvoice->number);
    266	snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
    267	spin_unlock(&gus->reg_lock);
    268	if (pcmp == NULL)
    269		return;
    270	/* are we active? */
    271	if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
    272		return;
    273	/* load real volume - better precision */
    274	cvoice = pcmp->pvoices[0] == pvoice ? 0 : 1;
    275	if (pcmp->substream == NULL)
    276		return;
    277	vol = !cvoice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
    278	spin_lock(&gus->reg_lock);
    279	snd_gf1_select_voice(gus, pvoice->number);
    280	snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol);
    281	pcmp->final_volume = 1;
    282	spin_unlock(&gus->reg_lock);
    283}
    284
    285static void snd_gf1_pcm_volume_change(struct snd_gus_card * gus)
    286{
    287}
    288
    289static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf,
    290				  unsigned int pos, unsigned int count,
    291				  int w16, int invert)
    292{
    293	unsigned int len;
    294	unsigned long flags;
    295
    296	/*
    297	printk(KERN_DEBUG
    298	       "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n",
    299	       (int)buf, pos, count, gus->gf1.port);
    300	*/
    301	while (count > 0) {
    302		len = count;
    303		if (len > 512)		/* limit, to allow IRQ */
    304			len = 512;
    305		count -= len;
    306		if (gus->interwave) {
    307			spin_lock_irqsave(&gus->reg_lock, flags);
    308			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01 | (invert ? 0x08 : 0x00));
    309			snd_gf1_dram_addr(gus, pos);
    310			if (w16) {
    311				outb(SNDRV_GF1_GW_DRAM_IO16, GUSP(gus, GF1REGSEL));
    312				outsw(GUSP(gus, GF1DATALOW), buf, len >> 1);
    313			} else {
    314				outsb(GUSP(gus, DRAM), buf, len);
    315			}
    316			spin_unlock_irqrestore(&gus->reg_lock, flags);
    317			buf += 512;
    318			pos += 512;
    319		} else {
    320			invert = invert ? 0x80 : 0x00;
    321			if (w16) {
    322				len >>= 1;
    323				while (len--) {
    324					snd_gf1_poke(gus, pos++, *buf++);
    325					snd_gf1_poke(gus, pos++, *buf++ ^ invert);
    326				}
    327			} else {
    328				while (len--)
    329					snd_gf1_poke(gus, pos++, *buf++ ^ invert);
    330			}
    331		}
    332		if (count > 0 && !in_interrupt()) {
    333			schedule_timeout_interruptible(1);
    334			if (signal_pending(current))
    335				return -EAGAIN;
    336		}
    337	}
    338	return 0;
    339}
    340
    341static int get_bpos(struct gus_pcm_private *pcmp, int voice, unsigned int pos,
    342		    unsigned int len)
    343{
    344	unsigned int bpos = pos + (voice * (pcmp->dma_size / 2));
    345	if (snd_BUG_ON(bpos > pcmp->dma_size))
    346		return -EIO;
    347	if (snd_BUG_ON(bpos + len > pcmp->dma_size))
    348		return -EIO;
    349	return bpos;
    350}
    351
    352static int playback_copy_ack(struct snd_pcm_substream *substream,
    353			     unsigned int bpos, unsigned int len)
    354{
    355	struct snd_pcm_runtime *runtime = substream->runtime;
    356	struct gus_pcm_private *pcmp = runtime->private_data;
    357	struct snd_gus_card *gus = pcmp->gus;
    358	int w16, invert;
    359
    360	if (len > 32)
    361		return snd_gf1_pcm_block_change(substream, bpos,
    362						pcmp->memory + bpos, len);
    363
    364	w16 = (snd_pcm_format_width(runtime->format) == 16);
    365	invert = snd_pcm_format_unsigned(runtime->format);
    366	return snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos,
    367				      pcmp->memory + bpos, len, w16, invert);
    368}
    369
    370static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
    371				     int voice, unsigned long pos,
    372				     void __user *src, unsigned long count)
    373{
    374	struct snd_pcm_runtime *runtime = substream->runtime;
    375	struct gus_pcm_private *pcmp = runtime->private_data;
    376	unsigned int len = count;
    377	int bpos;
    378
    379	bpos = get_bpos(pcmp, voice, pos, len);
    380	if (bpos < 0)
    381		return pos;
    382	if (copy_from_user(runtime->dma_area + bpos, src, len))
    383		return -EFAULT;
    384	return playback_copy_ack(substream, bpos, len);
    385}
    386
    387static int snd_gf1_pcm_playback_copy_kernel(struct snd_pcm_substream *substream,
    388					    int voice, unsigned long pos,
    389					    void *src, unsigned long count)
    390{
    391	struct snd_pcm_runtime *runtime = substream->runtime;
    392	struct gus_pcm_private *pcmp = runtime->private_data;
    393	unsigned int len = count;
    394	int bpos;
    395
    396	bpos = get_bpos(pcmp, voice, pos, len);
    397	if (bpos < 0)
    398		return pos;
    399	memcpy(runtime->dma_area + bpos, src, len);
    400	return playback_copy_ack(substream, bpos, len);
    401}
    402
    403static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
    404					int voice, unsigned long pos,
    405					unsigned long count)
    406{
    407	struct snd_pcm_runtime *runtime = substream->runtime;
    408	struct gus_pcm_private *pcmp = runtime->private_data;
    409	unsigned int len = count;
    410	int bpos;
    411	
    412	bpos = get_bpos(pcmp, voice, pos, len);
    413	if (bpos < 0)
    414		return pos;
    415	snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos,
    416				   bytes_to_samples(runtime, count));
    417	return playback_copy_ack(substream, bpos, len);
    418}
    419
    420static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream,
    421					  struct snd_pcm_hw_params *hw_params)
    422{
    423	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    424	struct snd_pcm_runtime *runtime = substream->runtime;
    425	struct gus_pcm_private *pcmp = runtime->private_data;
    426
    427	if (runtime->buffer_changed) {
    428		struct snd_gf1_mem_block *block;
    429		if (pcmp->memory > 0) {
    430			snd_gf1_mem_free(&gus->gf1.mem_alloc, pcmp->memory);
    431			pcmp->memory = 0;
    432		}
    433		block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
    434					  SNDRV_GF1_MEM_OWNER_DRIVER,
    435					  "GF1 PCM",
    436					  runtime->dma_bytes, 1, 32,
    437					  NULL);
    438		if (!block)
    439			return -ENOMEM;
    440		pcmp->memory = block->ptr;
    441	}
    442	pcmp->voices = params_channels(hw_params);
    443	if (pcmp->pvoices[0] == NULL) {
    444		pcmp->pvoices[0] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0);
    445		if (!pcmp->pvoices[0])
    446			return -ENOMEM;
    447		pcmp->pvoices[0]->handler_wave = snd_gf1_pcm_interrupt_wave;
    448		pcmp->pvoices[0]->handler_volume = snd_gf1_pcm_interrupt_volume;
    449		pcmp->pvoices[0]->volume_change = snd_gf1_pcm_volume_change;
    450		pcmp->pvoices[0]->private_data = pcmp;
    451	}
    452	if (pcmp->voices > 1 && pcmp->pvoices[1] == NULL) {
    453		pcmp->pvoices[1] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0);
    454		if (!pcmp->pvoices[1])
    455			return -ENOMEM;
    456		pcmp->pvoices[1]->handler_wave = snd_gf1_pcm_interrupt_wave;
    457		pcmp->pvoices[1]->handler_volume = snd_gf1_pcm_interrupt_volume;
    458		pcmp->pvoices[1]->volume_change = snd_gf1_pcm_volume_change;
    459		pcmp->pvoices[1]->private_data = pcmp;
    460	} else if (pcmp->voices == 1) {
    461		if (pcmp->pvoices[1]) {
    462			snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]);
    463			pcmp->pvoices[1] = NULL;
    464		}
    465	}
    466	return 0;
    467}
    468
    469static int snd_gf1_pcm_playback_hw_free(struct snd_pcm_substream *substream)
    470{
    471	struct snd_pcm_runtime *runtime = substream->runtime;
    472	struct gus_pcm_private *pcmp = runtime->private_data;
    473
    474	if (pcmp->pvoices[0]) {
    475		snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[0]);
    476		pcmp->pvoices[0] = NULL;
    477	}
    478	if (pcmp->pvoices[1]) {
    479		snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]);
    480		pcmp->pvoices[1] = NULL;
    481	}
    482	if (pcmp->memory > 0) {
    483		snd_gf1_mem_free(&pcmp->gus->gf1.mem_alloc, pcmp->memory);
    484		pcmp->memory = 0;
    485	}
    486	return 0;
    487}
    488
    489static int snd_gf1_pcm_playback_prepare(struct snd_pcm_substream *substream)
    490{
    491	struct snd_pcm_runtime *runtime = substream->runtime;
    492	struct gus_pcm_private *pcmp = runtime->private_data;
    493
    494	pcmp->bpos = 0;
    495	pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream);
    496	pcmp->block_size = snd_pcm_lib_period_bytes(substream);
    497	pcmp->blocks = pcmp->dma_size / pcmp->block_size;
    498	return 0;
    499}
    500
    501static int snd_gf1_pcm_playback_trigger(struct snd_pcm_substream *substream,
    502					int cmd)
    503{
    504	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    505	struct snd_pcm_runtime *runtime = substream->runtime;
    506	struct gus_pcm_private *pcmp = runtime->private_data;
    507	int voice;
    508
    509	if (cmd == SNDRV_PCM_TRIGGER_START) {
    510		snd_gf1_pcm_trigger_up(substream);
    511	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
    512		spin_lock(&pcmp->lock);
    513		pcmp->flags &= ~SNDRV_GF1_PCM_PFLG_ACTIVE;
    514		spin_unlock(&pcmp->lock);
    515		voice = pcmp->pvoices[0]->number;
    516		snd_gf1_stop_voices(gus, voice, voice);
    517		if (pcmp->pvoices[1]) {
    518			voice = pcmp->pvoices[1]->number;
    519			snd_gf1_stop_voices(gus, voice, voice);
    520		}
    521	} else {
    522		return -EINVAL;
    523	}
    524	return 0;
    525}
    526
    527static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream *substream)
    528{
    529	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    530	struct snd_pcm_runtime *runtime = substream->runtime;
    531	struct gus_pcm_private *pcmp = runtime->private_data;
    532	unsigned int pos;
    533	unsigned char voice_ctrl;
    534
    535	pos = 0;
    536	spin_lock(&gus->reg_lock);
    537	if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) {
    538		snd_gf1_select_voice(gus, pcmp->pvoices[0]->number);
    539		voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
    540		pos = (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4) - pcmp->memory;
    541		if (substream->runtime->channels > 1)
    542			pos <<= 1;
    543		pos = bytes_to_frames(runtime, pos);
    544	}
    545	spin_unlock(&gus->reg_lock);
    546	return pos;
    547}
    548
    549static const struct snd_ratnum clock = {
    550	.num = 9878400/16,
    551	.den_min = 2,
    552	.den_max = 257,
    553	.den_step = 1,
    554};
    555
    556static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks  = {
    557	.nrats = 1,
    558	.rats = &clock,
    559};
    560
    561static int snd_gf1_pcm_capture_hw_params(struct snd_pcm_substream *substream,
    562					 struct snd_pcm_hw_params *hw_params)
    563{
    564	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    565
    566	gus->c_dma_size = params_buffer_bytes(hw_params);
    567	gus->c_period_size = params_period_bytes(hw_params);
    568	gus->c_pos = 0;
    569	gus->gf1.pcm_rcntrl_reg = 0x21;		/* IRQ at end, enable & start */
    570	if (params_channels(hw_params) > 1)
    571		gus->gf1.pcm_rcntrl_reg |= 2;
    572	if (gus->gf1.dma2 > 3)
    573		gus->gf1.pcm_rcntrl_reg |= 4;
    574	if (snd_pcm_format_unsigned(params_format(hw_params)))
    575		gus->gf1.pcm_rcntrl_reg |= 0x80;
    576	return 0;
    577}
    578
    579static int snd_gf1_pcm_capture_prepare(struct snd_pcm_substream *substream)
    580{
    581	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    582	struct snd_pcm_runtime *runtime = substream->runtime;
    583
    584	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RECORD_RATE, runtime->rate_den - 2);
    585	snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0);	/* disable sampling */
    586	snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL);	/* Sampling Control Register */
    587	snd_dma_program(gus->gf1.dma2, runtime->dma_addr, gus->c_period_size, DMA_MODE_READ);
    588	return 0;
    589}
    590
    591static int snd_gf1_pcm_capture_trigger(struct snd_pcm_substream *substream,
    592				       int cmd)
    593{
    594	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    595	int val;
    596	
    597	if (cmd == SNDRV_PCM_TRIGGER_START) {
    598		val = gus->gf1.pcm_rcntrl_reg;
    599	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
    600		val = 0;
    601	} else {
    602		return -EINVAL;
    603	}
    604
    605	spin_lock(&gus->reg_lock);
    606	snd_gf1_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, val);
    607	snd_gf1_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL);
    608	spin_unlock(&gus->reg_lock);
    609	return 0;
    610}
    611
    612static snd_pcm_uframes_t snd_gf1_pcm_capture_pointer(struct snd_pcm_substream *substream)
    613{
    614	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    615	int pos = snd_dma_pointer(gus->gf1.dma2, gus->c_period_size);
    616	pos = bytes_to_frames(substream->runtime, (gus->c_pos + pos) % gus->c_dma_size);
    617	return pos;
    618}
    619
    620static void snd_gf1_pcm_interrupt_dma_read(struct snd_gus_card * gus)
    621{
    622	snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0);	/* disable sampling */
    623	snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL);	/* Sampling Control Register */
    624	if (gus->pcm_cap_substream != NULL) {
    625		snd_gf1_pcm_capture_prepare(gus->pcm_cap_substream); 
    626		snd_gf1_pcm_capture_trigger(gus->pcm_cap_substream, SNDRV_PCM_TRIGGER_START);
    627		gus->c_pos += gus->c_period_size;
    628		snd_pcm_period_elapsed(gus->pcm_cap_substream);
    629	}
    630}
    631
    632static const struct snd_pcm_hardware snd_gf1_pcm_playback =
    633{
    634	.info =			SNDRV_PCM_INFO_NONINTERLEAVED,
    635	.formats		= (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
    636				 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
    637	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
    638	.rate_min =		5510,
    639	.rate_max =		48000,
    640	.channels_min =		1,
    641	.channels_max =		2,
    642	.buffer_bytes_max =	(128*1024),
    643	.period_bytes_min =	64,
    644	.period_bytes_max =	(128*1024),
    645	.periods_min =		1,
    646	.periods_max =		1024,
    647	.fifo_size =		0,
    648};
    649
    650static const struct snd_pcm_hardware snd_gf1_pcm_capture =
    651{
    652	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
    653				 SNDRV_PCM_INFO_MMAP_VALID),
    654	.formats =		SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8,
    655	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100,
    656	.rate_min =		5510,
    657	.rate_max =		44100,
    658	.channels_min =		1,
    659	.channels_max =		2,
    660	.buffer_bytes_max =	(128*1024),
    661	.period_bytes_min =	64,
    662	.period_bytes_max =	(128*1024),
    663	.periods_min =		1,
    664	.periods_max =		1024,
    665	.fifo_size =		0,
    666};
    667
    668static void snd_gf1_pcm_playback_free(struct snd_pcm_runtime *runtime)
    669{
    670	kfree(runtime->private_data);
    671}
    672
    673static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream)
    674{
    675	struct gus_pcm_private *pcmp;
    676	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    677	struct snd_pcm_runtime *runtime = substream->runtime;
    678	int err;
    679
    680	pcmp = kzalloc(sizeof(*pcmp), GFP_KERNEL);
    681	if (pcmp == NULL)
    682		return -ENOMEM;
    683	pcmp->gus = gus;
    684	spin_lock_init(&pcmp->lock);
    685	init_waitqueue_head(&pcmp->sleep);
    686	atomic_set(&pcmp->dma_count, 0);
    687
    688	runtime->private_data = pcmp;
    689	runtime->private_free = snd_gf1_pcm_playback_free;
    690
    691#if 0
    692	printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n",
    693	       (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer);
    694#endif
    695	err = snd_gf1_dma_init(gus);
    696	if (err < 0)
    697		return err;
    698	pcmp->flags = SNDRV_GF1_PCM_PFLG_NONE;
    699	pcmp->substream = substream;
    700	runtime->hw = snd_gf1_pcm_playback;
    701	snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.buffer_bytes_max);
    702	snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.period_bytes_max);
    703	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
    704	return 0;
    705}
    706
    707static int snd_gf1_pcm_playback_close(struct snd_pcm_substream *substream)
    708{
    709	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    710	struct snd_pcm_runtime *runtime = substream->runtime;
    711	struct gus_pcm_private *pcmp = runtime->private_data;
    712	
    713	if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ))
    714		snd_printk(KERN_ERR "gf1 pcm - serious DMA problem\n");
    715
    716	snd_gf1_dma_done(gus);	
    717	return 0;
    718}
    719
    720static int snd_gf1_pcm_capture_open(struct snd_pcm_substream *substream)
    721{
    722	struct snd_pcm_runtime *runtime = substream->runtime;
    723	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    724
    725	gus->gf1.interrupt_handler_dma_read = snd_gf1_pcm_interrupt_dma_read;
    726	gus->pcm_cap_substream = substream;
    727	substream->runtime->hw = snd_gf1_pcm_capture;
    728	snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.buffer_bytes_max);
    729	snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.period_bytes_max);
    730	snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
    731				      &hw_constraints_clocks);
    732	return 0;
    733}
    734
    735static int snd_gf1_pcm_capture_close(struct snd_pcm_substream *substream)
    736{
    737	struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
    738
    739	gus->pcm_cap_substream = NULL;
    740	snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_READ);
    741	return 0;
    742}
    743
    744static int snd_gf1_pcm_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    745{
    746	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    747	uinfo->count = 2;
    748	uinfo->value.integer.min = 0;
    749	uinfo->value.integer.max = 127;
    750	return 0;
    751}
    752
    753static int snd_gf1_pcm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    754{
    755	struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
    756	unsigned long flags;
    757	
    758	spin_lock_irqsave(&gus->pcm_volume_level_lock, flags);
    759	ucontrol->value.integer.value[0] = gus->gf1.pcm_volume_level_left1;
    760	ucontrol->value.integer.value[1] = gus->gf1.pcm_volume_level_right1;
    761	spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags);
    762	return 0;
    763}
    764
    765static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    766{
    767	struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
    768	unsigned long flags;
    769	int change;
    770	unsigned int idx;
    771	unsigned short val1, val2, vol;
    772	struct gus_pcm_private *pcmp;
    773	struct snd_gus_voice *pvoice;
    774	
    775	val1 = ucontrol->value.integer.value[0] & 127;
    776	val2 = ucontrol->value.integer.value[1] & 127;
    777	spin_lock_irqsave(&gus->pcm_volume_level_lock, flags);
    778	change = val1 != gus->gf1.pcm_volume_level_left1 ||
    779	         val2 != gus->gf1.pcm_volume_level_right1;
    780	gus->gf1.pcm_volume_level_left1 = val1;
    781	gus->gf1.pcm_volume_level_right1 = val2;
    782	gus->gf1.pcm_volume_level_left = snd_gf1_lvol_to_gvol_raw(val1 << 9) << 4;
    783	gus->gf1.pcm_volume_level_right = snd_gf1_lvol_to_gvol_raw(val2 << 9) << 4;
    784	spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags);
    785	/* are we active? */
    786	spin_lock_irqsave(&gus->voice_alloc, flags);
    787	for (idx = 0; idx < 32; idx++) {
    788		pvoice = &gus->gf1.voices[idx];
    789		if (!pvoice->pcm)
    790			continue;
    791		pcmp = pvoice->private_data;
    792		if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
    793			continue;
    794		/* load real volume - better precision */
    795		spin_lock(&gus->reg_lock);
    796		snd_gf1_select_voice(gus, pvoice->number);
    797		snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
    798		vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
    799		snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol);
    800		pcmp->final_volume = 1;
    801		spin_unlock(&gus->reg_lock);
    802	}
    803	spin_unlock_irqrestore(&gus->voice_alloc, flags);
    804	return change;
    805}
    806
    807static const struct snd_kcontrol_new snd_gf1_pcm_volume_control =
    808{
    809	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    810	.name = "PCM Playback Volume",
    811	.info = snd_gf1_pcm_volume_info,
    812	.get = snd_gf1_pcm_volume_get,
    813	.put = snd_gf1_pcm_volume_put
    814};
    815
    816static const struct snd_kcontrol_new snd_gf1_pcm_volume_control1 =
    817{
    818	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    819	.name = "GPCM Playback Volume",
    820	.info = snd_gf1_pcm_volume_info,
    821	.get = snd_gf1_pcm_volume_get,
    822	.put = snd_gf1_pcm_volume_put
    823};
    824
    825static const struct snd_pcm_ops snd_gf1_pcm_playback_ops = {
    826	.open =		snd_gf1_pcm_playback_open,
    827	.close =	snd_gf1_pcm_playback_close,
    828	.hw_params =	snd_gf1_pcm_playback_hw_params,
    829	.hw_free =	snd_gf1_pcm_playback_hw_free,
    830	.prepare =	snd_gf1_pcm_playback_prepare,
    831	.trigger =	snd_gf1_pcm_playback_trigger,
    832	.pointer =	snd_gf1_pcm_playback_pointer,
    833	.copy_user =	snd_gf1_pcm_playback_copy,
    834	.copy_kernel =	snd_gf1_pcm_playback_copy_kernel,
    835	.fill_silence =	snd_gf1_pcm_playback_silence,
    836};
    837
    838static const struct snd_pcm_ops snd_gf1_pcm_capture_ops = {
    839	.open =		snd_gf1_pcm_capture_open,
    840	.close =	snd_gf1_pcm_capture_close,
    841	.hw_params =	snd_gf1_pcm_capture_hw_params,
    842	.prepare =	snd_gf1_pcm_capture_prepare,
    843	.trigger =	snd_gf1_pcm_capture_trigger,
    844	.pointer =	snd_gf1_pcm_capture_pointer,
    845};
    846
    847int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index)
    848{
    849	struct snd_card *card;
    850	struct snd_kcontrol *kctl;
    851	struct snd_pcm *pcm;
    852	struct snd_pcm_substream *substream;
    853	int capture, err;
    854
    855	card = gus->card;
    856	capture = !gus->interwave && !gus->ess_flag && !gus->ace_flag ? 1 : 0;
    857	err = snd_pcm_new(card,
    858			  gus->interwave ? "AMD InterWave" : "GF1",
    859			  pcm_dev,
    860			  gus->gf1.pcm_channels / 2,
    861			  capture,
    862			  &pcm);
    863	if (err < 0)
    864		return err;
    865	pcm->private_data = gus;
    866	/* playback setup */
    867	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_gf1_pcm_playback_ops);
    868
    869	for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
    870		snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
    871					   card->dev,
    872					   64*1024, gus->gf1.dma1 > 3 ? 128*1024 : 64*1024);
    873	
    874	pcm->info_flags = 0;
    875	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
    876	if (capture) {
    877		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_gf1_pcm_capture_ops);
    878		if (gus->gf1.dma2 == gus->gf1.dma1)
    879			pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
    880		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
    881					   SNDRV_DMA_TYPE_DEV, card->dev,
    882					   64*1024, gus->gf1.dma2 > 3 ? 128*1024 : 64*1024);
    883	}
    884	strcpy(pcm->name, pcm->id);
    885	if (gus->interwave) {
    886		sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
    887	}
    888	strcat(pcm->name, " (synth)");
    889	gus->pcm = pcm;
    890
    891	if (gus->codec_flag)
    892		kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus);
    893	else
    894		kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus);
    895	err = snd_ctl_add(card, kctl);
    896	if (err < 0)
    897		return err;
    898	kctl->id.index = control_index;
    899
    900	return 0;
    901}
    902