/*
 * i2sbus driver
 *
 * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
 *
 * GPL v2, can be found in COPYING.
 */

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>

#include <sound/core.h>

#include <asm/macio.h>
#include <asm/dbdma.h>

#include "../soundbus.h"
#include "i2sbus.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_DESCRIPTION("Apple Soundbus: I2S support");

static int force;
module_param(force, int, 0444);
MODULE_PARM_DESC(force, "Force loading i2sbus even when"
			" no layout-id property is present");

static struct of_device_id i2sbus_match[] = {
	{ .name = "i2s" },
	{ }
};

MODULE_DEVICE_TABLE(of, i2sbus_match);

static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
				       struct dbdma_command_mem *r,
				       int numcmds)
{
	/* one more for rounding, one for branch back, one for stop command */
	r->size = (numcmds + 3) * sizeof(struct dbdma_cmd);
	/* We use the PCI APIs for now until the generic one gets fixed
	 * enough or until we get some macio-specific versions
	 */
	r->space = dma_alloc_coherent(
			&macio_get_pci_dev(i2sdev->macio)->dev,
			r->size,
			&r->bus_addr,
			GFP_KERNEL);

	if (!r->space) return -ENOMEM;

	memset(r->space, 0, r->size);
	r->cmds = (void*)DBDMA_ALIGN(r->space);
	r->bus_cmd_start = r->bus_addr +
			   (dma_addr_t)((char*)r->cmds - (char*)r->space);

	return 0;
}

static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
				       struct dbdma_command_mem *r)
{
	if (!r->space) return;

	dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
			    r->size, r->space, r->bus_addr);
}

static void i2sbus_release_dev(struct device *dev)
{
	struct i2sbus_dev *i2sdev;
	int i;

	i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev);

 	if (i2sdev->intfregs) iounmap(i2sdev->intfregs);
 	if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma);
 	if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma);
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
		if (i2sdev->allocated_resource[i])
			release_and_free_resource(i2sdev->allocated_resource[i]);
	free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
	free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring);
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
		free_irq(i2sdev->interrupts[i], i2sdev);
	i2sbus_control_remove_dev(i2sdev->control, i2sdev);
	mutex_destroy(&i2sdev->lock);
	kfree(i2sdev);
}

static irqreturn_t i2sbus_bus_intr(int irq, void *devid)
{
	struct i2sbus_dev *dev = devid;
	u32 intreg;

	spin_lock(&dev->low_lock);
	intreg = in_le32(&dev->intfregs->intr_ctl);

	/* acknowledge interrupt reasons */
	out_le32(&dev->intfregs->intr_ctl, intreg);

	spin_unlock(&dev->low_lock);

	return IRQ_HANDLED;
}


/*
 * XXX FIXME: We test the layout_id's here to get the proper way of
 * mapping in various registers, thanks to bugs in Apple device-trees.
 * We could instead key off the machine model and the name of the i2s
 * node (i2s-a). This we'll do when we move it all to macio_asic.c
 * and have that export items for each sub-node too.
 */
static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index,
				     int layout, struct resource *res)
{
	struct device_node *parent;
	int pindex, rc = -ENXIO;
	const u32 *reg;

	/* Machines with layout 76 and 36 (K2 based) have a weird device
	 * tree what we need to special case.
	 * Normal machines just fetch the resource from the i2s-X node.
	 * Darwin further divides normal machines into old and new layouts
	 * with a subtely different code path but that doesn't seem necessary
	 * in practice, they just bloated it. In addition, even on our K2
	 * case the i2s-modem node, if we ever want to handle it, uses the
	 * normal layout
	 */
	if (layout != 76 && layout != 36)
		return of_address_to_resource(np, index, res);

	parent = of_get_parent(np);
	pindex = (index == aoa_resource_i2smmio) ? 0 : 1;
	rc = of_address_to_resource(parent, pindex, res);
	if (rc)
		goto bail;
	reg = of_get_property(np, "reg", NULL);
	if (reg == NULL) {
		rc = -ENXIO;
		goto bail;
	}
	res->start += reg[index * 2];
	res->end = res->start + reg[index * 2 + 1] - 1;
 bail:
	of_node_put(parent);
	return rc;
}

