/* *TheVX855DMAdescriptor(usedfors/gtransfers)looks *likethis.
*/ struct viafb_vx855_dma_descr {
u32 addr_low; /* Low part of phys addr */
u32 addr_high; /* High 12 bits of addr */
u32 fb_offset; /* Offset into FB memory */
u32 seg_size; /* Size, 16-byte units */
u32 tile_mode; /* "tile mode" setting */
u32 next_desc_low; /* Next descriptor addr */
u32 next_desc_high;
u32 pad; /* Fill out to 64 bytes */
};
/* *Flagsaddedtothe"nextdescriptorlow"pointers
*/ #define VIAFB_DMA_MAGIC 0x01 /* ??? Just has to be there */ #define VIAFB_DMA_FINAL_SEGMENT 0x02 /* Final segment */
/* *ThecompletionIRQhandler.
*/ static irqreturn_t viafb_dma_irq(int irq, void *data)
{ int csr;
irqreturn_t ret = IRQ_NONE;
spin_lock(&global_dev.reg_lock);
csr = viafb_mmio_read(VDMA_CSR0); if (csr & VDMA_C_DONE) {
viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
complete(&viafb_dma_completion);
ret = IRQ_HANDLED;
}
spin_unlock(&global_dev.reg_lock); return ret;
}
/* *IndicateaneedforDMAfunctionality.
*/ int viafb_request_dma(void)
{ int ret = 0;
/* *OnlyVX855issupportedcurrently.
*/ if (global_dev.chip_type != UNICHROME_VX855) return -ENODEV; /* *Notethenewuserandsetupourinterrupthandler *ifneedbe.
*/
mutex_lock(&viafb_dma_lock);
viafb_dma_users++; if (viafb_dma_users == 1) {
ret = request_irq(global_dev.pdev->irq, viafb_dma_irq,
IRQF_SHARED, "via-dma", &viafb_dma_users); if (ret)
viafb_dma_users--; else
viafb_irq_enable(VDE_I_DMA0TDEN);
}
mutex_unlock(&viafb_dma_lock); return ret;
}
EXPORT_SYMBOL_GPL(viafb_request_dma);
/* Get the BIOS-configured framebuffer size from PCI configuration space
* of function 3 in the respective chipset */ staticint viafb_get_fb_size_from_pci(int chip_type)
{ int i;
u8 offset = 0;
u32 FBSize;
u32 VideoMemSize;
/* search for the "FUNCTION3" device in this chipset */ for (i = 0; i < ARRAY_SIZE(via_function3); i++) { struct pci_dev *pdev;
pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
NULL); if (!pdev) continue;
DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
switch (pdev->device) { case CLE266_FUNCTION3: case KM400_FUNCTION3:
offset = 0xE0; break; case CN400_FUNCTION3: case CN700_FUNCTION3: case CX700_FUNCTION3: case KM800_FUNCTION3: case KM890_FUNCTION3: case P4M890_FUNCTION3: case P4M900_FUNCTION3: case VX800_FUNCTION3: case VX855_FUNCTION3: case VX900_FUNCTION3: /*case CN750_FUNCTION3: */
offset = 0xA0; break;
}
/* *FigureoutandmapourMMIOregions.
*/ staticint via_pci_setup_mmio(struct viafb_dev *vdev)
{ int ret; /* *Hookuptothedeviceregisters.Notethatwesoldier *onifitfails;theframebuffercanoperate(without *acceleration)withoutthisregion.
*/
vdev->engine_start = pci_resource_start(vdev->pdev, 1);
vdev->engine_len = pci_resource_len(vdev->pdev, 1);
vdev->engine_mmio = ioremap(vdev->engine_start,
vdev->engine_len); if (vdev->engine_mmio == NULL)
dev_err(&vdev->pdev->dev, "Unable to map engine MMIO; operation will be " "slow and crippled.\n"); /* *Mapinframebuffermemory.Fornow,failurehereis *fatal.Unfortunately,intheabsenceofsignificant *vmallocspace,failurehereisalsoentirelyplausible. *Eventuallywewanttomoveawayfrommappingthis *entireregion.
*/ if (vdev->chip_type == UNICHROME_VX900)
vdev->fbmem_start = pci_resource_start(vdev->pdev, 2); else
vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); if (ret < 0) goto out_unmap;
/* try to map less memory on failure, 8 MB should be still enough */ for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len); if (vdev->fbmem) break;
}
if (vdev->fbmem == NULL) {
ret = -ENOMEM; goto out_unmap;
} return0;
out_unmap:
iounmap(vdev->engine_mmio); return ret;
}
staticint via_create_subdev(struct viafb_dev *vdev, struct viafb_subdev_info *info)
{ int ret;
info->platdev = platform_device_alloc(info->name, -1); if (!info->platdev) {
dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
info->name); return -ENOMEM;
}
info->platdev->dev.parent = &vdev->pdev->dev;
info->platdev->dev.platform_data = vdev;
ret = platform_device_add(info->platdev); if (ret) {
dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
info->name);
platform_device_put(info->platdev);
info->platdev = NULL;
} return ret;
}
staticint via_setup_subdevs(struct viafb_dev *vdev)
{ int i;
/* *Ignorereturnvalues.Evenifsomeofthedevices *failtobecreated,we'llstillbeabletousesome *oftherest.
*/ for (i = 0; i < N_SUBDEVS; i++)
via_create_subdev(vdev, viafb_subdevs + i); return0;
}
staticvoid via_teardown_subdevs(void)
{ int i;
for (i = 0; i < N_SUBDEVS; i++) if (viafb_subdevs[i].platdev) {
viafb_subdevs[i].platdev->dev.platform_data = NULL;
platform_device_unregister(viafb_subdevs[i].platdev);
}
}
/* Now bring back any subdevs */
mutex_lock(&viafb_pm_hooks_lock);
list_for_each_entry(hooks, &viafb_pm_hooks, list)
hooks->resume(hooks->private);
mutex_unlock(&viafb_pm_hooks_lock);
return0;
}
staticint via_pci_probe(struct pci_dev *pdev, conststruct pci_device_id *ent)
{ int ret;
ret = aperture_remove_conflicting_pci_devices(pdev, "viafb"); if (ret) return ret;
ret = pci_enable_device(pdev); if (ret) return ret;
if (fb_modesetting_disabled("viafb")) return -ENODEV;
ret = viafb_init(); if (ret) return ret;
viafb_i2c_init();
viafb_gpio_init();
ret = pci_register_driver(&via_driver); if (ret) {
viafb_gpio_exit();
viafb_i2c_exit(); return ret;
}
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.