cregit-Linux how code gets into the kernel

Release 4.11 sound/pci/emu10k1/emu10k1_patch.c

/*
 *  Patch transfer callback for Emu10k1
 *
 *  Copyright (C) 2000 Takashi iwai <tiwai@suse.de>
 *
 *   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
 */
/*
 * All the code for loading in a patch.  There is very little that is
 * chip specific here.  Just the actual writing to the board.
 */

#include "emu10k1_synth_local.h"

/*
 */

#define BLANK_LOOP_START	4

#define BLANK_LOOP_END		8

#define BLANK_LOOP_SIZE		12

#define BLANK_HEAD_SIZE		32

/*
 * allocate a sample block and copy data from userspace
 */

int snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, struct snd_util_memhdr *hdr, const void __user *data, long count) { int offset; int truesize, size, loopsize, blocksize; int loopend, sampleend; unsigned int start_addr; struct snd_emu10k1 *emu; emu = rec->hw; if (snd_BUG_ON(!sp || !hdr)) return -EINVAL; if (sp->v.size == 0) { dev_dbg(emu->card->dev, "emu: rom font for sample %d\n", sp->v.sample); return 0; } /* recalculate address offset */ sp->v.end -= sp->v.start; sp->v.loopstart -= sp->v.start; sp->v.loopend -= sp->v.start; sp->v.start = 0; /* some samples have invalid data. the addresses are corrected in voice info */ sampleend = sp->v.end; if (sampleend > sp->v.size) sampleend = sp->v.size; loopend = sp->v.loopend; if (loopend > sampleend) loopend = sampleend; /* be sure loop points start < end */ if (sp->v.loopstart >= sp->v.loopend) { int tmp = sp->v.loopstart; sp->v.loopstart = sp->v.loopend; sp->v.loopend = tmp; } /* compute true data size to be loaded */ truesize = sp->v.size + BLANK_HEAD_SIZE; loopsize = 0; #if 0 /* not supported */ if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) loopsize = sp->v.loopend - sp->v.loopstart; truesize += loopsize; #endif if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) truesize += BLANK_LOOP_SIZE; /* try to allocate a memory block */ blocksize = truesize; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) blocksize *= 2; sp->block = snd_emu10k1_synth_alloc(emu, blocksize); if (sp->block == NULL) { dev_dbg(emu->card->dev, "synth malloc failed (size=%d)\n", blocksize); /* not ENOMEM (for compatibility with OSS) */ return -ENOSPC; } /* set the total size */ sp->v.truesize = blocksize; /* write blank samples at head */ offset = 0; size = BLANK_HEAD_SIZE; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) size *= 2; if (offset + size > blocksize) return -EINVAL; snd_emu10k1_synth_bzero(emu, sp->block, offset, size); offset += size; /* copy start->loopend */ size = loopend; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) size *= 2; if (offset + size > blocksize) return -EINVAL; if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { snd_emu10k1_synth_free(emu, sp->block); sp->block = NULL; return -EFAULT; } offset += size; data += size; #if 0 /* not supported yet */ /* handle reverse (or bidirectional) loop */ if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) { /* copy loop in reverse */ if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) { int woffset; unsigned short *wblock = (unsigned short*)block; woffset = offset / 2; if (offset + loopsize * 2 > blocksize) return -EINVAL; for (i = 0; i < loopsize; i++) wblock[woffset + i] = wblock[woffset - i -1]; offset += loopsize * 2; } else { if (offset + loopsize > blocksize) return -EINVAL; for (i = 0; i < loopsize; i++) block[offset + i] = block[offset - i -1]; offset += loopsize; } /* modify loop pointers */ if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) { sp->v.loopend += loopsize; } else { sp->v.loopstart += loopsize; sp->v.loopend += loopsize; } /* add sample pointer */ sp->v.end += loopsize; } #endif /* loopend -> sample end */ size = sp->v.size - loopend; if (size < 0) return -EINVAL; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) size *= 2; if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { snd_emu10k1_synth_free(emu, sp->block); sp->block = NULL; return -EFAULT; } offset += size; /* clear rest of samples (if any) */ if (offset < blocksize) snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset); if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) { /* if no blank loop is attached in the sample, add it */ if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) { sp->v.loopstart = sp->v.end + BLANK_LOOP_START; sp->v.loopend = sp->v.end + BLANK_LOOP_END; } } #if 0 /* not supported yet */ if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) { /* unsigned -> signed */ if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) { unsigned short *wblock = (unsigned short*)block; for (i = 0; i < truesize; i++) wblock[i] ^= 0x8000; } else { for (i = 0; i < truesize; i++) block[i] ^= 0x80; } } #endif /* recalculate offset */ start_addr = BLANK_HEAD_SIZE * 2; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) start_addr >>= 1; sp->v.start += start_addr; sp->v.end += start_addr; sp->v.loopstart += start_addr; sp->v.loopend += start_addr; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela65190.17%342.86%
Takashi Iwai709.70%342.86%
Masanari Iida10.14%114.29%
Total722100.00%7100.00%

/* * free a sample block */
int snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, struct snd_util_memhdr *hdr) { struct snd_emu10k1 *emu; emu = rec->hw; if (snd_BUG_ON(!sp || !hdr)) return -EINVAL; if (sp->block) { snd_emu10k1_synth_free(emu, sp->block); sp->block = NULL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela5170.83%250.00%
Takashi Iwai2129.17%250.00%
Total72100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Jaroslav Kysela72688.75%342.86%
Takashi Iwai9111.12%342.86%
Masanari Iida10.12%114.29%
Total818100.00%7100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.