/* FIXME: look at device node refcounting */
static int i2sbus_add_dev(struct macio_dev *macio,
			  struct i2sbus_control *control,
			  struct device_node *np)
{
	struct i2sbus_dev *dev;
	struct device_node *child = NULL, *sound = NULL;
	struct resource *r;
	int i, layout = 0, rlen, ok = force;
	static const char *rnames[] = { "i2sbus: %s (control)",
					"i2sbus: %s (tx)",
					"i2sbus: %s (rx)" };
	static irq_handler_t ints[] = {
		i2sbus_bus_intr,
		i2sbus_tx_intr,
		i2sbus_rx_intr
	};

	if (strlen(np->name) != 5)
		return 0;
	if (strncmp(np->name, "i2s-", 4))
		return 0;

	dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL);
	if (!dev)
		return 0;

	i = 0;
	while ((child = of_get_next_child(np, child))) {
		if (strcmp(child->name, "sound") == 0) {
			i++;
			sound = child;
		}
	}
	if (i == 1) {
		const u32 *id = of_get_property(sound, "layout-id", NULL);

		if (id) {
			layout = *id;
			snprintf(dev->sound.modalias, 32,
				 "sound-layout-%d", layout);
			ok = 1;
		} else {
			id = of_get_property(sound, "device-id", NULL);
			/*
			 * We probably cannot handle all device-id machines,
			 * so restrict to those we do handle for now.
			 */
			if (id && (*id == 22 || *id == 14 || *id == 35)) {
				snprintf(dev->sound.modalias, 32,
					 "aoa-device-id-%d", *id);
				ok = 1;
				layout = -1;
			}
		}
	}
	/* for the time being, until we can handle non-layout-id
	 * things in some fabric, refuse to attach if there is no
	 * layout-id property or we haven't been forced to attach.
	 * When there are two i2s busses and only one has a layout-id,
	 * then this depends on the order, but that isn't important
	 * either as the second one in that case is just a modem. */
	if (!ok) {
		kfree(dev);
		return -ENODEV;
	}

	mutex_init(&dev->lock);
	spin_lock_init(&dev->low_lock);
	dev->sound.ofdev.node = np;
	dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask;
	dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask;
	dev->sound.ofdev.dev.parent = &macio->ofdev.dev;
	dev->sound.ofdev.dev.release = i2sbus_release_dev;
	dev->sound.attach_codec = i2sbus_attach_codec;
	dev->sound.detach_codec = i2sbus_detach_codec;
	dev->sound.pcmid = -1;
	dev->macio = macio;
	dev->control = control;
	dev->bus_number = np->name[4] - 'a';
	INIT_LIST_HEAD(&dev->sound.codec_list);

	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
		dev->interrupts[i] = -1;
		snprintf(dev->rnames[i], sizeof(dev->rnames[i]),
			 rnames[i], np->name);
	}
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
		int irq = irq_of_parse_and_map(np, i);
		if (request_irq(irq, ints[i], 0, dev->rnames[i], dev))
			goto err;
		dev->interrupts[i] = irq;
	}


	/* Resource handling is problematic as some device-trees contain
	 * useless crap (ugh ugh ugh). We work around that here by calling
	 * specific functions for calculating the appropriate resources.
	 *
	 * This will all be moved to macio_asic.c at one point
	 */
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
		if (i2sbus_get_and_fixup_rsrc(np,i,layout,&dev->resources[i]))
			goto err;
		/* If only we could use our resource dev->resources[i]...
		 * but request_resource doesn't know about parents and
		 * contained resources...
		 */
		dev->allocated_resource[i] =
			request_mem_region(dev->resources[i].start,
					   dev->resources[i].end -
					   dev->resources[i].start + 1,
					   dev->rnames[i]);
		if (!dev->allocated_resource[i]) {
			printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i);
			goto err;
		}
	}

	r = &dev->resources[aoa_resource_i2smmio];
	rlen = r->end - r->start + 1;
	if (rlen < sizeof(struct i2s_interface_regs))
		goto err;
	dev->intfregs = ioremap(r->start, rlen);

	r = &dev->resources[aoa_resource_txdbdma];
	rlen = r->end - r->start + 1;
	if (rlen < sizeof(struct dbdma_regs))
		goto err;
	dev->out.dbdma = ioremap(r->start, rlen);

	r = &dev->resources[aoa_resource_rxdbdma];
	rlen = r->end - r->start + 1;
	if (rlen < sizeof(struct dbdma_regs))
		goto err;
	dev->in.dbdma = ioremap(r->start, rlen);

	if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma)
		goto err;

	if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring,
					MAX_DBDMA_COMMANDS))
		goto err;
	if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring,
					MAX_DBDMA_COMMANDS))
		goto err;

	if (i2sbus_control_add_dev(dev->control, dev)) {
		printk(KERN_ERR "i2sbus: control layer didn't like bus\n");
		goto err;
	}

	if (soundbus_add_one(&dev->sound)) {
		printk(KERN_DEBUG "i2sbus: device registration error!\n");
		goto err;
	}

	/* enable this cell */
	i2sbus_control_cell(dev->control, dev, 1);
	i2sbus_control_enable(dev->control, dev);
	i2sbus_control_clock(dev->control, dev, 1);

	return 1;
 err:
	for (i=0;i<3;i++)
		if (dev->interrupts[i] != -1)
			free_irq(dev->interrupts[i], dev);
	free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring);
	free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring);
	if (dev->intfregs) iounmap(dev->intfregs);
	if (dev->out.dbdma) iounmap(dev->out.dbdma);
	if (dev->in.dbdma) iounmap(dev->in.dbdma);
	for (i=0;i<3;i++)
		if (dev->allocated_resource[i])
			release_and_free_resource(dev->allocated_resource[i]);
	mutex_destroy(&dev->lock);
	kfree(dev);
	return 0;
}

