1 /* 2 * Routines for GF1 DMA control 3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <sound/driver.h> 23 #include <asm/dma.h> 24 #include <linux/slab.h> 25 #include <sound/core.h> 26 #include <sound/gus.h> 27 28 static void snd_gf1_dma_ack(struct snd_gus_card * gus) 29 { 30 unsigned long flags; 31 32 spin_lock_irqsave(&gus->reg_lock, flags); 33 snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, 0x00); 34 snd_gf1_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL); 35 spin_unlock_irqrestore(&gus->reg_lock, flags); 36 } 37 38 static void snd_gf1_dma_program(struct snd_gus_card * gus, 39 unsigned int addr, 40 unsigned long buf_addr, 41 unsigned int count, 42 unsigned int cmd) 43 { 44 unsigned long flags; 45 unsigned int address; 46 unsigned char dma_cmd; 47 unsigned int address_high; 48 49 // snd_printk("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", addr, (long) buf, count); 50 51 if (gus->gf1.dma1 > 3) { 52 if (gus->gf1.enh_mode) { 53 address = addr >> 1; 54 } else { 55 if (addr & 0x1f) { 56 snd_printd("snd_gf1_dma_transfer: unaligned address (0x%x)?\n", addr); 57 return; 58 } 59 address = (addr & 0x000c0000) | ((addr & 0x0003ffff) >> 1); 60 } 61 } else { 62 address = addr; 63 } 64 65 dma_cmd = SNDRV_GF1_DMA_ENABLE | (unsigned short) cmd; 66 #if 0 67 dma_cmd |= 0x08; 68 #endif 69 if (dma_cmd & SNDRV_GF1_DMA_16BIT) { 70 count++; 71 count &= ~1; /* align */ 72 } 73 if (gus->gf1.dma1 > 3) { 74 dma_cmd |= SNDRV_GF1_DMA_WIDTH16; 75 count++; 76 count &= ~1; /* align */ 77 } 78 snd_gf1_dma_ack(gus); 79 snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); 80 #if 0 81 snd_printk("address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", address << 1, count, dma_cmd); 82 #endif 83 spin_lock_irqsave(&gus->reg_lock, flags); 84 if (gus->gf1.enh_mode) { 85 address_high = ((address >> 16) & 0x000000f0) | (address & 0x0000000f); 86 snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); 87 snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH, (unsigned char) address_high); 88 } else 89 snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); 90 snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, dma_cmd); 91 spin_unlock_irqrestore(&gus->reg_lock, flags); 92 } 93 94 static struct snd_gf1_dma_block *snd_gf1_dma_next_block(struct snd_gus_card * gus) 95 { 96 struct snd_gf1_dma_block *block; 97 98 /* PCM block have bigger priority than synthesizer one */ 99 if (gus->gf1.dma_data_pcm) { 100 block = gus->gf1.dma_data_pcm; 101 if (gus->gf1.dma_data_pcm_last == block) { 102 gus->gf1.dma_data_pcm = 103 gus->gf1.dma_data_pcm_last = NULL; 104 } else { 105 gus->gf1.dma_data_pcm = block->next; 106 } 107 } else if (gus->gf1.dma_data_synth) { 108 block = gus->gf1.dma_data_synth; 109 if (gus->gf1.dma_data_synth_last == block) { 110 gus->gf1.dma_data_synth = 111 gus->gf1.dma_data_synth_last = NULL; 112 } else { 113 gus->gf1.dma_data_synth = block->next; 114 } 115 } else { 116 block = NULL; 117 } 118 if (block) { 119 gus->gf1.dma_ack = block->ack; 120 gus->gf1.dma_private_data = block->private_data; 121 } 122 return block; 123 } 124 125 126 static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) 127 { 128 struct snd_gf1_dma_block *block; 129 130 snd_gf1_dma_ack(gus); 131 if (gus->gf1.dma_ack) 132 gus->gf1.dma_ack(gus, gus->gf1.dma_private_data); 133 spin_lock(&gus->dma_lock); 134 if (gus->gf1.dma_data_pcm == NULL && 135 gus->gf1.dma_data_synth == NULL) { 136 gus->gf1.dma_ack = NULL; 137 gus->gf1.dma_flags &= ~SNDRV_GF1_DMA_TRIGGER; 138 spin_unlock(&gus->dma_lock); 139 return; 140 } 141 block = snd_gf1_dma_next_block(gus); 142 spin_unlock(&gus->dma_lock); 143 snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); 144 kfree(block); 145 #if 0 146 printk("program dma (IRQ) - addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", addr, (long) buffer, count, cmd); 147 #endif 148 } 149 150 int snd_gf1_dma_init(struct snd_gus_card * gus) 151 { 152 mutex_lock(&gus->dma_mutex); 153 gus->gf1.dma_shared++; 154 if (gus->gf1.dma_shared > 1) { 155 mutex_unlock(&gus->dma_mutex); 156 return 0; 157 } 158 gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt; 159 gus->gf1.dma_data_pcm = 160 gus->gf1.dma_data_pcm_last = 161 gus->gf1.dma_data_synth = 162 gus->gf1.dma_data_synth_last = NULL; 163 mutex_unlock(&gus->dma_mutex); 164 return 0; 165 } 166 167 int snd_gf1_dma_done(struct snd_gus_card * gus) 168 { 169 struct snd_gf1_dma_block *block; 170 171 mutex_lock(&gus->dma_mutex); 172 gus->gf1.dma_shared--; 173 if (!gus->gf1.dma_shared) { 174 snd_dma_disable(gus->gf1.dma1); 175 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_WRITE); 176 snd_gf1_dma_ack(gus); 177 while ((block = gus->gf1.dma_data_pcm)) { 178 gus->gf1.dma_data_pcm = block->next; 179 kfree(block); 180 } 181 while ((block = gus->gf1.dma_data_synth)) { 182 gus->gf1.dma_data_synth = block->next; 183 kfree(block); 184 } 185 gus->gf1.dma_data_pcm_last = 186 gus->gf1.dma_data_synth_last = NULL; 187 } 188 mutex_unlock(&gus->dma_mutex); 189 return 0; 190 } 191 192 int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, 193 struct snd_gf1_dma_block * __block, 194 int atomic, 195 int synth) 196 { 197 unsigned long flags; 198 struct snd_gf1_dma_block *block; 199 200 block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL); 201 if (block == NULL) { 202 snd_printk(KERN_ERR "gf1: DMA transfer failure; not enough memory\n"); 203 return -ENOMEM; 204 } 205 *block = *__block; 206 block->next = NULL; 207 #if 0 208 printk("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", block->addr, (long) block->buffer, block->count, block->cmd); 209 #endif 210 #if 0 211 printk("gus->gf1.dma_data_pcm_last = 0x%lx\n", (long)gus->gf1.dma_data_pcm_last); 212 printk("gus->gf1.dma_data_pcm = 0x%lx\n", (long)gus->gf1.dma_data_pcm); 213 #endif 214 spin_lock_irqsave(&gus->dma_lock, flags); 215 if (synth) { 216 if (gus->gf1.dma_data_synth_last) { 217 gus->gf1.dma_data_synth_last->next = block; 218 gus->gf1.dma_data_synth_last = block; 219 } else { 220 gus->gf1.dma_data_synth = 221 gus->gf1.dma_data_synth_last = block; 222 } 223 } else { 224 if (gus->gf1.dma_data_pcm_last) { 225 gus->gf1.dma_data_pcm_last->next = block; 226 gus->gf1.dma_data_pcm_last = block; 227 } else { 228 gus->gf1.dma_data_pcm = 229 gus->gf1.dma_data_pcm_last = block; 230 } 231 } 232 if (!(gus->gf1.dma_flags & SNDRV_GF1_DMA_TRIGGER)) { 233 gus->gf1.dma_flags |= SNDRV_GF1_DMA_TRIGGER; 234 block = snd_gf1_dma_next_block(gus); 235 spin_unlock_irqrestore(&gus->dma_lock, flags); 236 if (block == NULL) 237 return 0; 238 snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); 239 kfree(block); 240 return 0; 241 } 242 spin_unlock_irqrestore(&gus->dma_lock, flags); 243 return 0; 244 } 245