// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Patch routines for the emu8000 (AWE32/64)
 *
 *  Copyright (C) 1999 Steve Ratcliffe
 *  Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
 */

#include "emu8000_local.h"

#include <linux/sched/signal.h>
#include <linux/uaccess.h>
#include <linux/moduleparam.h>

static int emu8000_reset_addr;
module_param(emu8000_reset_addr, int, 0444);
MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)");


/*
 * Open up channels.
 */
static int
snd_emu8000_open_dma(struct snd_emu8000 *emu, int write)
{
	int i;

	/* reserve all 30 voices for loading */
	for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
		snd_emux_lock_voice(emu->emu, i);
		snd_emu8000_dma_chan(emu, i, write);
	}

	/* assign voice 31 and 32 to ROM */
	EMU8000_VTFT_WRITE(emu, 30, 0);
	EMU8000_PSST_WRITE(emu, 30, 0x1d8);
	EMU8000_CSL_WRITE(emu, 30, 0x1e0);
	EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
	EMU8000_VTFT_WRITE(emu, 31, 0);
	EMU8000_PSST_WRITE(emu, 31, 0x1d8);
	EMU8000_CSL_WRITE(emu, 31, 0x1e0);
	EMU8000_CCCA_WRITE(emu, 31, 0x1d8);

	return 0;
}

/*
 * Close all dram channels.
 */
static void
snd_emu8000_close_dma(struct snd_emu8000 *emu)
{
	int i;

	for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
		snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
		snd_emux_unlock_voice(emu->emu, i);
	}
}

/*
 */

#define BLANK_LOOP_START	4
#define BLANK_LOOP_END		8
#define BLANK_LOOP_SIZE		12
#define BLANK_HEAD_SIZE		48

/*
 * Read a word from userland, taking care of conversions from
 * 8bit samples etc.
 */
static unsigned short
read_word(const void __user *buf, int offset, int mode)
{
	unsigned short c;
	if (mode & SNDRV_SFNT_SAMPLE_8BITS) {
		unsigned char cc;
		get_user(cc, (unsigned char __user *)buf + offset);
		c = cc << 8; /* convert 8bit -> 16bit */
	} else {
#ifdef SNDRV_LITTLE_ENDIAN
		get_user(c, (unsigned short __user *)buf + offset);
#else
		unsigned short cc;
		get_user(cc, (unsigned short __user *)buf + offset);
		c = swab16(cc);
#endif
	}
	if (mode & SNDRV_SFNT_SAMPLE_UNSIGNED)
		c ^= 0x8000; /* unsigned -> signed */
	return c;
}

/*
 */
static void
snd_emu8000_write_wait(struct snd_emu8000 *emu)
{
	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
		schedule_timeout_interruptible(1);
		if (signal_pending(current))
			break;
	}
}

/*
 * write sample word data
 *
 * You should not have to keep resetting the address each time
 * as the chip is supposed to step on the next address automatically.
 * It mostly does, but during writes of some samples at random it
 * completely loses words (every one in 16 roughly but with no
 * obvious pattern).
 *
 * This is therefore much slower than need be, but is at least
 * working.
 */
static inline void
write_word(struct snd_emu8000 *emu, int *offset, unsigned short data)
{
	if (emu8000_reset_addr) {
		if (emu8000_reset_addr > 1)
			snd_emu8000_write_wait(emu);
		EMU8000_SMALW_WRITE(emu, *offset);
	}
	EMU8000_SMLD_WRITE(emu, data);
	*offset += 1;
}

/*
 * Write the sample to EMU800 memory.  This routine is invoked out of
 * the generic soundfont routines as a callback.
 */
int
snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
		       struct snd_util_memhdr *hdr,
		       const void __user *data, long count)
{
	int  i;
	int  rc;
	int  offset;
	int  truesize;
	int  dram_offset, dram_start;
	struct snd_emu8000 *emu;

	emu = rec->hw;
	if (snd_BUG_ON(!sp))
		return -EINVAL;

	if (sp->v.size == 0)
		return 0;

	/* be sure loop points start < end */
	if (sp->v.loopstart > sp->v.loopend)
		swap(sp->v.loopstart, sp->v.loopend);

	/* compute true data size to be loaded */
	truesize = sp->v.size;
	if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
		truesize += sp->v.loopend - sp->v.loopstart;
	if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
		truesize += BLANK_LOOP_SIZE;

	sp->block = snd_util_mem_alloc(hdr, truesize * 2);
	if (sp->block == NULL) {
		/*snd_printd("EMU8000: out of memory\n");*/
		/* not ENOMEM (for compatibility) */
		return -ENOSPC;
	}

	if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
		if (!access_ok(data, sp->v.size))
			return -EFAULT;
	} else {
		if (!access_ok(data, sp->v.size * 2))
			return -EFAULT;
	}

	/* 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;

	/* dram position (in word) -- mem_offset is byte */
	dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1);
	dram_start = dram_offset;

	/* set the total size (store onto obsolete checksum value) */
	sp->v.truesize = truesize * 2; /* in bytes */

	snd_emux_terminate_all(emu->emu);
	if ((rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE)) != 0)
		return rc;

	/* Set the address to start writing at */
	snd_emu8000_write_wait(emu);
	EMU8000_SMALW_WRITE(emu, dram_offset);

	/*snd_emu8000_init_fm(emu);*/

#if 0
	/* first block - write 48 samples for silence */
	if (! sp->block->offset) {
		for (i = 0; i < BLANK_HEAD_SIZE; i++) {
			write_word(emu, &dram_offset, 0);
		}
	}
#endif

	offset = 0;
	for (i = 0; i < sp->v.size; i++) {
		unsigned short s;

		s = read_word(data, offset, sp->v.mode_flags);
		offset++;
		write_word(emu, &dram_offset, s);

		/* we may take too long time in this loop.
		 * so give controls back to kernel if needed.
		 */
		cond_resched();

		if (i == sp->v.loopend &&
		    (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)))
		{
			int looplen = sp->v.loopend - sp->v.loopstart;
			int k;

			/* copy reverse loop */
			for (k = 1; k <= looplen; k++) {
				s = read_word(data, offset - k, sp->v.mode_flags);
				write_word(emu, &dram_offset, s);
			}
			if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
				sp->v.loopend += looplen;
			} else {
				sp->v.loopstart += looplen;
				sp->v.loopend += looplen;
			}
			sp->v.end += looplen;
		}
	}

	/* if no blank loop is attached in the sample, add it */
	if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
		for (i = 0; i < BLANK_LOOP_SIZE; i++) {
			write_word(emu, &dram_offset, 0);
		}
		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;
		}
	}

	/* add dram offset */
	sp->v.start += dram_start;
	sp->v.end += dram_start;
	sp->v.loopstart += dram_start;
	sp->v.loopend += dram_start;

	snd_emu8000_close_dma(emu);
	snd_emu8000_init_fm(emu);

	return 0;
}

/*
 * free a sample block
 */
int
snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
			struct snd_util_memhdr *hdr)
{
	if (sp->block) {
		snd_util_mem_free(hdr, sp->block);
		sp->block = NULL;
	}
	return 0;
}


/*
 * sample_reset callback - terminate voices
 */
void
snd_emu8000_sample_reset(struct snd_emux *rec)
{
	snd_emux_terminate_all(rec);
}
