cregit-Linux how code gets into the kernel

Release 4.8 sound/isa/gus/gus_dma.c

Directory: sound/isa/gus
/*
 *  Routines for GF1 DMA control
 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

#include <asm/dma.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/gus.h>


static void snd_gf1_dma_ack(struct snd_gus_card * gus) { unsigned long flags; spin_lock_irqsave(&gus->reg_lock, flags); snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, 0x00); snd_gf1_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL); spin_unlock_irqrestore(&gus->reg_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela4996.08%266.67%
takashi iwaitakashi iwai23.92%133.33%
Total51100.00%3100.00%


static void snd_gf1_dma_program(struct snd_gus_card * gus, unsigned int addr, unsigned long buf_addr, unsigned int count, unsigned int cmd) { unsigned long flags; unsigned int address; unsigned char dma_cmd; unsigned int address_high; snd_printdd("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", addr, buf_addr, count); if (gus->gf1.dma1 > 3) { if (gus->gf1.enh_mode) { address = addr >> 1; } else { if (addr & 0x1f) { snd_printd("snd_gf1_dma_transfer: unaligned address (0x%x)?\n", addr); return; } address = (addr & 0x000c0000) | ((addr & 0x0003ffff) >> 1); } } else { address = addr; } dma_cmd = SNDRV_GF1_DMA_ENABLE | (unsigned short) cmd; #if 0 dma_cmd |= 0x08; #endif if (dma_cmd & SNDRV_GF1_DMA_16BIT) { count++; count &= ~1; /* align */ } if (gus->gf1.dma1 > 3) { dma_cmd |= SNDRV_GF1_DMA_WIDTH16; count++; count &= ~1; /* align */ } snd_gf1_dma_ack(gus); snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); #if 0 snd_printk(KERN_DEBUG "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", address << 1, count, dma_cmd); #endif spin_lock_irqsave(&gus->reg_lock, flags); if (gus->gf1.enh_mode) { address_high = ((address >> 16) & 0x000000f0) | (address & 0x0000000f); snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH, (unsigned char) address_high); } else snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, dma_cmd); spin_unlock_irqrestore(&gus->reg_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela30795.64%350.00%
krzysztof heltkrzysztof helt113.43%116.67%
takashi iwaitakashi iwai30.93%233.33%
Total321100.00%6100.00%


static struct snd_gf1_dma_block *snd_gf1_dma_next_block(struct snd_gus_card * gus) { struct snd_gf1_dma_block *block; /* PCM block have bigger priority than synthesizer one */ if (gus->gf1.dma_data_pcm) { block = gus->gf1.dma_data_pcm; if (gus->gf1.dma_data_pcm_last == block) { gus->gf1.dma_data_pcm = gus->gf1.dma_data_pcm_last = NULL; } else { gus->gf1.dma_data_pcm = block->next; } } else if (gus->gf1.dma_data_synth) { block = gus->gf1.dma_data_synth; if (gus->gf1.dma_data_synth_last == block) { gus->gf1.dma_data_synth = gus->gf1.dma_data_synth_last = NULL; } else { gus->gf1.dma_data_synth = block->next; } } else { block = NULL; } if (block) { gus->gf1.dma_ack = block->ack; gus->gf1.dma_private_data = block->private_data; } return block; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela16496.47%150.00%
takashi iwaitakashi iwai63.53%150.00%
Total170100.00%2100.00%


static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) { struct snd_gf1_dma_block *block; snd_gf1_dma_ack(gus); if (gus->gf1.dma_ack) gus->gf1.dma_ack(gus, gus->gf1.dma_private_data); spin_lock(&gus->dma_lock); if (gus->gf1.dma_data_pcm == NULL && gus->gf1.dma_data_synth == NULL) { gus->gf1.dma_ack = NULL; gus->gf1.dma_flags &= ~SNDRV_GF1_DMA_TRIGGER; spin_unlock(&gus->dma_lock); return; } block = snd_gf1_dma_next_block(gus); spin_unlock(&gus->dma_lock); snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); kfree(block); #if 0 snd_printd(KERN_DEBUG "program dma (IRQ) - " "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", block->addr, block->buf_addr, block->count, block->cmd); #endif }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela14496.64%250.00%
takashi iwaitakashi iwai42.68%125.00%
krzysztof heltkrzysztof helt10.67%125.00%
Total149100.00%4100.00%


