/*
 *  Copyright (c) 1998-2002 by Paul Davis <pbd@op.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */

#include <sound/driver.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <sound/snd_wavefront.h>
#include <sound/initval.h>

/* Control bits for the Load Control Register
 */

#define FX_LSB_TRANSFER 0x01    /* transfer after DSP LSB byte written */
#define FX_MSB_TRANSFER 0x02    /* transfer after DSP MSB byte written */
#define FX_AUTO_INCR    0x04    /* auto-increment DSP address after transfer */

#define WAIT_IDLE	0xff

#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
#include "yss225.c"
static const struct firmware yss225_registers_firmware = {
	.data = (u8 *)yss225_registers,
	.size = sizeof yss225_registers
};
#endif

static int
wavefront_fx_idle (snd_wavefront_t *dev)

{
	int i;
	unsigned int x = 0x80;

	for (i = 0; i < 1000; i++) {
		x = inb (dev->fx_status);
		if ((x & 0x80) == 0) {
			break;
		}
	}

	if (x & 0x80) {
		snd_printk ("FX device never idle.\n");
		return 0;
	}

	return (1);
}

static void
wavefront_fx_mute (snd_wavefront_t *dev, int onoff)

{
	if (!wavefront_fx_idle(dev)) {
		return;
	}

	outb (onoff ? 0x02 : 0x00, dev->fx_op);
}

static int
wavefront_fx_memset (snd_wavefront_t *dev,
		     int page,
		     int addr,
		     int cnt,
		     unsigned short *data)
{
	if (page < 0 || page > 7) {
		snd_printk ("FX memset: "
			"page must be >= 0 and <= 7\n");
		return -(EINVAL);
	}

	if (addr < 0 || addr > 0x7f) {
		snd_printk ("FX memset: "
			"addr must be >= 0 and <= 7f\n");
		return -(EINVAL);
	}

	if (cnt == 1) {

		outb (FX_LSB_TRANSFER, dev->fx_lcr);
		outb (page, dev->fx_dsp_page);
		outb (addr, dev->fx_dsp_addr);
		outb ((data[0] >> 8), dev->fx_dsp_msb);
		outb ((data[0] & 0xff), dev->fx_dsp_lsb);

		snd_printk ("FX: addr %d:%x set to 0x%x\n",
			page, addr, data[0]);

	} else {
		int i;

		outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
		outb (page, dev->fx_dsp_page);
		outb (addr, dev->fx_dsp_addr);

		for (i = 0; i < cnt; i++) {
			outb ((data[i] >> 8), dev->fx_dsp_msb);
			outb ((data[i] & 0xff), dev->fx_dsp_lsb);
			if (!wavefront_fx_idle (dev)) {
				break;
			}
		}

		if (i != cnt) {
			snd_printk ("FX memset "
				    "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",
				    page, addr, (unsigned long) data, cnt);
			return -(EIO);
		}
	}

	return 0;
}

int
snd_wavefront_fx_detect (snd_wavefront_t *dev)

{
	/* This is a crude check, but its the best one I have for now.
	   Certainly on the Maui and the Tropez, wavefront_fx_idle() will
	   report "never idle", which suggests that this test should
	   work OK.
	*/

	if (inb (dev->fx_status) & 0x80) {
		snd_printk ("Hmm, probably a Maui or Tropez.\n");
		return -1;
	}

	return 0;
}

int
snd_wavefront_fx_open (struct snd_hwdep *hw, struct file *file)

{
	if (!try_module_get(hw->card->module))
		return -EFAULT;
	file->private_data = hw;
	return 0;
}

int 
snd_wavefront_fx_release (struct snd_hwdep *hw, struct file *file)

{
	module_put(hw->card->module);
	return 0;
}

int
snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
			unsigned int cmd, unsigned long arg)

{
	struct snd_card *card;
	snd_wavefront_card_t *acard;
	snd_wavefront_t *dev;
	wavefront_fx_info r;
	unsigned short *page_data = NULL;
	unsigned short *pd;
	int err = 0;

	snd_assert(sdev->card != NULL, return -ENODEV);
	
	card = sdev->card;

	snd_assert(card->private_data != NULL, return -ENODEV);

	acard = card->private_data;
	dev = &acard->wavefront;

	if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info)))
		return -EFAULT;

	switch (r.request) {
	case WFFX_MUTE:
		wavefront_fx_mute (dev, r.data[0]);
		return -EIO;

	case WFFX_MEMSET:
		if (r.data[2] <= 0) {
			snd_printk ("cannot write "
				"<= 0 bytes to FX\n");
			return -EIO;
		} else if (r.data[2] == 1) {
			pd = (unsigned short *) &r.data[3];
		} else {
			if (r.data[2] > 256) {
				snd_printk ("cannot write "
					    "> 512 bytes to FX\n");
				return -EIO;
			}
			page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
			if (!page_data)
				return -ENOMEM;
			if (copy_from_user (page_data,
					    (unsigned char __user *) r.data[3],
					    r.data[2] * sizeof(short))) {
				kfree(page_data);
				return -EFAULT;
			}
			pd = page_data;
		}

		err = wavefront_fx_memset (dev,
			     r.data[0], /* page */
			     r.data[1], /* addr */
			     r.data[2], /* cnt */
			     pd);
		kfree(page_data);
		break;

	default:
		snd_printk ("FX: ioctl %d not yet supported\n",
			    r.request);
		return -ENOTTY;
	}
	return err;
}

/* YSS225 initialization.

   This code was developed using DOSEMU. The Turtle Beach SETUPSND
   utility was run with I/O tracing in DOSEMU enabled, and a reconstruction
   of the port I/O done, using the Yamaha faxback document as a guide
   to add more logic to the code. Its really pretty weird.

   This is the approach of just dumping the whole I/O
   sequence as a series of port/value pairs and a simple loop
   that outputs it.
*/

int __devinit
snd_wavefront_fx_start (snd_wavefront_t *dev)
{
	unsigned int i;
	int err;
	const struct firmware *firmware = NULL;

	if (dev->fx_initialized)
		return 0;

#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
	firmware = &yss225_registers_firmware;
#else
	err = request_firmware(&firmware, "yamaha/yss225_registers.bin",
			       dev->card->dev);
	if (err < 0) {
		err = -1;
		goto out;
	}
#endif

	for (i = 0; i + 1 < firmware->size; i += 2) {
		if (firmware->data[i] >= 8 && firmware->data[i] < 16) {
			outb(firmware->data[i + 1],
			     dev->base + firmware->data[i]);
		} else if (firmware->data[i] == WAIT_IDLE) {
			if (!wavefront_fx_idle(dev)) {
				err = -1;
				goto out;
			}
		} else {
			snd_printk(KERN_ERR "invalid address"
				   " in register data\n");
			err = -1;
			goto out;
		}
	}

	dev->fx_initialized = 1;
	err = 0;

out:
#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
	release_firmware(firmware);
#endif
	return err;
}

#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
MODULE_FIRMWARE("yamaha/yss225_registers.bin");
#endif
