~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/emu10k1/emu10k1_patch.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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         3
 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         u8 fill;
 30         u32 xor;
 31         int shift;
 32         int offset;
 33         int truesize, size, blocksize;
 34         int loop_start, loop_end, loop_size, data_end, unroll;
 35         struct snd_emu10k1 *emu;
 36 
 37         emu = rec->hw;
 38         if (snd_BUG_ON(!sp || !hdr))
 39                 return -EINVAL;
 40 
 41         if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP | SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
 42                 /* should instead return -ENOTSUPP; but compatibility */
 43                 printk(KERN_WARNING "Emu10k1 wavetable patch %d with unsupported loop feature\n",
 44                        sp->v.sample);
 45         }
 46 
 47         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
 48                 shift = 0;
 49                 fill = 0x80;
 50                 xor = (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) ? 0 : 0x80808080;
 51         } else {
 52                 shift = 1;
 53                 fill = 0;
 54                 xor = (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) ? 0x80008000 : 0;
 55         }
 56 
 57         /* compute true data size to be loaded */
 58         truesize = sp->v.size + BLANK_HEAD_SIZE;
 59         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
 60                 truesize += BLANK_LOOP_SIZE;
 61                 /* if no blank loop is attached in the sample, add it */
 62                 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
 63                         sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
 64                         sp->v.loopend = sp->v.end + BLANK_LOOP_END;
 65                 }
 66         }
 67 
 68         loop_start = sp->v.loopstart;
 69         loop_end = sp->v.loopend;
 70         loop_size = loop_end - loop_start;
 71         if (!loop_size)
 72                 return -EINVAL;
 73         data_end = sp->v.end;
 74 
 75         /* recalculate offset */
 76         sp->v.start += BLANK_HEAD_SIZE;
 77         sp->v.end += BLANK_HEAD_SIZE;
 78         sp->v.loopstart += BLANK_HEAD_SIZE;
 79         sp->v.loopend += BLANK_HEAD_SIZE;
 80 
 81         // Automatic pre-filling of the cache does not work in the presence
 82         // of loops (*), and we don't want to fill it manually, as that is
 83         // fiddly and slow. So we unroll the loop until the loop end is
 84         // beyond the cache size.
 85         // (*) Strictly speaking, a single iteration is supported (that's
 86         // how it works when the playback engine runs), but handling this
 87         // special case is not worth it.
 88         unroll = 0;
 89         while (sp->v.loopend < 64) {
 90                 truesize += loop_size;
 91                 sp->v.loopstart += loop_size;
 92                 sp->v.loopend += loop_size;
 93                 sp->v.end += loop_size;
 94                 unroll++;
 95         }
 96 
 97         /* try to allocate a memory block */
 98         blocksize = truesize << shift;
 99         sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
100         if (sp->block == NULL) {
101                 dev_dbg(emu->card->dev,
102                         "synth malloc failed (size=%d)\n", blocksize);
103                 /* not ENOMEM (for compatibility with OSS) */
104                 return -ENOSPC;
105         }
106         /* set the total size */
107         sp->v.truesize = blocksize;
108 
109         /* write blank samples at head */
110         offset = 0;
111         size = BLANK_HEAD_SIZE << shift;
112         snd_emu10k1_synth_memset(emu, sp->block, offset, size, fill);
113         offset += size;
114 
115         /* copy provided samples */
116         if (unroll && loop_end <= data_end) {
117                 size = loop_end << shift;
118                 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size, xor))
119                         goto faulty;
120                 offset += size;
121 
122                 data += loop_start << shift;
123                 while (--unroll > 0) {
124                         size = loop_size << shift;
125                         if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size, xor))
126                                 goto faulty;
127                         offset += size;
128                 }
129 
130                 size = (data_end - loop_start) << shift;
131         } else {
132                 size = data_end << shift;
133         }
134         if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size, xor))
135                 goto faulty;
136         offset += size;
137 
138         /* clear rest of samples (if any) */
139         if (offset < blocksize)
140                 snd_emu10k1_synth_memset(emu, sp->block, offset, blocksize - offset, fill);
141 
142         return 0;
143 
144 faulty:
145         snd_emu10k1_synth_free(emu, sp->block);
146         sp->block = NULL;
147         return -EFAULT;
148 }
149 
150 /*
151  * free a sample block
152  */
153 int
154 snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
155                         struct snd_util_memhdr *hdr)
156 {
157         struct snd_emu10k1 *emu;
158 
159         emu = rec->hw;
160         if (snd_BUG_ON(!sp || !hdr))
161                 return -EINVAL;
162 
163         if (sp->block) {
164                 snd_emu10k1_synth_free(emu, sp->block);
165                 sp->block = NULL;
166         }
167         return 0;
168 }
169 
170 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php