Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * pcm emulation on emu8000 wavetable
  4 *
  5 *  Copyright (C) 2002 Takashi Iwai <tiwai@suse.de>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  6 */
  7
  8#include "emu8000_local.h"
  9
 10#include <linux/sched/signal.h>
 11#include <linux/init.h>
 12#include <linux/slab.h>
 13#include <sound/initval.h>
 14#include <sound/pcm.h>
 15
 16/*
 17 * define the following if you want to use this pcm with non-interleaved mode
 18 */
 19/* #define USE_NONINTERLEAVE */
 20
 21/* NOTE: for using the non-interleaved mode with alsa-lib, you have to set
 22 * mmap_emulation flag to 1 in your .asoundrc, such like
 23 *
 24 *	pcm.emu8k {
 25 *		type plug
 26 *		slave.pcm {
 27 *			type hw
 28 *			card 0
 29 *			device 1
 30 *			mmap_emulation 1
 31 *		}
 32 *	}
 33 *
 34 * besides, for the time being, the non-interleaved mode doesn't work well on
 35 * alsa-lib...
 36 */
 37
 38
 39struct snd_emu8k_pcm {
 40	struct snd_emu8000 *emu;
 41	struct snd_pcm_substream *substream;
 42
 43	unsigned int allocated_bytes;
 44	struct snd_util_memblk *block;
 45	unsigned int offset;
 46	unsigned int buf_size;
 47	unsigned int period_size;
 48	unsigned int loop_start[2];
 49	unsigned int pitch;
 50	int panning[2];
 51	int last_ptr;
 52	int period_pos;
 53	int voices;
 54	unsigned int dram_opened: 1;
 55	unsigned int running: 1;
 56	unsigned int timer_running: 1;
 57	struct timer_list timer;
 58	spinlock_t timer_lock;
 59};
 60
 61#define LOOP_BLANK_SIZE		8
 62
 63
 64/*
 65 * open up channels for the simultaneous data transfer and playback
 66 */
 67static int
 68emu8k_open_dram_for_pcm(struct snd_emu8000 *emu, int channels)
 69{
 70	int i;
 71
 72	/* reserve up to 2 voices for playback */
 73	snd_emux_lock_voice(emu->emu, 0);
 74	if (channels > 1)
 75		snd_emux_lock_voice(emu->emu, 1);
 76
 77	/* reserve 28 voices for loading */
 78	for (i = channels + 1; i < EMU8000_DRAM_VOICES; i++) {
 79		unsigned int mode = EMU8000_RAM_WRITE;
 80		snd_emux_lock_voice(emu->emu, i);
 81#ifndef USE_NONINTERLEAVE
 82		if (channels > 1 && (i & 1) != 0)
 83			mode |= EMU8000_RAM_RIGHT;
 84#endif
 85		snd_emu8000_dma_chan(emu, i, mode);
 86	}
 87
 88	/* assign voice 31 and 32 to ROM */
 89	EMU8000_VTFT_WRITE(emu, 30, 0);
 90	EMU8000_PSST_WRITE(emu, 30, 0x1d8);
 91	EMU8000_CSL_WRITE(emu, 30, 0x1e0);
 92	EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
 93	EMU8000_VTFT_WRITE(emu, 31, 0);
 94	EMU8000_PSST_WRITE(emu, 31, 0x1d8);
 95	EMU8000_CSL_WRITE(emu, 31, 0x1e0);
 96	EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
 97
 98	return 0;
 99}
