/*
 * Driver for Digigram VX soundcards
 *
 * DSP firmware management
 *
 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
 *
 *   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 <linux/device.h>
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#include <sound/core.h>
#include <sound/hwdep.h>
#include <sound/vx_core.h>

#ifdef SND_VX_FW_LOADER

MODULE_FIRMWARE("vx/bx_1_vxp.b56");
MODULE_FIRMWARE("vx/bx_1_vp4.b56");
MODULE_FIRMWARE("vx/x1_1_vx2.xlx");
MODULE_FIRMWARE("vx/x1_2_v22.xlx");
MODULE_FIRMWARE("vx/x1_1_vxp.xlx");
MODULE_FIRMWARE("vx/x1_1_vp4.xlx");
MODULE_FIRMWARE("vx/bd56002.boot");
MODULE_FIRMWARE("vx/bd563v2.boot");
MODULE_FIRMWARE("vx/bd563s3.boot");
MODULE_FIRMWARE("vx/l_1_vx2.d56");
MODULE_FIRMWARE("vx/l_1_v22.d56");
MODULE_FIRMWARE("vx/l_1_vxp.d56");
MODULE_FIRMWARE("vx/l_1_vp4.d56");

int snd_vx_setup_firmware(struct vx_core *chip)
{
	static char *fw_files[VX_TYPE_NUMS][4] = {
		[VX_TYPE_BOARD] = {
			NULL, "x1_1_vx2.xlx", "bd56002.boot", "l_1_vx2.d56",
		},
		[VX_TYPE_V2] = {
			NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56",
		},
		[VX_TYPE_MIC] = {
			NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56",
		},
		[VX_TYPE_VXPOCKET] = {
			"bx_1_vxp.b56", "x1_1_vxp.xlx", "bd563s3.boot", "l_1_vxp.d56"
		},
		[VX_TYPE_VXP440] = {
			"bx_1_vp4.b56", "x1_1_vp4.xlx", "bd563s3.boot", "l_1_vp4.d56"
		},
	};

	int i, err;

	for (i = 0; i < 4; i++) {
		char path[32];
		const struct firmware *fw;
		if (! fw_files[chip->type][i])
			continue;
		sprintf(path, "vx/%s", fw_files[chip->type][i]);
		if (request_firmware(&fw, path, chip->dev)) {
			snd_printk(KERN_ERR "vx: can't load firmware %s\n", path);
			return -ENOENT;
		}
		err = chip->ops->load_dsp(chip, i, fw);
		if (err < 0) {
			release_firmware(fw);
			return err;
		}
		if (i == 1)
			chip->chip_status |= VX_STAT_XILINX_LOADED;
#ifdef CONFIG_PM
		chip->firmware[i] = fw;
#else
		release_firmware(fw);
#endif
	}

	/* ok, we reached to the last one */
	/* create the devices if not built yet */
	if ((err = snd_vx_pcm_new(chip)) < 0)
		return err;

	if ((err = snd_vx_mixer_new(chip)) < 0)
		return err;

	if (chip->ops->add_controls)
		if ((err = chip->ops->add_controls(chip)) < 0)
			return err;

	chip->chip_status |= VX_STAT_DEVICE_INIT;
	chip->chip_status |= VX_STAT_CHIP_INIT;

	return snd_card_register(chip->card);
}

/* exported */
void snd_vx_free_firmware(struct vx_core *chip)
{
#ifdef CONFIG_PM
	int i;
	for (i = 0; i < 4; i++)
		release_firmware(chip->firmware[i]);
#endif
}

#else /* old style firmware loading */

static int vx_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
	return 0;
}

static int vx_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
	return 0;
}

static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
			       struct snd_hwdep_dsp_status *info)
{
	static char *type_ids[VX_TYPE_NUMS] = {
		[VX_TYPE_BOARD] = "vxboard",
		[VX_TYPE_V2] = "vx222",
		[VX_TYPE_MIC] = "vx222",
		[VX_TYPE_VXPOCKET] = "vxpocket",
		[VX_TYPE_VXP440] = "vxp440",
	};
	struct vx_core *vx = hw->private_data;

	if (snd_BUG_ON(!type_ids[vx->type]))
		return -EINVAL;
	strcpy(info->id, type_ids[vx->type]);
	if (vx_is_pcmcia(vx))
		info->num_dsps = 4;
	else
		info->num_dsps = 3;
	if (vx->chip_status & VX_STAT_CHIP_INIT)
		info->chip_ready = 1;
	info->version = VX_DRIVER_VERSION;
	return 0;
}

static void free_fw(const struct firmware *fw)
{
	if (fw) {
		vfree(fw->data);
		kfree(fw);
	}
}

static int vx_hwdep_dsp_load(struct snd_hwdep *hw,
			     struct snd_hwdep_dsp_image *dsp)
{
	struct vx_core *vx = hw->private_data;
	int index, err;
	struct firmware *fw;

	if (snd_BUG_ON(!vx->ops->load_dsp))
		return -ENXIO;

	fw = kmalloc(sizeof(*fw), GFP_KERNEL);
	if (! fw) {
		snd_printk(KERN_ERR "cannot allocate firmware\n");
		return -ENOMEM;
	}
	fw->size = dsp->length;
	fw->data = vmalloc(fw->size);
	if (! fw->data) {
		snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n",
			   (int)fw->size);
		kfree(fw);
		return -ENOMEM;
	}
	if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) {
		free_fw(fw);
		return -EFAULT;
	}

	index = dsp->index;
	if (! vx_is_pcmcia(vx))
		index++;
	err = vx->ops->load_dsp(vx, index, fw);
	if (err < 0) {
		free_fw(fw);
		return err;
	}
#ifdef CONFIG_PM
	vx->firmware[index] = fw;
#else
	free_fw(fw);
#endif

	if (index == 1)
		vx->chip_status |= VX_STAT_XILINX_LOADED;
	if (index < 3)
		return 0;

	/* ok, we reached to the last one */
	/* create the devices if not built yet */
	if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) {
		if ((err = snd_vx_pcm_new(vx)) < 0)
			return err;

		if ((err = snd_vx_mixer_new(vx)) < 0)
			return err;

		if (vx->ops->add_controls)
			if ((err = vx->ops->add_controls(vx)) < 0)
				return err;

		if ((err = snd_card_register(vx->card)) < 0)
			return err;

		vx->chip_status |= VX_STAT_DEVICE_INIT;
	}
	vx->chip_status |= VX_STAT_CHIP_INIT;
	return 0;
}


/* exported */
int snd_vx_setup_firmware(struct vx_core *chip)
{
	int err;
	struct snd_hwdep *hw;

	if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0)
		return err;

	hw->iface = SNDRV_HWDEP_IFACE_VX;
	hw->private_data = chip;
	hw->ops.open = vx_hwdep_open;
	hw->ops.release = vx_hwdep_release;
	hw->ops.dsp_status = vx_hwdep_dsp_status;
	hw->ops.dsp_load = vx_hwdep_dsp_load;
	hw->exclusive = 1;
	sprintf(hw->name, "VX Loader (%s)", chip->card->driver);
	chip->hwdep = hw;

	return snd_card_register(chip->card);
}

/* exported */
void snd_vx_free_firmware(struct vx_core *chip)
{
#ifdef CONFIG_PM
	int i;
	for (i = 0; i < 4; i++)
		free_fw(chip->firmware[i]);
#endif
}

#endif /* SND_VX_FW_LOADER */

EXPORT_SYMBOL(snd_vx_setup_firmware);
EXPORT_SYMBOL(snd_vx_free_firmware);
