File Index
Files and directories
Sign in
FILE

gus_pcm.c

File preview with syntax highlighting.

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