0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "emu8000_local.h"
0010
0011 #include <linux/sched/signal.h>
0012 #include <linux/uaccess.h>
0013 #include <linux/moduleparam.h>
0014
0015 static int emu8000_reset_addr;
0016 module_param(emu8000_reset_addr, int, 0444);
0017 MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)");
0018
0019
0020
0021
0022
0023 static int
0024 snd_emu8000_open_dma(struct snd_emu8000 *emu, int write)
0025 {
0026 int i;
0027
0028
0029 for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
0030 snd_emux_lock_voice(emu->emu, i);
0031 snd_emu8000_dma_chan(emu, i, write);
0032 }
0033
0034
0035 EMU8000_VTFT_WRITE(emu, 30, 0);
0036 EMU8000_PSST_WRITE(emu, 30, 0x1d8);
0037 EMU8000_CSL_WRITE(emu, 30, 0x1e0);
0038 EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
0039 EMU8000_VTFT_WRITE(emu, 31, 0);
0040 EMU8000_PSST_WRITE(emu, 31, 0x1d8);
0041 EMU8000_CSL_WRITE(emu, 31, 0x1e0);
0042 EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
0043
0044 return 0;
0045 }
0046
0047
0048
0049
0050 static void
0051 snd_emu8000_close_dma(struct snd_emu8000 *emu)
0052 {
0053 int i;
0054
0055 for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
0056 snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
0057 snd_emux_unlock_voice(emu->emu, i);
0058 }
0059 }
0060
0061
0062
0063
0064 #define BLANK_LOOP_START 4
0065 #define BLANK_LOOP_END 8
0066 #define BLANK_LOOP_SIZE 12
0067 #define BLANK_HEAD_SIZE 48
0068
0069
0070
0071
0072
0073 static unsigned short
0074 read_word(const void __user *buf, int offset, int mode)
0075 {
0076 unsigned short c;
0077 if (mode & SNDRV_SFNT_SAMPLE_8BITS) {
0078 unsigned char cc;
0079 get_user(cc, (unsigned char __user *)buf + offset);
0080 c = cc << 8;
0081 } else {
0082 #ifdef SNDRV_LITTLE_ENDIAN
0083 get_user(c, (unsigned short __user *)buf + offset);
0084 #else
0085 unsigned short cc;
0086 get_user(cc, (unsigned short __user *)buf + offset);
0087 c = swab16(cc);
0088 #endif
0089 }
0090 if (mode & SNDRV_SFNT_SAMPLE_UNSIGNED)
0091 c ^= 0x8000;
0092 return c;
0093 }
0094
0095
0096
0097 static void
0098 snd_emu8000_write_wait(struct snd_emu8000 *emu)
0099 {
0100 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
0101 schedule_timeout_interruptible(1);
0102 if (signal_pending(current))
0103 break;
0104 }
0105 }
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119 static inline void
0120 write_word(struct snd_emu8000 *emu, int *offset, unsigned short data)
0121 {
0122 if (emu8000_reset_addr) {
0123 if (emu8000_reset_addr > 1)
0124 snd_emu8000_write_wait(emu);
0125 EMU8000_SMALW_WRITE(emu, *offset);
0126 }
0127 EMU8000_SMLD_WRITE(emu, data);
0128 *offset += 1;
0129 }
0130
0131
0132
0133
0134
0135 int
0136 snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
0137 struct snd_util_memhdr *hdr,
0138 const void __user *data, long count)
0139 {
0140 int i;
0141 int rc;
0142 int offset;
0143 int truesize;
0144 int dram_offset, dram_start;
0145 struct snd_emu8000 *emu;
0146
0147 emu = rec->hw;
0148 if (snd_BUG_ON(!sp))
0149 return -EINVAL;
0150
0151 if (sp->v.size == 0)
0152 return 0;
0153
0154
0155 if (sp->v.loopstart > sp->v.loopend)
0156 swap(sp->v.loopstart, sp->v.loopend);
0157
0158
0159 truesize = sp->v.size;
0160 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
0161 truesize += sp->v.loopend - sp->v.loopstart;
0162 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
0163 truesize += BLANK_LOOP_SIZE;
0164
0165 sp->block = snd_util_mem_alloc(hdr, truesize * 2);
0166 if (sp->block == NULL) {
0167
0168
0169 return -ENOSPC;
0170 }
0171
0172 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
0173 if (!access_ok(data, sp->v.size))
0174 return -EFAULT;
0175 } else {
0176 if (!access_ok(data, sp->v.size * 2))
0177 return -EFAULT;
0178 }
0179
0180
0181 sp->v.end -= sp->v.start;
0182 sp->v.loopstart -= sp->v.start;
0183 sp->v.loopend -= sp->v.start;
0184 sp->v.start = 0;
0185
0186
0187 dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1);
0188 dram_start = dram_offset;
0189
0190
0191 sp->v.truesize = truesize * 2;
0192
0193 snd_emux_terminate_all(emu->emu);
0194 rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE);
0195 if (rc)
0196 return rc;
0197
0198
0199 snd_emu8000_write_wait(emu);
0200 EMU8000_SMALW_WRITE(emu, dram_offset);
0201
0202
0203
0204 #if 0
0205
0206 if (! sp->block->offset) {
0207 for (i = 0; i < BLANK_HEAD_SIZE; i++) {
0208 write_word(emu, &dram_offset, 0);
0209 }
0210 }
0211 #endif
0212
0213 offset = 0;
0214 for (i = 0; i < sp->v.size; i++) {
0215 unsigned short s;
0216
0217 s = read_word(data, offset, sp->v.mode_flags);
0218 offset++;
0219 write_word(emu, &dram_offset, s);
0220
0221
0222
0223
0224 cond_resched();
0225
0226 if (i == sp->v.loopend &&
0227 (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)))
0228 {
0229 int looplen = sp->v.loopend - sp->v.loopstart;
0230 int k;
0231
0232
0233 for (k = 1; k <= looplen; k++) {
0234 s = read_word(data, offset - k, sp->v.mode_flags);
0235 write_word(emu, &dram_offset, s);
0236 }
0237 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
0238 sp->v.loopend += looplen;
0239 } else {
0240 sp->v.loopstart += looplen;
0241 sp->v.loopend += looplen;
0242 }
0243 sp->v.end += looplen;
0244 }
0245 }
0246
0247
0248 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
0249 for (i = 0; i < BLANK_LOOP_SIZE; i++) {
0250 write_word(emu, &dram_offset, 0);
0251 }
0252 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
0253 sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
0254 sp->v.loopend = sp->v.end + BLANK_LOOP_END;
0255 }
0256 }
0257
0258
0259 sp->v.start += dram_start;
0260 sp->v.end += dram_start;
0261 sp->v.loopstart += dram_start;
0262 sp->v.loopend += dram_start;
0263
0264 snd_emu8000_close_dma(emu);
0265 snd_emu8000_init_fm(emu);
0266
0267 return 0;
0268 }
0269
0270
0271
0272
0273 int
0274 snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
0275 struct snd_util_memhdr *hdr)
0276 {
0277 if (sp->block) {
0278 snd_util_mem_free(hdr, sp->block);
0279 sp->block = NULL;
0280 }
0281 return 0;
0282 }
0283
0284
0285
0286
0287
0288 void
0289 snd_emu8000_sample_reset(struct snd_emux *rec)
0290 {
0291 snd_emux_terminate_all(rec);
0292 }