staticint 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;
/* * 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.
*/ staticint 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);
if (snprintf(node_name, sizeof(node_name), "%pOFn", np) != 5) return 0; if (strncmp(node_name, "i2s-", 4)) return 0;
dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); if (!dev) return 0;
i = 0;
for_each_child_of_node(np, child) { if (of_node_name_eq(child, "sound")) {
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 ||
*id == 31 || *id == 44)) {
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 0;
}
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);
} 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,
resource_size(&dev->resources[i]),
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 = resource_size(r); if (rlen < sizeof(struct i2s_interface_regs)) goto err;
dev->intfregs = ioremap(r->start, rlen);
r = &dev->resources[aoa_resource_txdbdma];
rlen = resource_size(r); if (rlen < sizeof(struct dbdma_regs)) goto err;
dev->out.dbdma = ioremap(r->start, rlen);
r = &dev->resources[aoa_resource_rxdbdma];
rlen = resource_size(r); 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"); if (dev->sound.ofdev.dev.kobj.state_initialized) {
soundbus_dev_put(&dev->sound); return 0;
} goto err;
}
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;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.