core.c 11.9 KB
Newer Older
J
Johannes Berg 已提交
1 2 3
/*
 * i2sbus driver
 *
4
 * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
J
Johannes Berg 已提交
5 6 7 8 9
 *
 * GPL v2, can be found in COPYING.
 */

#include <linux/module.h>
10
#include <linux/slab.h>
J
Johannes Berg 已提交
11 12
#include <linux/pci.h>
#include <linux/interrupt.h>
13
#include <linux/dma-mapping.h>
14 15
#include <linux/of_address.h>
#include <linux/of_irq.h>
16

J
Johannes Berg 已提交
17
#include <sound/core.h>
18 19 20 21

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

J
Johannes Berg 已提交
22 23 24 25 26 27 28
#include "../soundbus.h"
#include "i2sbus.h"

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

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

34
static const struct of_device_id i2sbus_match[] = {
J
Johannes Berg 已提交
35 36 37 38
	{ .name = "i2s" },
	{ }
};

39 40
MODULE_DEVICE_TABLE(of, i2sbus_match);

J
Johannes Berg 已提交
41 42 43 44
static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
				       struct dbdma_command_mem *r,
				       int numcmds)
{
45 46
	/* one more for rounding, one for branch back, one for stop command */
	r->size = (numcmds + 3) * sizeof(struct dbdma_cmd);
J
Johannes Berg 已提交
47 48 49
	/* We use the PCI APIs for now until the generic one gets fixed
	 * enough or until we get some macio-specific versions
	 */
50 51
	r->space = dma_alloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
				      r->size, &r->bus_addr, GFP_KERNEL);
J
Joe Perches 已提交
52 53
	if (!r->space)
		return -ENOMEM;
J
Johannes Berg 已提交
54 55 56 57 58 59 60 61 62 63 64 65

	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;
J
Johannes Berg 已提交
66

J
Johannes Berg 已提交
67 68 69 70 71 72 73 74 75 76
	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);
77 78 79
	iounmap(i2sdev->intfregs);
	iounmap(i2sdev->out.dbdma);
	iounmap(i2sdev->in.dbdma);
80
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
81
		release_and_free_resource(i2sdev->allocated_resource[i]);
J
Johannes Berg 已提交
82 83
	free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
	free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring);
84
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
J
Johannes Berg 已提交
85 86 87 88 89 90
		free_irq(i2sdev->interrupts[i], i2sdev);
	i2sbus_control_remove_dev(i2sdev->control, i2sdev);
	mutex_destroy(&i2sdev->lock);
	kfree(i2sdev);
}

91
static irqreturn_t i2sbus_bus_intr(int irq, void *devid)
J
Johannes Berg 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
{
	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;
}

107 108 109 110 111 112 113 114 115 116 117 118 119

/*
 * 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;
120
	const u32 *reg;
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

	/* 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;
139
	reg = of_get_property(np, "reg", NULL);
140 141 142 143 144 145 146 147 148 149 150
	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;
}

J
Johannes Berg 已提交
151 152 153 154 155 156
/* 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;
157
	struct device_node *child, *sound = NULL;
158
	struct resource *r;
159
	int i, layout = 0, rlen, ok = force;
160 161 162 163
	char node_name[6];
	static const char *rnames[] = { "i2sbus: %pOFn (control)",
					"i2sbus: %pOFn (tx)",
					"i2sbus: %pOFn (rx)" };
164
	static irq_handler_t ints[] = {
J
Johannes Berg 已提交
165 166 167 168 169
		i2sbus_bus_intr,
		i2sbus_tx_intr,
		i2sbus_rx_intr
	};

170
	if (snprintf(node_name, sizeof(node_name), "%pOFn", np) != 5)
J
Johannes Berg 已提交
171
		return 0;
172
	if (strncmp(node_name, "i2s-", 4))
J
Johannes Berg 已提交
173 174 175 176 177 178 179
		return 0;

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

	i = 0;
180 181
	for_each_child_of_node(np, child) {
		if (of_node_name_eq(child, "sound")) {
J
Johannes Berg 已提交
182 183 184 185 186
			i++;
			sound = child;
		}
	}
	if (i == 1) {
187 188 189 190
		const u32 *id = of_get_property(sound, "layout-id", NULL);

		if (id) {
			layout = *id;
J
Johannes Berg 已提交
191
			snprintf(dev->sound.modalias, 32,
192
				 "sound-layout-%d", layout);
193
			ok = 1;
194 195 196 197 198 199
		} 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.
			 */
200
			if (id && (*id == 22 || *id == 14 || *id == 35 ||
201
				   *id == 31 || *id == 44)) {
202 203 204 205 206
				snprintf(dev->sound.modalias, 32,
					 "aoa-device-id-%d", *id);
				ok = 1;
				layout = -1;
			}
J
Johannes Berg 已提交
207 208 209 210 211 212 213 214
		}
	}
	/* 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. */