int snd_gf1_dma_init(struct snd_gus_card * gus) { mutex_lock(&gus->dma_mutex); gus->gf1.dma_shared++; if (gus->gf1.dma_shared > 1) { mutex_unlock(&gus->dma_mutex); return 0; } gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt; gus->gf1.dma_data_pcm = gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth = gus->gf1.dma_data_synth_last = NULL; mutex_unlock(&gus->dma_mutex); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela8894.62%133.33%
ingo molnaringo molnar33.23%133.33%
takashi iwaitakashi iwai22.15%133.33%
Total93100.00%3100.00%


int snd_gf1_dma_done(struct snd_gus_card * gus) { struct snd_gf1_dma_block *block; mutex_lock(&gus->dma_mutex); gus->gf1.dma_shared--; if (!gus->gf1.dma_shared) { snd_dma_disable(gus->gf1.dma1); snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_WRITE); snd_gf1_dma_ack(gus); while ((block = gus->gf1.dma_data_pcm)) { gus->gf1.dma_data_pcm = block->next; kfree(block); } while ((block = gus->gf1.dma_data_synth)) { gus->gf1.dma_data_synth = block->next; kfree(block); } gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth_last = NULL; } mutex_unlock(&gus->dma_mutex); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela13995.86%133.33%
takashi iwaitakashi iwai42.76%133.33%
ingo molnaringo molnar21.38%133.33%
Total145100.00%3100.00%


int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, struct snd_gf1_dma_block * __block, int atomic, int synth) { unsigned long flags; struct snd_gf1_dma_block *block; block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL); if (block == NULL) { snd_printk(KERN_ERR "gf1: DMA transfer failure; not enough memory\n"); return -ENOMEM; } *block = *__block; block->next = NULL; snd_printdd("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", block->addr, (long) block->buffer, block->count, block->cmd); snd_printdd("gus->gf1.dma_data_pcm_last = 0x%lx\n", (long)gus->gf1.dma_data_pcm_last); snd_printdd("gus->gf1.dma_data_pcm = 0x%lx\n", (long)gus->gf1.dma_data_pcm); spin_lock_irqsave(&gus->dma_lock, flags); if (synth) { if (gus->gf1.dma_data_synth_last) { gus->gf1.dma_data_synth_last->next = block; gus->gf1.dma_data_synth_last = block; } else { gus->gf1.dma_data_synth = gus->gf1.dma_data_synth_last = block; } } else { if (gus->gf1.dma_data_pcm_last) { gus->gf1.dma_data_pcm_last->next = block; gus->gf1.dma_data_pcm_last = block; } else { gus->gf1.dma_data_pcm = gus->gf1.dma_data_pcm_last = block; } } if (!(gus->gf1.dma_flags & SNDRV_GF1_DMA_TRIGGER)) { gus->gf1.dma_flags |= SNDRV_GF1_DMA_TRIGGER; block = snd_gf1_dma_next_block(gus); spin_unlock_irqrestore(&gus->dma_lock, flags); if (block == NULL) return 0; snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); kfree(block); return 0; } spin_unlock_irqrestore(&gus->dma_lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela27482.28%240.00%
krzysztof heltkrzysztof helt5215.62%120.00%
takashi iwaitakashi iwai72.10%240.00%
Total333100.00%5100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela117892.39%444.44%
krzysztof heltkrzysztof helt645.02%111.11%
takashi iwaitakashi iwai282.20%333.33%
ingo molnaringo molnar50.39%111.11%
Total1275100.00%9100.00%
Directory: sound/isa/gus
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.