summaryrefslogtreecommitdiff
path: root/linux-core/drm_vm.c
AgeCommit message (Expand)Author
2007-04-03Make sure CMA (Can't map aperture) pages are mapped uncached.Thomas Hellstrom
2007-03-24vm: cleanup drm_vm.c along lines of cleanups queued for kernelDave Airlie
2007-03-23cleanup more whitespace from ttm mergeDave Airlie
2007-02-26Fix build for 2.6.21-rc1.Thomas Hellstrom
2007-02-14Set the drm bus map type for each buffer object memory type.Thomas Hellstrom
2007-02-14Rework buffer object vm code to use nopfn() for kernels >= 2.6.19.Thomas Hellstrom
2007-02-10Various bugfixes.Thomas Hellstrom
2007-02-09Fix evict_mutex locking range.Thomas Hellstrom
2007-02-08Fix mm_block leak.Thomas Hellstrom
2007-02-08Simplify external ttm page allocation.Thomas Hellstrom
2007-02-07Fix a stray unlock_kernel() in drm_vm.cThomas Hellstrom
2007-02-06Simplify pci map vs no pci map choice.Thomas Hellstrom
2007-02-02Make also later kernels work with buffer object vmThomas Hellstrom
2007-02-02Make vm handle buffer objects instead of ttm objects.Thomas Hellstrom
2007-02-01Fix missing ttm_open_vma call from previous commit.Thomas Hellstrom
2007-02-01Protect drm_mmap against disappearing maps.Thomas Hellstrom
2007-01-08drm: remove drm_follow_page, and drm_ioremap and ioremapfreeChristoph Hellwig
2007-01-01make build against 2.6.20 hopefullyDave Airlie
2006-12-27Proper allocation of AGP pages for ttms.Thomas Hellstrom
2006-12-19Security fix. Zero pages before they are handed to user space.Thomas Hellstrom
2006-12-19drm: remove all 2.4 support for drm development tree.Dave Airlie
2006-12-19[SPARC]: Respect vm_page_prot in io_remap_page_range().Dave Airlie
2006-12-19[PATCH] mm: incorrect VM_FAULT_OOM returns from driversDave Airlie
2006-10-30Bugzilla Bug #8819Thomas Hellstrom
2006-10-20Bug #8707, 2.6.19-rc compatibility for memory manager code.Thomas Hellstrom
2006-10-18Merging drm-ttm-0-2-branchThomas Hellstrom
2006-10-17Add vma list memory usage to memory accounting.Thomas Hellstrom
2006-10-17Add memory usage accounting to avoid DOS problems.Thomas Hellstrom
2006-10-11Compatibility code for 2.6.15-2.6.18. It is ugly but a little comfort is thatThomas Hellstrom
2006-10-11Big update:Thomas Hellstrom
2006-10-10Use a nopage-based approach to fault in pfns.Thomas Hellstrom
2006-10-02Bug 6242: [mach64] Use private DMA buffers, part #3.George Sapountzis
2006-10-02Allow for 44 bit user-tokens (or drm_file offsets)Thomas Hellstrom
2006-09-27Adapt to architecture-specific hooks for gatt pages.Thomas Hellstrom
2006-09-14Remove the use of reserved pages, and use locked pages instead.Thomas Hellstrom
2006-09-12More bugfixes.Thomas Hellstrom
2006-08-30Buffer object mapping and mapping synchronization for multiple clients.Thomas Hellstrom
2006-08-28Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into drm-...Thomas Hellstrom
2006-08-28drm: lots of small cleanups and whitespace issues fixed upDave Airlie
2006-08-25Module protection map access is moving into mainline kernels.Thomas Hellstrom
2006-08-25Checkpoint commitThomas Hellstrom
2006-08-22More ttm cleanups.Thomas Hellstrom
2006-08-22Bring in stripped TTM functionality.Thomas Hellstrom
2006-07-24switch drm to use Linux mutexes instead of semaphore.Dave Airlie
2006-07-11Keep hashed user tokens, with the following changes:Thomas Hellstrom
2006-07-10Change drm Map handles to be arbitrary 32-bit hash tokens in the rangeThomas Hellstrom
2006-02-18major realigment of DRM CVS with kernel code, makes integration much easierDave Airlie
2005-11-29Fix from Hugh Dickins for consistent mappingDave Airlie
2005-08-20remove checks that make ppc64 not work properly... also fix ppc64 check..Dave Airlie
2005-08-16add Egberts 32/64 bit patch (its in kernel already...)Dave Airlie
ss="hl ppc">#include "nv50_crtc.h" #include "nv50_output.h" #include "nv50_connector.h" static int nv50_display_pre_init(struct nv50_display *display) { struct drm_device *dev = display->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; int i; uint32_t ram_amount; NV50_DEBUG("\n"); NV_WRITE(0x00610184, NV_READ(0x00614004)); /* * I think the 0x006101XX range is some kind of main control area that enables things. */ /* CRTC? */ NV_WRITE(0x00610190 + 0 * 0x10, NV_READ(0x00616100 + 0 * 0x800)); NV_WRITE(0x00610190 + 1 * 0x10, NV_READ(0x00616100 + 1 * 0x800)); NV_WRITE(0x00610194 + 0 * 0x10, NV_READ(0x00616104 + 0 * 0x800)); NV_WRITE(0x00610194 + 1 * 0x10, NV_READ(0x00616104 + 1 * 0x800)); NV_WRITE(0x00610198 + 0 * 0x10, NV_READ(0x00616108 + 0 * 0x800)); NV_WRITE(0x00610198 + 1 * 0x10, NV_READ(0x00616108 + 1 * 0x800)); NV_WRITE(0x0061019c + 0 * 0x10, NV_READ(0x0061610c + 0 * 0x800)); NV_WRITE(0x0061019c + 1 * 0x10, NV_READ(0x0061610c + 1 * 0x800)); /* DAC */ NV_WRITE(0x006101d0 + 0 * 0x4, NV_READ(0x0061a000 + 0 * 0x800)); NV_WRITE(0x006101d0 + 1 * 0x4, NV_READ(0x0061a000 + 1 * 0x800)); NV_WRITE(0x006101d0 + 2 * 0x4, NV_READ(0x0061a000 + 2 * 0x800)); /* SOR */ NV_WRITE(0x006101e0 + 0 * 0x4, NV_READ(0x0061c000 + 0 * 0x800)); NV_WRITE(0x006101e0 + 1 * 0x4, NV_READ(0x0061c000 + 1 * 0x800)); /* Something not yet in use, tv-out maybe. */ NV_WRITE(0x006101f0 + 0 * 0x4, NV_READ(0x0061e000 + 0 * 0x800)); NV_WRITE(0x006101f0 + 1 * 0x4, NV_READ(0x0061e000 + 1 * 0x800)); NV_WRITE(0x006101f0 + 2 * 0x4, NV_READ(0x0061e000 + 2 * 0x800)); for (i = 0; i < 3; i++) { NV_WRITE(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(i), 0x00550000 | NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING); NV_WRITE(NV50_PDISPLAY_DAC_REGS_CLK_CTRL1(i), 0x00000001); } /* This used to be in crtc unblank, but seems out of place there. */ NV_WRITE(NV50_PDISPLAY_UNK_380, 0); /* RAM is clamped to 256 MiB. */ ram_amount = nouveau_mem_fb_amount(display->dev); NV50_DEBUG("ram_amount %d\n", ram_amount); if (ram_amount > 256*1024*1024) ram_amount = 256*1024*1024; NV_WRITE(NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); NV_WRITE(NV50_PDISPLAY_UNK_388, 0x150000); NV_WRITE(NV50_PDISPLAY_UNK_38C, 0); display->preinit_done = true; return 0; } static int nv50_display_init(struct nv50_display *display) { struct drm_device *dev = display->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t val; NV50_DEBUG("\n"); /* The precise purpose is unknown, i suspect it has something to do with text mode. */ if (NV_READ(NV50_PDISPLAY_SUPERVISOR) & 0x100) { NV_WRITE(NV50_PDISPLAY_SUPERVISOR, 0x100); NV_WRITE(0x006194e8, NV_READ(0x006194e8) & ~1); while (NV_READ(0x006194e8) & 2); } /* taken from nv bug #12637 */ NV_WRITE(NV50_PDISPLAY_UNK200_CTRL, 0x2b00); do { val = NV_READ(NV50_PDISPLAY_UNK200_CTRL); if ((val & 0x9f0000) == 0x20000) NV_WRITE(NV50_PDISPLAY_UNK200_CTRL, val | 0x800000); if ((val & 0x3f0000) == 0x30000) NV_WRITE(NV50_PDISPLAY_UNK200_CTRL, val | 0x200000); } while (val & 0x1e0000); NV_WRITE(NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); NV_WRITE(NV50_PDISPLAY_UNK200_CTRL, 0x1000b03); while (!(NV_READ(NV50_PDISPLAY_UNK200_CTRL) & 0x40000000)); /* For the moment this is just a wrapper, which should be replaced with a real fifo at some point. */ OUT_MODE(NV50_UNK84, 0); OUT_MODE(NV50_UNK88, 0); OUT_MODE(NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK); OUT_MODE(NV50_CRTC0_UNK800, 0); OUT_MODE(NV50_CRTC0_DISPLAY_START, 0); OUT_MODE(NV50_CRTC0_UNK82C, 0); /* enable clock change interrupts. */ NV_WRITE(NV50_PDISPLAY_SUPERVISOR_INTR, NV_READ(NV50_PDISPLAY_SUPERVISOR_INTR) | 0x70); /* enable hotplug interrupts */ NV_WRITE(NV50_PCONNECTOR_HOTPLUG_INTR, 0x7FFF7FFF); display->init_done = true; return 0; } static int nv50_display_disable(struct nv50_display *display) { struct drm_device *dev = display->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_crtc *crtc = NULL; int i; NV50_DEBUG("\n"); list_for_each_entry(crtc, &display->crtcs, item) { crtc->blank(crtc, true); } display->update(display); /* Almost like ack'ing a vblank interrupt, maybe in the spirit of cleaning up? */ list_for_each_entry(crtc, &display->crtcs, item) { if (crtc->enabled) { uint32_t mask; if (crtc->index == 1) mask = NV50_PDISPLAY_SUPERVISOR_CRTC1; else mask = NV50_PDISPLAY_SUPERVISOR_CRTC0; NV_WRITE(NV50_PDISPLAY_SUPERVISOR, mask); while (!(NV_READ(NV50_PDISPLAY_SUPERVISOR) & mask)); } } NV_WRITE(NV50_PDISPLAY_UNK200_CTRL, 0); NV_WRITE(NV50_PDISPLAY_CTRL_STATE, 0); while ((NV_READ(NV50_PDISPLAY_UNK200_CTRL) & 0x1e0000) != 0); for (i = 0; i < 2; i++) { while (NV_READ(NV50_PDISPLAY_SOR_REGS_DPMS_STATE(i)) & NV50_PDISPLAY_SOR_REGS_DPMS_STATE_WAIT); } /* disable clock change interrupts. */ NV_WRITE(NV50_PDISPLAY_SUPERVISOR_INTR, NV_READ(NV50_PDISPLAY_SUPERVISOR_INTR) & ~0x70); /* disable hotplug interrupts */ NV_WRITE(NV50_PCONNECTOR_HOTPLUG_INTR, 0); display->init_done = false; return 0; } static int nv50_display_update(struct nv50_display *display) { struct drm_device *dev = display->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; NV50_DEBUG("\n"); OUT_MODE(NV50_UPDATE_DISPLAY, 0); return 0; } int nv50_display_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_display *display = kzalloc(sizeof(struct nv50_display), GFP_KERNEL); int i, type, output_index, bus; /* DAC0, DAC1, DAC2, SOR0, SOR1*/ int or_counter[5] = {0, 0, 0, 0, 0}; int i2c_index[5] = {0, 0, 0, 0, 0}; uint32_t bus_mask = 0; uint32_t bus_digital = 0, bus_analog = 0; NV50_DEBUG("\n"); if (!display) return -ENOMEM; INIT_LIST_HEAD(&display->crtcs); INIT_LIST_HEAD(&display->outputs); INIT_LIST_HEAD(&display->connectors); dev_priv->display_priv = display; for (i = 0; i < 2; i++) { nv50_crtc_create(dev, i); } /* we setup the outputs up from the BIOS table */ for (i = 0 ; i < dev_priv->dcb_table.entries; i++) { type = dev_priv->dcb_table.entry[i].type; output_index = ffs(dev_priv->dcb_table.entry[i].or) - 1; bus = dev_priv->dcb_table.entry[i].bus; switch (type) { case DCB_OUTPUT_TMDS: case DCB_OUTPUT_LVDS: or_counter[output_index + 3] += 1; i2c_index[output_index + 3] = dev_priv->dcb_table.entry[i].i2c_index; bus_digital |= (1 << bus); nv50_sor_create(dev, i); break; case DCB_OUTPUT_ANALOG: or_counter[output_index] += 1; i2c_index[output_index] = dev_priv->dcb_table.entry[i].i2c_index; bus_analog |= (1 << bus); nv50_dac_create(dev, i); break; default: break; } } /* setup the connectors based on the output tables. */ for (i = 0 ; i < dev_priv->dcb_table.entries; i++) { int connector_type = 0; type = dev_priv->dcb_table.entry[i].type; bus = dev_priv->dcb_table.entry[i].bus; /* already done? */ if (bus_mask & (1 << bus)) continue; /* only do it for supported outputs */ if (type != DCB_OUTPUT_ANALOG && type != DCB_OUTPUT_TMDS && type != DCB_OUTPUT_LVDS) continue; switch (type) { case DCB_OUTPUT_TMDS: case DCB_OUTPUT_ANALOG: if ((bus_digital & (1 << bus)) && (bus_analog & (1 << bus))) connector_type = CONNECTOR_DVI_I; else if (bus_digital & (1 << bus)) connector_type = CONNECTOR_DVI_D; else if (bus_analog & (1 << bus)) connector_type = CONNECTOR_VGA; break; case DCB_OUTPUT_LVDS: connector_type = CONNECTOR_LVDS; break; default: connector_type = CONNECTOR_UNKNOWN; break; } if (connector_type == CONNECTOR_UNKNOWN) continue; nv50_connector_create(dev, bus, dev_priv->dcb_table.entry[i].i2c_index, connector_type); bus_mask |= (1 << bus); } display->dev = dev; /* function pointers */ display->init = nv50_display_init; display->pre_init = nv50_display_pre_init; display->disable = nv50_display_disable; display->update = nv50_display_update; return 0; } int nv50_display_destroy(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_display *display = nv50_get_display(dev); struct nv50_crtc *crtc = NULL; struct nv50_output *output = NULL; struct nv50_connector *connector = NULL; NV50_DEBUG("\n"); if (display->init_done) display->disable(display); list_for_each_entry(connector, &display->connectors, item) { connector->destroy(connector); } list_for_each_entry(output, &display->outputs, item) { output->destroy(output); } list_for_each_entry(crtc, &display->crtcs, item) { crtc->destroy(crtc); } kfree(display); dev_priv->display_priv = NULL; return 0; } /* This can be replaced with a real fifo in the future. */ void nv50_display_command(struct drm_nouveau_private *dev_priv, uint32_t mthd, uint32_t val) { uint32_t counter = 0; #if 1 DRM_INFO("mthd 0x%03X val 0x%08X\n", mthd, val); #endif NV_WRITE(NV50_PDISPLAY_CTRL_VAL, val); NV_WRITE(NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_PENDING | 0x10000 | mthd | NV50_PDISPLAY_CTRL_STATE_ENABLE); while (NV_READ(NV50_PDISPLAY_CTRL_STATE) & NV50_PDISPLAY_CTRL_STATE_PENDING) { counter++; if (counter > 1000000) { DRM_ERROR("You probably need a reboot now\n"); break; } udelay(1); } } struct nv50_display *nv50_get_display(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; return (struct nv50_display *) dev_priv->display_priv; }