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