100
101/*
102 */
103static void
104snd_emu8000_write_wait(struct snd_emu8000 *emu, int can_schedule)
105{
106	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
107		if (can_schedule) {
108			schedule_timeout_interruptible(1);
109			if (signal_pending(current))
110				break;
111		}
112	}
113}
114
115/*
116 * close all channels
117 */
118static void
119emu8k_close_dram(struct snd_emu8000 *emu)
120{
121	int i;
122
123	for (i = 0; i < 2; i++)
124		snd_emux_unlock_voice(emu->emu, i);
125	for (; i < EMU8000_DRAM_VOICES; i++) {
126		snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
127		snd_emux_unlock_voice(emu->emu, i);
128	}
129}
130
131/*
132 * convert Hz to AWE32 rate offset (see emux/soundfont.c)
133 */
134
135#define OFFSET_SAMPLERATE	1011119		/* base = 44100 */
136#define SAMPLERATE_RATIO	4096
137
138static int calc_rate_offset(int hz)
139{
140	return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
141}
142
143
144/*
145 */
146
147static const struct snd_pcm_hardware emu8k_pcm_hw = {
148#ifdef USE_NONINTERLEAVE
149	.info =			SNDRV_PCM_INFO_NONINTERLEAVED,
150#else
151	.info =			SNDRV_PCM_INFO_INTERLEAVED,
152#endif
153	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
154	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
155	.rate_min =		4000,
156	.rate_max =		48000,
157	.channels_min =		1,
158	.channels_max =		2,
159	.buffer_bytes_max =	(128*1024),
160	.period_bytes_min =	1024,
161	.period_bytes_max =	(128*1024),
162	.periods_min =		2,
163	.periods_max =		1024,
164	.fifo_size =		0,
165
166};
167
168/*
169 * get the current position at the given channel from CCCA register
170 */
171static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch)
172{
173	int val = EMU8000_CCCA_READ(rec->emu, ch) & 0xfffffff;
174	val -= rec->loop_start[ch] - 1;
175	return val;
176}
177
178
179/*
180 * timer interrupt handler
181 * check the current position and update the period if necessary.
182 */
183static void emu8k_pcm_timer_func(struct timer_list *t)
184{
185	struct snd_emu8k_pcm *rec = from_timer(rec, t, timer);
186	int ptr, delta;
187
188	spin_lock(&rec->timer_lock);
189	/* update the current pointer */
190	ptr = emu8k_get_curpos(rec, 0);
191	if (ptr < rec->last_ptr)
192		delta = ptr + rec->buf_size - rec->last_ptr;
193	else
194		delta = ptr - rec->last_ptr;
195	rec->period_pos += delta;
196	rec->last_ptr = ptr;
197
198	/* reprogram timer */
199	mod_timer(&rec->timer, jiffies + 1);
200
201	/* update period */
202	if (rec->period_pos >= (int)rec->period_size) {
203		rec->period_pos %= rec->period_size;
204		spin_unlock(&rec->timer_lock);
205		snd_pcm_period_elapsed(rec->substream);
206		return;
207	}
208	spin_unlock(&rec->timer_lock);
209}
210
211
212/*
213 * open pcm
214 * creating an instance here
215 */
216static int emu8k_pcm_open(struct snd_pcm_substream *subs)
217{
218	struct snd_emu8000 *emu = snd_pcm_substream_chip(subs);
219	struct snd_emu8k_pcm *rec;
220	struct snd_pcm_runtime *runtime = subs->runtime;
221
222	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
223	if (! rec)
224		return -ENOMEM;
225
226	rec->emu = emu;
227	rec->substream = subs;
228	runtime->private_data = rec;
229
230	spin_lock_init(&rec->timer_lock);
231	timer_setup(&rec->timer, emu8k_pcm_timer_func, 0);
232
233	runtime->hw = emu8k_pcm_hw;
234	runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3;
235	runtime->hw.period_bytes_max = runtime->hw.buffer_bytes_max / 2;
236
237	/* use timer to update periods.. (specified in msec) */
238	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
239				     (1000000 + HZ - 1) / HZ, UINT_MAX);
240
241	return 0;
242}
243
244static int emu8k_pcm_close(struct snd_pcm_substream *subs)
245{
246	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
247	kfree(rec);
248	subs->runtime->private_data = NULL;
249	return 0;
250}
251
252/*
253 * calculate pitch target
254 */
255static int calc_pitch_target(int pitch)
256{
257	int ptarget = 1 << (pitch >> 12);
258	if (pitch & 0x800) ptarget += (ptarget * 0x102e) / 0x2710;
259	if (pitch & 0x400) ptarget += (ptarget * 0x764) / 0x2710;
260	if (pitch & 0x200) ptarget += (ptarget * 0x389) / 0x2710;
261	ptarget += (ptarget >> 1);
262	if (ptarget > 0xffff) ptarget = 0xffff;
263	return ptarget;
264}
265
266/*
267 * set up the voice
268 */
269static void setup_voice(struct snd_emu8k_pcm *rec, int ch)
270{
271	struct snd_emu8000 *hw = rec->emu;
272	unsigned int temp;
273
274	/* channel to be silent and idle */
275	EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
276	EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
277	EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
278	EMU8000_PTRX_WRITE(hw, ch, 0);
279	EMU8000_CPF_WRITE(hw, ch, 0);
280
281	/* pitch offset */
282	EMU8000_IP_WRITE(hw, ch, rec->pitch);
283	/* set envelope parameters */
284	EMU8000_ENVVAL_WRITE(hw, ch, 0x8000);
285	EMU8000_ATKHLD_WRITE(hw, ch, 0x7f7f);
286	EMU8000_DCYSUS_WRITE(hw, ch, 0x7f7f);
287	EMU8000_ENVVOL_WRITE(hw, ch, 0x8000);
288	EMU8000_ATKHLDV_WRITE(hw, ch, 0x7f7f);
289	/* decay/sustain parameter for volume envelope is used
290	   for triggerg the voice */
291	/* modulation envelope heights */
292	EMU8000_PEFE_WRITE(hw, ch, 0x0);
293	/* lfo1/2 delay */
294	EMU8000_LFO1VAL_WRITE(hw, ch, 0x8000);
295	EMU8000_LFO2VAL_WRITE(hw, ch, 0x8000);
296	/* lfo1 pitch & cutoff shift */
297	EMU8000_FMMOD_WRITE(hw, ch, 0);
298	/* lfo1 volume & freq */
299	EMU8000_TREMFRQ_WRITE(hw, ch, 0);
300	/* lfo2 pitch & freq */
301	EMU8000_FM2FRQ2_WRITE(hw, ch, 0);
302	/* pan & loop start */
303	temp = rec->panning[ch];
304	temp = (temp <<24) | ((unsigned int)rec->loop_start[ch] - 1);
305	EMU8000_PSST_WRITE(hw, ch, temp);
306	/* chorus & loop end (chorus 8bit, MSB) */
307	temp = 0; // chorus
308	temp = (temp << 24) | ((unsigned int)rec->loop_start[ch] + rec->buf_size - 1);
309	EMU8000_CSL_WRITE(hw, ch, temp);
310	/* Q & current address (Q 4bit value, MSB) */
311	temp = 0; // filterQ
312	temp = (temp << 28) | ((unsigned int)rec->loop_start[ch] - 1);
313	EMU8000_CCCA_WRITE(hw, ch, temp);
314	/* clear unknown registers */
315	EMU8000_00A0_WRITE(hw, ch, 0);
316	EMU8000_0080_WRITE(hw, ch, 0);
317}
318
319/*
320 * trigger the voice
321 */
322static void start_voice(struct snd_emu8k_pcm *rec, int ch)
323{
324	unsigned long flags;
325	struct snd_emu8000 *hw = rec->emu;
326	unsigned int temp, aux;
327	int pt = calc_pitch_target(rec->pitch);
328
329	/* cutoff and volume */
330	EMU8000_IFATN_WRITE(hw, ch, 0xff00);
331	EMU8000_VTFT_WRITE(hw, ch, 0xffff);
332	EMU8000_CVCF_WRITE(hw, ch, 0xffff);
333	/* trigger envelope */
334	EMU8000_DCYSUSV_WRITE(hw, ch, 0x7f7f);
335	/* set reverb and pitch target */
336	temp = 0; // reverb
337	if (rec->panning[ch] == 0)
338		aux = 0xff;
339	else
340		aux = (-rec->panning[ch]) & 0xff;
341	temp = (temp << 8) | (pt << 16) | aux;
342	EMU8000_PTRX_WRITE(hw, ch, temp);
343	EMU8000_CPF_WRITE(hw, ch, pt << 16);
344
345	/* start timer */
346	spin_lock_irqsave(&rec->timer_lock, flags);
347	if (! rec->timer_running) {
348		mod_timer(&rec->timer, jiffies + 1);
349		rec->timer_running = 1;
350	}
351	spin_unlock_irqrestore(&rec->timer_lock, flags);
352}
353
354/*
355 * stop the voice immediately
356 */
357static void stop_voice(struct snd_emu8k_pcm *rec, int ch)
358{
359	unsigned long flags;
360	struct snd_emu8000 *hw = rec->emu;
361
362	EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
363
364	/* stop timer */
365	spin_lock_irqsave(&rec->timer_lock, flags);
366	if (rec->timer_running) {
367		del_timer(&rec->timer);
368		rec->timer_running = 0;
369	}
370	spin_unlock_irqrestore(&rec->timer_lock, flags);
371}
372
373static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
374{
375	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
376	int ch;
377
378	switch (cmd) {
379	case SNDRV_PCM_TRIGGER_START:
380		for (ch = 0; ch < rec->voices; ch++)
381			start_voice(rec, ch);
382		rec->running = 1;
383		break;
384	case SNDRV_PCM_TRIGGER_STOP:
385		rec->running = 0;
386		for (ch = 0; ch < rec->voices; ch++)
387			stop_voice(rec, ch);
388		break;
389	default:
390		return -EINVAL;
391	}
392	return 0;
393}
394
395
396/*
397 * copy / silence ops
398 */
399
400/*
401 * this macro should be inserted in the copy/silence loops
402 * to reduce the latency.  without this, the system will hang up
403 * during the whole loop.
404 */
405#define CHECK_SCHEDULER() \
406do { \
407	cond_resched();\
408	if (signal_pending(current))\
409		return -EAGAIN;\
410} while (0)
411
412enum {
413	COPY_USER, COPY_KERNEL, FILL_SILENCE,
414};
415
416#define GET_VAL(sval, buf, mode)					\
417	do {								\
418		switch (mode) {						\
419		case FILL_SILENCE:					\
420			sval = 0;					\
421			break;						\
422		case COPY_KERNEL:					\
423			sval = *buf++;					\
424			break;						\
425		default:						\
426			if (get_user(sval, (unsigned short __user *)buf)) \
427				return -EFAULT;				\
428			buf++;						\
429			break;						\
430		}							\
431	} while (0)
432
433#ifdef USE_NONINTERLEAVE
434
435#define LOOP_WRITE(rec, offset, _buf, count, mode)		\
436	do {							\
437		struct snd_emu8000 *emu = (rec)->emu;		\
438		unsigned short *buf = (__force unsigned short *)(_buf); \
439		snd_emu8000_write_wait(emu, 1);			\
440		EMU8000_SMALW_WRITE(emu, offset);		\
441		while (count > 0) {				\
442			unsigned short sval;			\
443			CHECK_SCHEDULER();			\
444			GET_VAL(sval, buf, mode);		\
445			EMU8000_SMLD_WRITE(emu, sval);		\
446			count--;				\
447		}						\
448	} while (0)
449
450/* copy one channel block */
451static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
452			  int voice, unsigned long pos,
453			  void __user *src, unsigned long count)
454{
455	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
456
457	/* convert to word unit */
458	pos = (pos << 1) + rec->loop_start[voice];
459	count <<= 1;
460	LOOP_WRITE(rec, pos, src, count, COPY_USER);
461	return 0;
462}
463
464static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
465				 int voice, unsigned long pos,
466				 void *src, unsigned long count)
467{
468	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
469
470	/* convert to word unit */
471	pos = (pos << 1) + rec->loop_start[voice];
472	count <<= 1;
473	LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
474	return 0;
475}
476
477/* make a channel block silence */
478static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
479			     int voice, unsigned long pos, unsigned long count)
480{
481	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
482
483	/* convert to word unit */
484	pos = (pos << 1) + rec->loop_start[voice];
485	count <<= 1;
486	LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
487	return 0;
488}
489
490#else /* interleave */
491
492#define LOOP_WRITE(rec, pos, _buf, count, mode)				\
493	do {								\
494		struct snd_emu8000 *emu = rec->emu;			\
495		unsigned short *buf = (__force unsigned short *)(_buf);	\
496		snd_emu8000_write_wait(emu, 1);				\
497		EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]);	\
498		if (rec->voices > 1)					\
499			EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); \
500		while (count > 0) {					\
501			unsigned short sval;				\
502			CHECK_SCHEDULER();				\
503			GET_VAL(sval, buf, mode);			\
504			EMU8000_SMLD_WRITE(emu, sval);			\
505			if (rec->voices > 1) {				\
506				CHECK_SCHEDULER();			\
507				GET_VAL(sval, buf, mode);		\
508				EMU8000_SMRD_WRITE(emu, sval);		\
509			}						\
510			count--;					\
511		}							\
512	} while (0)
513
514
515/*
516 * copy the interleaved data can be done easily by using
517 * DMA "left" and "right" channels on emu8k engine.
518 */
519static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
520			  int voice, unsigned long pos,
521			  void __user *src, unsigned long count)
522{
523	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
524
525	/* convert to frames */
526	pos = bytes_to_frames(subs->runtime, pos);
527	count = bytes_to_frames(subs->runtime, count);
528	LOOP_WRITE(rec, pos, src, count, COPY_USER);
529	return 0;
530}
531
532static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
533				 int voice, unsigned long pos,
534				 void *src, unsigned long count)
535{
536	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
537
538	/* convert to frames */
539	pos = bytes_to_frames(subs->runtime, pos);
540	count = bytes_to_frames(subs->runtime, count);
541	LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
542	return 0;
543}
544
545static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
546			     int voice, unsigned long pos, unsigned long count)
547{
548	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
549
550	/* convert to frames */
551	pos = bytes_to_frames(subs->runtime, pos);
552	count = bytes_to_frames(subs->runtime, count);
553	LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
554	return 0;
555}
556#endif
557
558
559/*
560 * allocate a memory block
561 */
562static int emu8k_pcm_hw_params(struct snd_pcm_substream *subs,
563			       struct snd_pcm_hw_params *hw_params)
564{
565	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
566
567	if (rec->block) {
568		/* reallocation - release the old block */
569		snd_util_mem_free(rec->emu->memhdr, rec->block);
570		rec->block = NULL;
571	}
572
573	rec->allocated_bytes = params_buffer_bytes(hw_params) + LOOP_BLANK_SIZE * 4;
574	rec->block = snd_util_mem_alloc(rec->emu->memhdr, rec->allocated_bytes);
575	if (! rec->block)
576		return -ENOMEM;
577	rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */
578	/* at least dma_bytes must be set for non-interleaved mode */
579	subs->dma_buffer.bytes = params_buffer_bytes(hw_params);
580
581	return 0;
582}
583
584/*
585 * free the memory block
586 */
587static int emu8k_pcm_hw_free(struct snd_pcm_substream *subs)
588{
589	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
590
591	if (rec->block) {
592		int ch;
593		for (ch = 0; ch < rec->voices; ch++)
594			stop_voice(rec, ch); // to be sure
595		if (rec->dram_opened)
596			emu8k_close_dram(rec->emu);
597		snd_util_mem_free(rec->emu->memhdr, rec->block);
598		rec->block = NULL;
599	}
600	return 0;
601}
602
603/*
604 */
605static int emu8k_pcm_prepare(struct snd_pcm_substream *subs)
606{
607	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
608
609	rec->pitch = 0xe000 + calc_rate_offset(subs->runtime->rate);
610	rec->last_ptr = 0;
611	rec->period_pos = 0;
612
613	rec->buf_size = subs->runtime->buffer_size;
614	rec->period_size = subs->runtime->period_size;
615	rec->voices = subs->runtime->channels;
616	rec->loop_start[0] = rec->offset + LOOP_BLANK_SIZE;
617	if (rec->voices > 1)
618		rec->loop_start[1] = rec->loop_start[0] + rec->buf_size + LOOP_BLANK_SIZE;
619	if (rec->voices > 1) {
620		rec->panning[0] = 0xff;
621		rec->panning[1] = 0x00;
622	} else
623		rec->panning[0] = 0x80;
624
625	if (! rec->dram_opened) {
626		int err, i, ch;
627
628		snd_emux_terminate_all(rec->emu->emu);
629		if ((err = emu8k_open_dram_for_pcm(rec->emu, rec->voices)) != 0)
630			return err;
631		rec->dram_opened = 1;
632
633		/* clear loop blanks */
634		snd_emu8000_write_wait(rec->emu, 0);
635		EMU8000_SMALW_WRITE(rec->emu, rec->offset);
636		for (i = 0; i < LOOP_BLANK_SIZE; i++)
637			EMU8000_SMLD_WRITE(rec->emu, 0);
638		for (ch = 0; ch < rec->voices; ch++) {
639			EMU8000_SMALW_WRITE(rec->emu, rec->loop_start[ch] + rec->buf_size);
640			for (i = 0; i < LOOP_BLANK_SIZE; i++)
641				EMU8000_SMLD_WRITE(rec->emu, 0);
642		}
643	}
644
645	setup_voice(rec, 0);
646	if (rec->voices > 1)
647		setup_voice(rec, 1);
648	return 0;
649}
650
651static snd_pcm_uframes_t emu8k_pcm_pointer(struct snd_pcm_substream *subs)
652{
653	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
654	if (rec->running)
655		return emu8k_get_curpos(rec, 0);
656	return 0;
657}
658
659
660static const struct snd_pcm_ops emu8k_pcm_ops = {
661	.open =		emu8k_pcm_open,
662	.close =	emu8k_pcm_close,
 
663	.hw_params =	emu8k_pcm_hw_params,
664	.hw_free =	emu8k_pcm_hw_free,
665	.prepare =	emu8k_pcm_prepare,
666	.trigger =	emu8k_pcm_trigger,
667	.pointer =	emu8k_pcm_pointer,
668	.copy_user =	emu8k_pcm_copy,
669	.copy_kernel =	emu8k_pcm_copy_kernel,
670	.fill_silence =	emu8k_pcm_silence,
671};
672
673
674static void snd_emu8000_pcm_free(struct snd_pcm *pcm)
675{
676	struct snd_emu8000 *emu = pcm->private_data;
677	emu->pcm = NULL;
678}
679
680int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index)
681{
682	struct snd_pcm *pcm;
683	int err;
684
685	if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0)
686		return err;
687	pcm->private_data = emu;
688	pcm->private_free = snd_emu8000_pcm_free;
689	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &emu8k_pcm_ops);
690	emu->pcm = pcm;
691
692	snd_device_register(card, pcm);
693
694	return 0;
695}
v4.17
 
  1/*
  2 * pcm emulation on emu8000 wavetable
  3 *
  4 *  Copyright (C) 2002 Takashi Iwai <tiwai@suse.de>
  5 *
  6 *   This program is free software; you can redistribute it and/or modify
  7 *   it under the terms of the GNU General Public License as published by
  8 *   the Free Software Foundation; either version 2 of the License, or
  9 *   (at your option) any later version.
 10 *
 11 *   This program is distributed in the hope that it will be useful,
 12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 *   GNU General Public License for more details.
 15 *
 16 *   You should have received a copy of the GNU General Public License
 17 *   along with this program; if not, write to the Free Software
 18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 19 */
 20
 21#include "emu8000_local.h"
 22
 23#include <linux/sched/signal.h>
 24#include <linux/init.h>
 25#include <linux/slab.h>
 26#include <sound/initval.h>
 27#include <sound/pcm.h>
 28
 29/*
 30 * define the following if you want to use this pcm with non-interleaved mode
 31 */
 32/* #define USE_NONINTERLEAVE */
 33
 34/* NOTE: for using the non-interleaved mode with alsa-lib, you have to set
 35 * mmap_emulation flag to 1 in your .asoundrc, such like
 36 *
 37 *	pcm.emu8k {
 38 *		type plug
 39 *		slave.pcm {
 40 *			type hw
 41 *			card 0
 42 *			device 1
 43 *			mmap_emulation 1
 44 *		}
 45 *	}
 46 *
 47 * besides, for the time being, the non-interleaved mode doesn't work well on
 48 * alsa-lib...
 49 */
 50
 51
 52struct snd_emu8k_pcm {
 53	struct snd_emu8000 *emu;
 54	struct snd_pcm_substream *substream;
 55
 56	unsigned int allocated_bytes;
 57	struct snd_util_memblk *block;
 58	unsigned int offset;
 59	unsigned int buf_size;
 60	unsigned int period_size;
 61	unsigned int loop_start[2];
 62	unsigned int pitch;
 63	int panning[2];
 64	int last_ptr;
 65	int period_pos;
 66	int voices;
 67	unsigned int dram_opened: 1;
 68	unsigned int running: 1;
 69	unsigned int timer_running: 1;
 70	struct timer_list timer;
 71	spinlock_t timer_lock;
 72};
 73
 74#define LOOP_BLANK_SIZE		8
 75
 76
 77/*
 78 * open up channels for the simultaneous data transfer and playback
 79 */
 80static int
 81emu8k_open_dram_for_pcm(struct snd_emu8000 *emu, int channels)
 82{
 83	int i;
 84
 85	/* reserve up to 2 voices for playback */
 86	snd_emux_lock_voice(emu->emu, 0);
 87	if (channels > 1)
 88		snd_emux_lock_voice(emu->emu, 1);
 89
 90	/* reserve 28 voices for loading */
 91	for (i = channels + 1; i < EMU8000_DRAM_VOICES; i++) {
 92		unsigned int mode = EMU8000_RAM_WRITE;
 93		snd_emux_lock_voice(emu->emu, i);
 94#ifndef USE_NONINTERLEAVE
 95		if (channels > 1 && (i & 1) != 0)
 96			mode |= EMU8000_RAM_RIGHT;
 97#endif
 98		snd_emu8000_dma_chan(emu, i, mode);
 99	}
100
101	/* assign voice 31 and 32 to ROM */
102	EMU8000_VTFT_WRITE(emu, 30, 0);
103	EMU8000_PSST_WRITE(emu, 30, 0x1d8);
104	EMU8000_CSL_WRITE(emu, 30, 0x1e0);
105	EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
106	EMU8000_VTFT_WRITE(emu, 31, 0);
107	EMU8000_PSST_WRITE(emu, 31, 0x1d8);
108	EMU8000_CSL_WRITE(emu, 31, 0x1e0);
109	EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
110
111	return 0;
112}
113
114/*
115 */
116static void
117snd_emu8000_write_wait(struct snd_emu8000 *emu, int can_schedule)
118{
119	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
120		if (can_schedule) {
121			schedule_timeout_interruptible(1);
122			if (signal_pending(current))
123				break;
124		}
125	}
126}
127
128/*
129 * close all channels
130 */
131static void
132emu8k_close_dram(struct snd_emu8000 *emu)
133{
134	int i;
135
136	for (i = 0; i < 2; i++)
137		snd_emux_unlock_voice(emu->emu, i);
138	for (; i < EMU8000_DRAM_VOICES; i++) {
139		snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
140		snd_emux_unlock_voice(emu->emu, i);
141	}
142}
143
144/*
145 * convert Hz to AWE32 rate offset (see emux/soundfont.c)
146 */
147
148#define OFFSET_SAMPLERATE	1011119		/* base = 44100 */
149#define SAMPLERATE_RATIO	4096
150
151static int calc_rate_offset(int hz)
152{
153	return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
154}
155
156
157/*
158 */
159
160static const struct snd_pcm_hardware emu8k_pcm_hw = {
161#ifdef USE_NONINTERLEAVE
162	.info =			SNDRV_PCM_INFO_NONINTERLEAVED,
163#else
164	.info =			SNDRV_PCM_INFO_INTERLEAVED,
165#endif
166	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
167	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
168	.rate_min =		4000,
169	.rate_max =		48000,
170	.channels_min =		1,
171	.channels_max =		2,
172	.buffer_bytes_max =	(128*1024),
173	.period_bytes_min =	1024,
174	.period_bytes_max =	(128*1024),
175	.periods_min =		2,
176	.periods_max =		1024,
177	.fifo_size =		0,
178
179};
180
181/*
182 * get the current position at the given channel from CCCA register
183 */
184static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch)
185{
186	int val = EMU8000_CCCA_READ(rec->emu, ch) & 0xfffffff;
187	val -= rec->loop_start[ch] - 1;
188	return val;
189}
190
191
192/*
193 * timer interrupt handler
194 * check the current position and update the period if necessary.
195 */
196static void emu8k_pcm_timer_func(struct timer_list *t)
197{
198	struct snd_emu8k_pcm *rec = from_timer(rec, t, timer);
199	int ptr, delta;
200
201	spin_lock(&rec->timer_lock);
202	/* update the current pointer */
203	ptr = emu8k_get_curpos(rec, 0);
204	if (ptr < rec->last_ptr)
205		delta = ptr + rec->buf_size - rec->last_ptr;
206	else
207		delta = ptr - rec->last_ptr;
208	rec->period_pos += delta;
209	rec->last_ptr = ptr;
210
211	/* reprogram timer */
212	mod_timer(&rec->timer, jiffies + 1);
213
214	/* update period */
215	if (rec->period_pos >= (int)rec->period_size) {
216		rec->period_pos %= rec->period_size;
217		spin_unlock(&rec->timer_lock);
218		snd_pcm_period_elapsed(rec->substream);
219		return;
220	}
221	spin_unlock(&rec->timer_lock);
222}
223
224
225/*
226 * open pcm
227 * creating an instance here
228 */
229static int emu8k_pcm_open(struct snd_pcm_substream *subs)
230{
231	struct snd_emu8000 *emu = snd_pcm_substream_chip(subs);
232	struct snd_emu8k_pcm *rec;
233	struct snd_pcm_runtime *runtime = subs->runtime;
234
235	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
236	if (! rec)
237		return -ENOMEM;
238
239	rec->emu = emu;
240	rec->substream = subs;
241	runtime->private_data = rec;
242
243	spin_lock_init(&rec->timer_lock);
244	timer_setup(&rec->timer, emu8k_pcm_timer_func, 0);
245
246	runtime->hw = emu8k_pcm_hw;
247	runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3;
248	runtime->hw.period_bytes_max = runtime->hw.buffer_bytes_max / 2;
249
250	/* use timer to update periods.. (specified in msec) */
251	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
252				     (1000000 + HZ - 1) / HZ, UINT_MAX);
253
254	return 0;
255}
256
257static int emu8k_pcm_close(struct snd_pcm_substream *subs)
258{
259	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
260	kfree(rec);
261	subs->runtime->private_data = NULL;
262	return 0;
263}
264
265/*
266 * calculate pitch target
267 */
268static int calc_pitch_target(int pitch)
269{
270	int ptarget = 1 << (pitch >> 12);
271	if (pitch & 0x800) ptarget += (ptarget * 0x102e) / 0x2710;
272	if (pitch & 0x400) ptarget += (ptarget * 0x764) / 0x2710;
273	if (pitch & 0x200) ptarget += (ptarget * 0x389) / 0x2710;
274	ptarget += (ptarget >> 1);
275	if (ptarget > 0xffff) ptarget = 0xffff;
276	return ptarget;
277}
278
279/*
280 * set up the voice
281 */
282static void setup_voice(struct snd_emu8k_pcm *rec, int ch)
283{
284	struct snd_emu8000 *hw = rec->emu;
285	unsigned int temp;
286
287	/* channel to be silent and idle */
288	EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
289	EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
290	EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
291	EMU8000_PTRX_WRITE(hw, ch, 0);
292	EMU8000_CPF_WRITE(hw, ch, 0);
293
294	/* pitch offset */
295	EMU8000_IP_WRITE(hw, ch, rec->pitch);
296	/* set envelope parameters */
297	EMU8000_ENVVAL_WRITE(hw, ch, 0x8000);
298	EMU8000_ATKHLD_WRITE(hw, ch, 0x7f7f);
299	EMU8000_DCYSUS_WRITE(hw, ch, 0x7f7f);
300	EMU8000_ENVVOL_WRITE(hw, ch, 0x8000);
301	EMU8000_ATKHLDV_WRITE(hw, ch, 0x7f7f);
302	/* decay/sustain parameter for volume envelope is used
303	   for triggerg the voice */
304	/* modulation envelope heights */
305	EMU8000_PEFE_WRITE(hw, ch, 0x0);
306	/* lfo1/2 delay */
307	EMU8000_LFO1VAL_WRITE(hw, ch, 0x8000);
308	EMU8000_LFO2VAL_WRITE(hw, ch, 0x8000);
309	/* lfo1 pitch & cutoff shift */
310	EMU8000_FMMOD_WRITE(hw, ch, 0);
311	/* lfo1 volume & freq */
312	EMU8000_TREMFRQ_WRITE(hw, ch, 0);
313	/* lfo2 pitch & freq */
314	EMU8000_FM2FRQ2_WRITE(hw, ch, 0);
315	/* pan & loop start */
316	temp = rec->panning[ch];
317	temp = (temp <<24) | ((unsigned int)rec->loop_start[ch] - 1);
318	EMU8000_PSST_WRITE(hw, ch, temp);
319	/* chorus & loop end (chorus 8bit, MSB) */
320	temp = 0; // chorus
321	temp = (temp << 24) | ((unsigned int)rec->loop_start[ch] + rec->buf_size - 1);
322	EMU8000_CSL_WRITE(hw, ch, temp);
323	/* Q & current address (Q 4bit value, MSB) */
324	temp = 0; // filterQ
325	temp = (temp << 28) | ((unsigned int)rec->loop_start[ch] - 1);
326	EMU8000_CCCA_WRITE(hw, ch, temp);
327	/* clear unknown registers */
328	EMU8000_00A0_WRITE(hw, ch, 0);
329	EMU8000_0080_WRITE(hw, ch, 0);
330}
331
332/*
333 * trigger the voice
334 */
335static void start_voice(struct snd_emu8k_pcm *rec, int ch)
336{
337	unsigned long flags;
338	struct snd_emu8000 *hw = rec->emu;
339	unsigned int temp, aux;
340	int pt = calc_pitch_target(rec->pitch);
341
342	/* cutoff and volume */
343	EMU8000_IFATN_WRITE(hw, ch, 0xff00);
344	EMU8000_VTFT_WRITE(hw, ch, 0xffff);
345	EMU8000_CVCF_WRITE(hw, ch, 0xffff);
346	/* trigger envelope */
347	EMU8000_DCYSUSV_WRITE(hw, ch, 0x7f7f);
348	/* set reverb and pitch target */
349	temp = 0; // reverb
350	if (rec->panning[ch] == 0)
351		aux = 0xff;
352	else
353		aux = (-rec->panning[ch]) & 0xff;
354	temp = (temp << 8) | (pt << 16) | aux;
355	EMU8000_PTRX_WRITE(hw, ch, temp);
356	EMU8000_CPF_WRITE(hw, ch, pt << 16);
357
358	/* start timer */
359	spin_lock_irqsave(&rec->timer_lock, flags);
360	if (! rec->timer_running) {
361		mod_timer(&rec->timer, jiffies + 1);
362		rec->timer_running = 1;
363	}
364	spin_unlock_irqrestore(&rec->timer_lock, flags);
365}
366
367/*
368 * stop the voice immediately
369 */
370static void stop_voice(struct snd_emu8k_pcm *rec, int ch)
371{
372	unsigned long flags;
373	struct snd_emu8000 *hw = rec->emu;
374
375	EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
376
377	/* stop timer */
378	spin_lock_irqsave(&rec->timer_lock, flags);
379	if (rec->timer_running) {
380		del_timer(&rec->timer);
381		rec->timer_running = 0;
382	}
383	spin_unlock_irqrestore(&rec->timer_lock, flags);
384}
385
386static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
387{
388	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
389	int ch;
390
391	switch (cmd) {
392	case SNDRV_PCM_TRIGGER_START:
393		for (ch = 0; ch < rec->voices; ch++)
394			start_voice(rec, ch);
395		rec->running = 1;
396		break;
397	case SNDRV_PCM_TRIGGER_STOP:
398		rec->running = 0;
399		for (ch = 0; ch < rec->voices; ch++)
400			stop_voice(rec, ch);
401		break;
402	default:
403		return -EINVAL;
404	}
405	return 0;
406}
407
408
409/*
410 * copy / silence ops
411 */
412
413/*
414 * this macro should be inserted in the copy/silence loops
415 * to reduce the latency.  without this, the system will hang up
416 * during the whole loop.
417 */
418#define CHECK_SCHEDULER() \
419do { \
420	cond_resched();\
421	if (signal_pending(current))\
422		return -EAGAIN;\
423} while (0)
424
425enum {
426	COPY_USER, COPY_KERNEL, FILL_SILENCE,
427};
428
429#define GET_VAL(sval, buf, mode)					\
430	do {								\
431		switch (mode) {						\
432		case FILL_SILENCE:					\
433			sval = 0;					\
434			break;						\
435		case COPY_KERNEL:					\
436			sval = *buf++;					\
437			break;						\
438		default:						\
439			if (get_user(sval, (unsigned short __user *)buf)) \
440				return -EFAULT;				\
441			buf++;						\
442			break;						\
443		}							\
444	} while (0)
445
446#ifdef USE_NONINTERLEAVE
447
448#define LOOP_WRITE(rec, offset, _buf, count, mode)		\
449	do {							\
450		struct snd_emu8000 *emu = (rec)->emu;		\
451		unsigned short *buf = (unsigned short *)(_buf); \
452		snd_emu8000_write_wait(emu, 1);			\
453		EMU8000_SMALW_WRITE(emu, offset);		\
454		while (count > 0) {				\
455			unsigned short sval;			\
456			CHECK_SCHEDULER();			\
457			GET_VAL(sval, buf, mode);		\
458			EMU8000_SMLD_WRITE(emu, sval);		\
459			count--;				\
460		}						\
461	} while (0)
462
463/* copy one channel block */
464static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
465			  int voice, unsigned long pos,
466			  void __user *src, unsigned long count)
467{
468	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
469
470	/* convert to word unit */
471	pos = (pos << 1) + rec->loop_start[voice];
472	count <<= 1;
473	LOOP_WRITE(rec, pos, src, count, COPY_UESR);
474	return 0;
475}
476
477static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
478				 int voice, unsigned long pos,
479				 void *src, unsigned long count)
480{
481	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
482
483	/* convert to word unit */
484	pos = (pos << 1) + rec->loop_start[voice];
485	count <<= 1;
486	LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
487	return 0;
488}
489
490/* make a channel block silence */
491static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
492			     int voice, unsigned long pos, unsigned long count)
493{
494	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
495
496	/* convert to word unit */
497	pos = (pos << 1) + rec->loop_start[voice];
498	count <<= 1;
499	LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
500	return 0;
501}
502
503#else /* interleave */
504
505#define LOOP_WRITE(rec, pos, _buf, count, mode)				\
506	do {								\
507		struct snd_emu8000 *emu = rec->emu;			\
508		unsigned short *buf = (unsigned short *)(_buf);		\
509		snd_emu8000_write_wait(emu, 1);				\
510		EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]);	\
511		if (rec->voices > 1)					\
512			EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); \
513		while (count > 0) {					\
514			unsigned short sval;				\
515			CHECK_SCHEDULER();				\
516			GET_VAL(sval, buf, mode);			\
517			EMU8000_SMLD_WRITE(emu, sval);			\
518			if (rec->voices > 1) {				\
519				CHECK_SCHEDULER();			\
520				GET_VAL(sval, buf, mode);		\
521				EMU8000_SMRD_WRITE(emu, sval);		\
522			}						\
523			count--;					\
524		}							\
525	} while (0)
526
527
528/*
529 * copy the interleaved data can be done easily by using
530 * DMA "left" and "right" channels on emu8k engine.
531 */
532static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
533			  int voice, unsigned long pos,
534			  void __user *src, unsigned long count)
535{
536	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
537
538	/* convert to frames */
539	pos = bytes_to_frames(subs->runtime, pos);
540	count = bytes_to_frames(subs->runtime, count);
541	LOOP_WRITE(rec, pos, src, count, COPY_USER);
542	return 0;
543}
544
545static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
546				 int voice, unsigned long pos,
547				 void *src, unsigned long count)
548{
549	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
550
551	/* convert to frames */
552	pos = bytes_to_frames(subs->runtime, pos);
553	count = bytes_to_frames(subs->runtime, count);
554	LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
555	return 0;
556}
557
558static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
559			     int voice, unsigned long pos, unsigned long count)
560{
561	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
562
563	/* convert to frames */
564	pos = bytes_to_frames(subs->runtime, pos);
565	count = bytes_to_frames(subs->runtime, count);
566	LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
567	return 0;
568}
569#endif
570
571
572/*
573 * allocate a memory block
574 */
575static int emu8k_pcm_hw_params(struct snd_pcm_substream *subs,
576			       struct snd_pcm_hw_params *hw_params)
577{
578	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
579
580	if (rec->block) {
581		/* reallocation - release the old block */
582		snd_util_mem_free(rec->emu->memhdr, rec->block);
583		rec->block = NULL;
584	}
585
586	rec->allocated_bytes = params_buffer_bytes(hw_params) + LOOP_BLANK_SIZE * 4;
587	rec->block = snd_util_mem_alloc(rec->emu->memhdr, rec->allocated_bytes);
588	if (! rec->block)
589		return -ENOMEM;
590	rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */
591	/* at least dma_bytes must be set for non-interleaved mode */
592	subs->dma_buffer.bytes = params_buffer_bytes(hw_params);
593
594	return 0;
595}
596
597/*
598 * free the memory block
599 */
600static int emu8k_pcm_hw_free(struct snd_pcm_substream *subs)
601{
602	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
603
604	if (rec->block) {
605		int ch;
606		for (ch = 0; ch < rec->voices; ch++)
607			stop_voice(rec, ch); // to be sure
608		if (rec->dram_opened)
609			emu8k_close_dram(rec->emu);
610		snd_util_mem_free(rec->emu->memhdr, rec->block);
611		rec->block = NULL;
612	}
613	return 0;
614}
615
616/*
617 */
618static int emu8k_pcm_prepare(struct snd_pcm_substream *subs)
619{
620	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
621
622	rec->pitch = 0xe000 + calc_rate_offset(subs->runtime->rate);
623	rec->last_ptr = 0;
624	rec->period_pos = 0;
625
626	rec->buf_size = subs->runtime->buffer_size;
627	rec->period_size = subs->runtime->period_size;
628	rec->voices = subs->runtime->channels;
629	rec->loop_start[0] = rec->offset + LOOP_BLANK_SIZE;
630	if (rec->voices > 1)
631		rec->loop_start[1] = rec->loop_start[0] + rec->buf_size + LOOP_BLANK_SIZE;
632	if (rec->voices > 1) {
633		rec->panning[0] = 0xff;
634		rec->panning[1] = 0x00;
635	} else
636		rec->panning[0] = 0x80;
637
638	if (! rec->dram_opened) {
639		int err, i, ch;
640
641		snd_emux_terminate_all(rec->emu->emu);
642		if ((err = emu8k_open_dram_for_pcm(rec->emu, rec->voices)) != 0)
643			return err;
644		rec->dram_opened = 1;
645
646		/* clear loop blanks */
647		snd_emu8000_write_wait(rec->emu, 0);
648		EMU8000_SMALW_WRITE(rec->emu, rec->offset);
649		for (i = 0; i < LOOP_BLANK_SIZE; i++)
650			EMU8000_SMLD_WRITE(rec->emu, 0);
651		for (ch = 0; ch < rec->voices; ch++) {
652			EMU8000_SMALW_WRITE(rec->emu, rec->loop_start[ch] + rec->buf_size);
653			for (i = 0; i < LOOP_BLANK_SIZE; i++)
654				EMU8000_SMLD_WRITE(rec->emu, 0);
655		}
656	}
657
658	setup_voice(rec, 0);
659	if (rec->voices > 1)
660		setup_voice(rec, 1);
661	return 0;
662}
663
664static snd_pcm_uframes_t emu8k_pcm_pointer(struct snd_pcm_substream *subs)
665{
666	struct snd_emu8k_pcm *rec = subs->runtime->private_data;
667	if (rec->running)
668		return emu8k_get_curpos(rec, 0);
669	return 0;
670}
671
672
673static const struct snd_pcm_ops emu8k_pcm_ops = {
674	.open =		emu8k_pcm_open,
675	.close =	emu8k_pcm_close,
676	.ioctl =	snd_pcm_lib_ioctl,
677	.hw_params =	emu8k_pcm_hw_params,
678	.hw_free =	emu8k_pcm_hw_free,
679	.prepare =	emu8k_pcm_prepare,
680	.trigger =	emu8k_pcm_trigger,
681	.pointer =	emu8k_pcm_pointer,
682	.copy_user =	emu8k_pcm_copy,
683	.copy_kernel =	emu8k_pcm_copy_kernel,
684	.fill_silence =	emu8k_pcm_silence,
685};
686
687
688static void snd_emu8000_pcm_free(struct snd_pcm *pcm)
689{
690	struct snd_emu8000 *emu = pcm->private_data;
691	emu->pcm = NULL;
692}
693
694int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index)
695{
696	struct snd_pcm *pcm;
697	int err;
698
699	if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0)
700		return err;
701	pcm->private_data = emu;
702	pcm->private_free = snd_emu8000_pcm_free;
703	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &emu8k_pcm_ops);
704	emu->pcm = pcm;
705
706	snd_device_register(card, pcm);
707
708	return 0;
709}