215
	if (!ok) {
J
Johannes Berg 已提交
216 217 218 219 220 221
		kfree(dev);
		return -ENODEV;
	}

	mutex_init(&dev->lock);
	spin_lock_init(&dev->low_lock);
222
	dev->sound.ofdev.archdata.dma_mask = macio->ofdev.archdata.dma_mask;
223
	dev->sound.ofdev.dev.of_node = np;
224
	dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.archdata.dma_mask;
J
Johannes Berg 已提交
225 226 227 228 229 230 231
	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;
232
	dev->bus_number = node_name[4] - 'a';
J
Johannes Berg 已提交
233 234
	INIT_LIST_HEAD(&dev->sound.codec_list);

235
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
J
Johannes Berg 已提交
236
		dev->interrupts[i] = -1;
237
		snprintf(dev->rnames[i], sizeof(dev->rnames[i]),
238
			 rnames[i], np);
J
Johannes Berg 已提交
239
	}
240
	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
241 242
		int irq = irq_of_parse_and_map(np, i);
		if (request_irq(irq, ints[i], 0, dev->rnames[i], dev))
J
Johannes Berg 已提交
243
			goto err;
244
		dev->interrupts[i] = irq;
J
Johannes Berg 已提交
245 246
	}

247 248 249 250 251 252 253 254 255

	/* 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]))
J
Johannes Berg 已提交
256
			goto err;
257
		/* If only we could use our resource dev->resources[i]...
J
Johannes Berg 已提交
258
		 * but request_resource doesn't know about parents and
259 260
		 * contained resources...
		 */
J
Johannes Berg 已提交
261
		dev->allocated_resource[i] =
J
Johannes Berg 已提交
262
			request_mem_region(dev->resources[i].start,
263
					   resource_size(&dev->resources[i]),
J
Johannes Berg 已提交
264 265 266 267 268 269
					   dev->rnames[i]);
		if (!dev->allocated_resource[i]) {
			printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i);
			goto err;
		}
	}
270 271

	r = &dev->resources[aoa_resource_i2smmio];
272
	rlen = resource_size(r);
273 274 275 276 277
	if (rlen < sizeof(struct i2s_interface_regs))
		goto err;
	dev->intfregs = ioremap(r->start, rlen);

	r = &dev->resources[aoa_resource_txdbdma];
278
	rlen = resource_size(r);
279 280 281 282 283
	if (rlen < sizeof(struct dbdma_regs))
		goto err;
	dev->out.dbdma = ioremap(r->start, rlen);

	r = &dev->resources[aoa_resource_rxdbdma];
284
	rlen = resource_size(r);
285 286 287 288
	if (rlen < sizeof(struct dbdma_regs))
		goto err;
	dev->in.dbdma = ioremap(r->start, rlen);

J
Johannes Berg 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
	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);
321 322 323
	iounmap(dev->intfregs);
	iounmap(dev->out.dbdma);
	iounmap(dev->in.dbdma);
J
Johannes Berg 已提交
324
	for (i=0;i<3;i++)
325
		release_and_free_resource(dev->allocated_resource[i]);
J
Johannes Berg 已提交
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
	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;
	}

345
	while ((np = of_get_next_child(dev->ofdev.dev.of_node, np))) {
346 347
		if (of_device_is_compatible(np, "i2sbus") ||
		    of_device_is_compatible(np, "i2s-modem")) {
J
Johannes Berg 已提交
348 349 350 351 352 353 354 355 356 357
			got += i2sbus_add_dev(dev, control, np);
		}
	}

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

358
	dev_set_drvdata(&dev->ofdev.dev, control);
J
Johannes Berg 已提交
359 360 361 362 363 364

	return 0;
}

static int i2sbus_remove(struct macio_dev* dev)
{
365
	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
J
Johannes Berg 已提交
366 367 368 369 370 371 372 373 374 375 376
	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)
{
377
	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
J
Johannes Berg 已提交
378 379 380 381 382 383 384 385 386 387 388 389 390
	struct codec_info_item *cii;
	struct i2sbus_dev* i2sdev;
	int err, ret = 0;

	list_for_each_entry(i2sdev, &control->list, item) {
		/* 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;
		}
391 392 393

		/* wait until streams are stopped */
		i2sbus_wait_for_stop_both(i2sdev);
J
Johannes Berg 已提交
394
	}
395

J
Johannes Berg 已提交
396 397 398 399 400
	return ret;
}

static int i2sbus_resume(struct macio_dev* dev)
{
401
	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
J
Johannes Berg 已提交
402 403 404 405 406
	struct codec_info_item *cii;
	struct i2sbus_dev* i2sdev;
	int err, ret = 0;

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

J
Johannes Berg 已提交
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
		/* 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 = {
430 431 432 433 434
	.driver = {
		.name = "soundbus-i2s",
		.owner = THIS_MODULE,
		.of_match_table = i2sbus_match,
	},
J
Johannes Berg 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
	.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);