root/sound/pci/emu10k1/emu10k1_patch.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_emu10k1_sample_new
  2. snd_emu10k1_sample_free

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Patch transfer callback for Emu10k1
   4  *
   5  *  Copyright (C) 2000 Takashi iwai <tiwai@suse.de>
   6  */
   7 /*
   8  * All the code for loading in a patch.  There is very little that is
   9  * chip specific here.  Just the actual writing to the board.
  10  */
  11 
  12 #include "emu10k1_synth_local.h"
  13 
  14 /*
  15  */
  16 #define BLANK_LOOP_START        4
  17 #define BLANK_LOOP_END          8
  18 #define BLANK_LOOP_SIZE         12
  19 #define BLANK_HEAD_SIZE         32
  20 
  21 /*
  22  * allocate a sample block and copy data from userspace
  23  */
  24 int
  25 snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
  26                        struct snd_util_memhdr *hdr,
  27                        const void __user *data, long count)
  28 {
  29         int offset;
  30         int truesize, size, loopsize, blocksize;
  31         int loopend, sampleend;
  32         unsigned int start_addr;
  33         struct snd_emu10k1 *emu;
  34 
  35         emu = rec->hw;
  36         if (snd_BUG_ON(!sp || !hdr))
  37                 return -EINVAL;
  38 
  39         if (sp->v.size == 0) {
  40                 dev_dbg(emu->card->dev,
  41                         "emu: rom font for sample %d\n", sp->v.sample);
  42                 return 0;
  43         }
  44 
  45         /* recalculate address offset */
  46         sp->v.end -= sp->v.start;
  47         sp->v.loopstart -= sp->v.start;
  48         sp->v.loopend -= sp->v.start;
  49         sp->v.start = 0;
  50 
  51         /* some samples have invalid data.  the addresses are corrected in voice info */
  52         sampleend = sp->v.end;
  53         if (sampleend > sp->v.size)
  54                 sampleend = sp->v.size;
  55         loopend = sp->v.loopend;
  56         if (loopend > sampleend)
  57                 loopend = sampleend;
  58 
  59         /* be sure loop points start < end */
  60         if (sp->v.loopstart >= sp->v.loopend)
  61                 swap(sp->v.loopstart, sp->v.loopend);
  62 
  63         /* compute true data size to be loaded */
  64         truesize = sp->v.size + BLANK_HEAD_SIZE;
  65         loopsize = 0;
  66 #if 0 /* not supported */
  67         if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
  68                 loopsize = sp->v.loopend - sp->v.loopstart;
  69         truesize += loopsize;
  70 #endif
  71         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
  72                 truesize += BLANK_LOOP_SIZE;
  73 
  74         /* try to allocate a memory block */
  75         blocksize = truesize;
  76         if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
  77                 blocksize *= 2;
  78         sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
  79         if (sp->block == NULL) {
  80                 dev_dbg(emu->card->dev,
  81                         "synth malloc failed (size=%d)\n", blocksize);
  82                 /* not ENOMEM (for compatibility with OSS) */
  83                 return -ENOSPC;
  84         }
  85         /* set the total size */
  86         sp->v.truesize = blocksize;
  87 
  88         /* write blank samples at head */
  89         offset = 0;
  90         size = BLANK_HEAD_SIZE;
  91         if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
  92                 size *= 2;
  93         if (offset + size > blocksize)
  94                 return -EINVAL;
  95         snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
  96         offset += size;
  97 
  98         /* copy start->loopend */
  99         size = loopend;
 100         if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
 101                 size *= 2;
 102         if (offset + size > blocksize)
 103                 return -EINVAL;
 104         if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
 105                 snd_emu10k1_synth_free(emu, sp->block);
 106                 sp->block = NULL;
 107                 return -EFAULT;
 108         }
 109         offset += size;
 110         data += size;
 111 
 112 #if 0 /* not supported yet */
 113         /* handle reverse (or bidirectional) loop */
 114         if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
 115                 /* copy loop in reverse */
 116                 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
 117                         int woffset;
 118                         unsigned short *wblock = (unsigned short*)block;
 119                         woffset = offset / 2;
 120                         if (offset + loopsize * 2 > blocksize)
 121                                 return -EINVAL;
 122                         for (i = 0; i < loopsize; i++)
 123                                 wblock[woffset + i] = wblock[woffset - i -1];
 124                         offset += loopsize * 2;
 125                 } else {
 126                         if (offset + loopsize > blocksize)
 127                                 return -EINVAL;
 128                         for (i = 0; i < loopsize; i++)
 129                                 block[offset + i] = block[offset - i -1];
 130                         offset += loopsize;
 131                 }
 132 
 133                 /* modify loop pointers */
 134                 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
 135                         sp->v.loopend += loopsize;
 136                 } else {
 137                         sp->v.loopstart += loopsize;
 138                         sp->v.loopend += loopsize;
 139                 }
 140                 /* add sample pointer */
 141                 sp->v.end += loopsize;
 142         }
 143 #endif
 144 
 145         /* loopend -> sample end */
 146         size = sp->v.size - loopend;
 147         if (size < 0)
 148                 return -EINVAL;
 149         if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
 150                 size *= 2;
 151         if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
 152                 snd_emu10k1_synth_free(emu, sp->block);
 153                 sp->block = NULL;
 154                 return -EFAULT;
 155         }
 156         offset += size;
 157 
 158         /* clear rest of samples (if any) */
 159         if (offset < blocksize)
 160                 snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
 161 
 162         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
 163                 /* if no blank loop is attached in the sample, add it */
 164                 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
 165                         sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
 166                         sp->v.loopend = sp->v.end + BLANK_LOOP_END;
 167                 }
 168         }
 169 
 170 #if 0 /* not supported yet */
 171         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
 172                 /* unsigned -> signed */
 173                 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
 174                         unsigned short *wblock = (unsigned short*)block;
 175                         for (i = 0; i < truesize; i++)
 176                                 wblock[i] ^= 0x8000;
 177                 } else {
 178                         for (i = 0; i < truesize; i++)
 179                                 block[i] ^= 0x80;
 180                 }
 181         }
 182 #endif
 183 
 184         /* recalculate offset */
 185         start_addr = BLANK_HEAD_SIZE * 2;
 186         if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
 187                 start_addr >>= 1;
 188         sp->v.start += start_addr;
 189         sp->v.end += start_addr;
 190         sp->v.loopstart += start_addr;
 191         sp->v.loopend += start_addr;
 192 
 193         return 0;
 194 }
 195 
 196 /*
 197  * free a sample block
 198  */
 199 int
 200 snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
 201                         struct snd_util_memhdr *hdr)
 202 {
 203         struct snd_emu10k1 *emu;
 204 
 205         emu = rec->hw;
 206         if (snd_BUG_ON(!sp || !hdr))
 207                 return -EINVAL;
 208 
 209         if (sp->block) {
 210                 snd_emu10k1_synth_free(emu, sp->block);
 211                 sp->block = NULL;
 212         }
 213         return 0;
 214 }
 215 

/* [<][>][^][v][top][bottom][index][help] */