static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
{
	struct device_node *np = NULL;
	int got = 0, err;
	struct i2sbus_control *control = NULL;

	err = i2sbus_control_init(dev, &control);
	if (err)
		return err;
	if (!control) {
		printk(KERN_ERR "i2sbus_control_init API breakage\n");
		return -ENODEV;
	}

	while ((np = of_get_next_child(dev->ofdev.node, np))) {
		if (of_device_is_compatible(np, "i2sbus") ||
		    of_device_is_compatible(np, "i2s-modem")) {
			got += i2sbus_add_dev(dev, control, np);
		}
	}

	if (!got) {
		/* found none, clean up */
		i2sbus_control_destroy(control);
		return -ENODEV;
	}

	dev_set_drvdata(&dev->ofdev.dev, control);

	return 0;
}

static int i2sbus_remove(struct macio_dev* dev)
{
	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
	struct i2sbus_dev *i2sdev, *tmp;

	list_for_each_entry_safe(i2sdev, tmp, &control->list, item)
		soundbus_remove_one(&i2sdev->sound);

	return 0;
}

#ifdef CONFIG_PM
static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
{
	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
	struct codec_info_item *cii;
	struct i2sbus_dev* i2sdev;
	int err, ret = 0;

	list_for_each_entry(i2sdev, &control->list, item) {
		/* Notify Alsa */
		if (i2sdev->sound.pcm) {
			/* Suspend PCM streams */
			snd_pcm_suspend_all(i2sdev->sound.pcm);
		}

		/* Notify codecs */
		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
			err = 0;
			if (cii->codec->suspend)
				err = cii->codec->suspend(cii, state);
			if (err)
				ret = err;
		}

		/* wait until streams are stopped */
		i2sbus_wait_for_stop_both(i2sdev);
	}

	return ret;
}

static int i2sbus_resume(struct macio_dev* dev)
{
	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
	struct codec_info_item *cii;
	struct i2sbus_dev* i2sdev;
	int err, ret = 0;

	list_for_each_entry(i2sdev, &control->list, item) {
		/* reset i2s bus format etc. */
		i2sbus_pcm_prepare_both(i2sdev);

		/* Notify codecs so they can re-initialize */
		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
			err = 0;
			if (cii->codec->resume)
				err = cii->codec->resume(cii);
			if (err)
				ret = err;
		}
	}

	return ret;
}
#endif /* CONFIG_PM */

static int i2sbus_shutdown(struct macio_dev* dev)
{
	return 0;
}

static struct macio_driver i2sbus_drv = {
	.name = "soundbus-i2s",
	.owner = THIS_MODULE,
	.match_table = i2sbus_match,
	.probe = i2sbus_probe,
	.remove = i2sbus_remove,
#ifdef CONFIG_PM
	.suspend = i2sbus_suspend,
	.resume = i2sbus_resume,
#endif
	.shutdown = i2sbus_shutdown,
};

static int __init soundbus_i2sbus_init(void)
{
	return macio_register_driver(&i2sbus_drv);
}

static void __exit soundbus_i2sbus_exit(void)
{
	macio_unregister_driver(&i2sbus_drv);
}

module_init(soundbus_i2sbus_init);
module_exit(soundbus_i2sbus_exit);
