From 38835f9cd2b44cfb6587a52ba1bfe292b958d0e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 15:21:13 +1000 Subject: [PATCH 01/49] radeon command submission start take code from Jerome munge into a TTM IB re-use --- linux-core/Makefile.kernel | 2 +- linux-core/radeon_cs.c | 1 + linux-core/radeon_gem.c | 211 +++++++++++++++++++++++++++++++++---- linux-core/radeon_reg.h | 4 + shared-core/radeon_cp.c | 30 +++--- shared-core/radeon_cs.c | 181 +++++++++++++++++++++++++++++++ shared-core/radeon_drm.h | 15 +++ shared-core/radeon_drv.h | 56 +++++++--- shared-core/radeon_state.c | 1 + 9 files changed, 450 insertions(+), 51 deletions(-) create mode 120000 linux-core/radeon_cs.c create mode 100644 shared-core/radeon_cs.c diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index d3668dfb..404944bf 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -41,7 +41,7 @@ nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nv50_kms_wrapper.o \ nv50_fbcon.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o radeon_gem.o \ - radeon_buffer.o radeon_fence.o atom.o radeon_display.o radeon_atombios.o radeon_i2c.o radeon_connectors.o \ + radeon_buffer.o radeon_fence.o atom.o radeon_display.o radeon_atombios.o radeon_i2c.o radeon_connectors.o radeon_cs.o \ atombios_crtc.o radeon_encoders.o radeon_fb.o radeon_combios.o sis-objs := sis_drv.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o diff --git a/linux-core/radeon_cs.c b/linux-core/radeon_cs.c new file mode 120000 index 00000000..0e3fa8ee --- /dev/null +++ b/linux-core/radeon_cs.c @@ -0,0 +1 @@ +../shared-core/radeon_cs.c \ No newline at end of file diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index d536aed2..021bb9f9 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -27,6 +27,9 @@ #include "radeon_drm.h" #include "radeon_drv.h" +static int radeon_gem_ib_init(struct drm_device *dev); +static int radeon_gem_ib_destroy(struct drm_device *dev); + int radeon_gem_init_object(struct drm_gem_object *obj) { struct drm_radeon_gem_object *obj_priv; @@ -513,19 +516,19 @@ static int radeon_gart_init(struct drm_device *dev) ret = drm_buffer_object_create(dev, RADEON_PCIGART_TABLE_SIZE, drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, - 0, 1, 0, &dev_priv->mm.pcie_table); + 0, 1, 0, &dev_priv->mm.pcie_table.bo); if (ret) return -EINVAL; - DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table, dev_priv->mm.pcie_table->offset); - ret = drm_bo_kmap(dev_priv->mm.pcie_table, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, - &dev_priv->mm.pcie_table_map); + DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset); + ret = drm_bo_kmap(dev_priv->mm.pcie_table.bo, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, + &dev_priv->mm.pcie_table.kmap); if (ret) return -EINVAL; dev_priv->pcigart_offset_set = 2; - dev_priv->gart_info.bus_addr = dev_priv->fb_location + dev_priv->mm.pcie_table->offset; - dev_priv->gart_info.addr = dev_priv->mm.pcie_table_map.virtual; + dev_priv->gart_info.bus_addr = dev_priv->fb_location + dev_priv->mm.pcie_table.bo->offset; + dev_priv->gart_info.addr = dev_priv->mm.pcie_table.kmap.virtual; dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB; memset(dev_priv->gart_info.addr, 0, RADEON_PCIGART_TABLE_SIZE); @@ -566,14 +569,14 @@ int radeon_alloc_gart_objects(struct drm_device *dev) drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, - 0, 1, 0, &dev_priv->mm.ring); + 0, 1, 0, &dev_priv->mm.ring.bo); if (ret) { DRM_ERROR("failed to allocate ring\n"); return -EINVAL; } - ret = drm_bo_kmap(dev_priv->mm.ring, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT, - &dev_priv->mm.ring_map); + ret = drm_bo_kmap(dev_priv->mm.ring.bo, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT, + &dev_priv->mm.ring.kmap); if (ret) { DRM_ERROR("failed to map ring\n"); return -EINVAL; @@ -583,24 +586,26 @@ int radeon_alloc_gart_objects(struct drm_device *dev) drm_bo_type_kernel, DRM_BO_FLAG_WRITE |DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, - 0, 1, 0, &dev_priv->mm.ring_read_ptr); + 0, 1, 0, &dev_priv->mm.ring_read.bo); if (ret) { DRM_ERROR("failed to allocate ring read\n"); return -EINVAL; } - ret = drm_bo_kmap(dev_priv->mm.ring_read_ptr, 0, + ret = drm_bo_kmap(dev_priv->mm.ring_read.bo, 0, PAGE_SIZE >> PAGE_SHIFT, - &dev_priv->mm.ring_read_ptr_map); + &dev_priv->mm.ring_read.kmap); if (ret) { DRM_ERROR("failed to map ring read\n"); return -EINVAL; } DRM_DEBUG("Ring ptr %p mapped at %d %p, read ptr %p maped at %d %p\n", - dev_priv->mm.ring, dev_priv->mm.ring->offset, dev_priv->mm.ring_map.virtual, - dev_priv->mm.ring_read_ptr, dev_priv->mm.ring_read_ptr->offset, dev_priv->mm.ring_read_ptr_map.virtual); + dev_priv->mm.ring.bo, dev_priv->mm.ring.bo->offset, dev_priv->mm.ring.kmap.virtual, + dev_priv->mm.ring_read.bo, dev_priv->mm.ring_read.bo->offset, dev_priv->mm.ring_read.kmap.virtual); + /* init the indirect buffers */ + radeon_gem_ib_init(dev); return 0; } @@ -634,6 +639,8 @@ int radeon_gem_mm_init(struct drm_device *dev) ret = radeon_alloc_gart_objects(dev); if (ret) return -EINVAL; + + return 0; } @@ -641,16 +648,19 @@ void radeon_gem_mm_fini(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; + radeon_gem_ib_destroy(dev); + mutex_lock(&dev->struct_mutex); - if (dev_priv->mm.ring_read_ptr) { - drm_bo_kunmap(&dev_priv->mm.ring_read_ptr_map); - drm_bo_usage_deref_locked(&dev_priv->mm.ring_read_ptr); + + if (dev_priv->mm.ring_read.bo) { + drm_bo_kunmap(&dev_priv->mm.ring_read.kmap); + drm_bo_usage_deref_locked(&dev_priv->mm.ring_read.bo); } - if (dev_priv->mm.ring) { - drm_bo_kunmap(&dev_priv->mm.ring_map); - drm_bo_usage_deref_locked(&dev_priv->mm.ring); + if (dev_priv->mm.ring.bo) { + drm_bo_kunmap(&dev_priv->mm.ring.kmap); + drm_bo_usage_deref_locked(&dev_priv->mm.ring.bo); } if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) { @@ -658,9 +668,9 @@ void radeon_gem_mm_fini(struct drm_device *dev) } if (dev_priv->flags & RADEON_IS_PCIE) { - if (dev_priv->mm.pcie_table) { - drm_bo_kunmap(&dev_priv->mm.pcie_table_map); - drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table); + if (dev_priv->mm.pcie_table.bo) { + drm_bo_kunmap(&dev_priv->mm.pcie_table.kmap); + drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table.bo); } } @@ -685,3 +695,158 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, return ret; } +#define RADEON_IB_MEMORY (1*1024*1024) +#define RADEON_IB_SIZE (65536) + +#define RADEON_NUM_IB (RADEON_IB_MEMORY / RADEON_IB_SIZE) + +int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords) +{ + int i, index = -1; + int ret; + drm_radeon_private_t *dev_priv = dev->dev_private; + + for (i = 0; i < RADEON_NUM_IB; i++) { + if (!(dev_priv->ib_alloc_bitmap & (1 << i))){ + index = i; + break; + } + } + + /* if all in use we need to wait */ + if (index == -1) { + for (i = 0; i < RADEON_NUM_IB; i++) { + if (dev_priv->ib_alloc_bitmap & (1 << i)) { + mutex_lock(&dev_priv->ib_objs[i]->bo->mutex); + ret = drm_bo_wait(dev_priv->ib_objs[i]->bo, 0, 1, 0, 0); + mutex_unlock(&dev_priv->ib_objs[i]->bo->mutex); + if (ret) + continue; + dev_priv->ib_alloc_bitmap &= ~(1 << i); + index = i; + break; + } + } + } + + if (index == -1) { + DRM_ERROR("Major case fail to allocate IB from freelist %x\n", dev_priv->ib_alloc_bitmap); + return -EINVAL; + } + + + if (dwords > RADEON_IB_SIZE / sizeof(uint32_t)) + return -EINVAL; + + *ib = dev_priv->ib_objs[index]->kmap.virtual; + dev_priv->ib_alloc_bitmap |= (1 << i); + return 0; +} + +static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_fence_object *fence; + int ret; + int i; + RING_LOCALS; + + for (i = 0; i < RADEON_NUM_IB; i++) { + + if (dev_priv->ib_objs[i]->kmap.virtual == ib) { + ret = drm_bo_do_validate(dev_priv->ib_objs[i]->bo, 0, + DRM_BO_FLAG_NO_EVICT, + 0, 0, NULL); + if (ret) + DRM_ERROR("FAiled to validate\n"); + + DRM_DEBUG("validated IB %x, %d\n", dev_priv->ib_objs[i]->bo->offset, dwords); + BEGIN_RING(4); + + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(dev_priv->gart_vm_start + dev_priv->ib_objs[i]->bo->offset); + OUT_RING(dwords); + OUT_RING(CP_PACKET2()); + + ADVANCE_RING(); + + COMMIT_RING(); + + /* emit a fence object */ + ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); + if (ret) { + + drm_putback_buffer_objects(dev); + } + /* dereference the fence object */ + if (fence) + drm_fence_usage_deref_unlocked(&fence); + } + } + +} + +static int radeon_gem_ib_destroy(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int i; + + if (dev_priv->ib_objs) { + for (i = 0; i < RADEON_NUM_IB; i++) { + if (dev_priv->ib_objs[i]) { + drm_bo_kunmap(&dev_priv->ib_objs[i]->kmap); + drm_bo_usage_deref_unlocked(&dev_priv->ib_objs[i]->bo); + } + drm_free(dev_priv->ib_objs[i], sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); + } + drm_free(dev_priv->ib_objs, RADEON_NUM_IB*sizeof(struct radeon_mm_obj *), DRM_MEM_DRIVER); + } + dev_priv->ib_objs = NULL; + return 0; +} + +/* allocate 1MB of 64k IBs the the kernel can keep mapped */ +static int radeon_gem_ib_init(struct drm_device *dev) +{ + + drm_radeon_private_t *dev_priv = dev->dev_private; + int i; + int ret; + + dev_priv->ib_objs = drm_calloc(RADEON_NUM_IB, sizeof(struct radeon_mm_obj *), DRM_MEM_DRIVER); + if (!dev_priv->ib_objs) + goto free_all; + + for (i = 0; i < RADEON_NUM_IB; i++) { + dev_priv->ib_objs[i] = drm_calloc(1, sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); + if (!dev_priv->ib_objs[i]) + goto free_all; + + ret = drm_buffer_object_create(dev, RADEON_IB_SIZE, + drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_MAPPABLE, 0, + 0, 0, &dev_priv->ib_objs[i]->bo); + if (ret) + goto free_all; + + ret = drm_bo_kmap(dev_priv->ib_objs[i]->bo, 0, RADEON_IB_SIZE >> PAGE_SHIFT, + &dev_priv->ib_objs[i]->kmap); + + if (ret) + goto free_all; + } + + dev_priv->ib_alloc_bitmap = 0; + + dev_priv->cs.ib_get = radeon_gem_ib_get; + dev_priv->cs.ib_free = radeon_gem_ib_free; + + radeon_cs_init(dev); + return 0; + +free_all: + radeon_gem_ib_destroy(dev); + return -ENOMEM; +} + diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index 9b6bf1ec..a5be6a63 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -3086,6 +3086,10 @@ # define RADEON_CSQ_PRIPIO_INDBM (3 << 28) # define RADEON_CSQ_PRIBM_INDBM (4 << 28) # define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) + +#define R300_CP_RESYNC_ADDR 0x778 +#define R300_CP_RESYNC_DATA 0x77c + #define RADEON_CP_CSQ_STAT 0x07f8 # define RADEON_CSQ_RPTR_PRIMARY_MASK (0xff << 0) # define RADEON_CSQ_WPTR_PRIMARY_MASK (0xff << 8) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 80951e91..46f4290a 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -658,8 +658,8 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, ((dev_priv->gart_vm_start - 1) & 0xffff0000) | (dev_priv->fb_location >> 16)); - if (dev_priv->mm.ring) { - ring_start = dev_priv->mm.ring->offset + + if (dev_priv->mm.ring.bo) { + ring_start = dev_priv->mm.ring.bo->offset + dev_priv->gart_vm_start; } else #if __OS_HAS_AGP @@ -692,9 +692,9 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, dev_priv->ring.tail = cur_read_ptr; - if (dev_priv->mm.ring_read_ptr) { + if (dev_priv->mm.ring_read.bo) { RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, - dev_priv->mm.ring_read_ptr->offset + + dev_priv->mm.ring_read.bo->offset + dev_priv->gart_vm_start); } else #if __OS_HAS_AGP @@ -745,9 +745,9 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR) + RADEON_SCRATCH_REG_OFFSET); - if (dev_priv->mm.ring_read_ptr) + if (dev_priv->mm.ring_read.bo) dev_priv->scratch = ((__volatile__ u32 *) - dev_priv->mm.ring_read_ptr_map.virtual + + dev_priv->mm.ring_read.kmap.virtual + (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); else dev_priv->scratch = ((__volatile__ u32 *) @@ -772,12 +772,18 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, radeon_do_wait_for_idle(dev_priv); /* Sync everything up */ + if (dev_priv->chip_family > CHIP_RV280) { RADEON_WRITE(RADEON_ISYNC_CNTL, (RADEON_ISYNC_ANY2D_IDLE3D | RADEON_ISYNC_ANY3D_IDLE2D | RADEON_ISYNC_WAIT_IDLEGUI | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); - + } else { + RADEON_WRITE(RADEON_ISYNC_CNTL, + (RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI)); + } } static void radeon_test_writeback(drm_radeon_private_t * dev_priv) @@ -785,8 +791,8 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv) u32 tmp; void *ring_read_ptr; - if (dev_priv->mm.ring_read_ptr) - ring_read_ptr = dev_priv->mm.ring_read_ptr_map.virtual; + if (dev_priv->mm.ring_read.bo) + ring_read_ptr = dev_priv->mm.ring_read.kmap.virtual; else ring_read_ptr = dev_priv->ring_rptr->handle; @@ -2282,8 +2288,8 @@ int radeon_modeset_cp_init(struct drm_device *dev) dev_priv->ring.size = RADEON_DEFAULT_RING_SIZE; dev_priv->cp_mode = RADEON_CSQ_PRIBM_INDBM; - dev_priv->ring.start = (u32 *)(void *)(unsigned long)dev_priv->mm.ring_map.virtual; - dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring_map.virtual + + dev_priv->ring.start = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual; + dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual + dev_priv->ring.size / sizeof(u32); dev_priv->ring.size_l2qw = drm_order(dev_priv->ring.size / 8); dev_priv->ring.rptr_update = 4096; @@ -2297,7 +2303,7 @@ int radeon_modeset_cp_init(struct drm_device *dev) radeon_cp_load_microcode(dev_priv); - DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring->offset, dev_priv->mm.ring_read_ptr->offset); + DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring.bo->offset, dev_priv->mm.ring_read.bo->offset); radeon_cp_init_ring_buffer(dev, dev_priv); diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c new file mode 100644 index 00000000..61fef79d --- /dev/null +++ b/shared-core/radeon_cs.c @@ -0,0 +1,181 @@ +/* + * Copyright 2008 Jerome Glisse. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jerome Glisse + */ +#include "drmP.h" +#include "radeon_drm.h" +#include "radeon_drv.h" +#include "r300_reg.h" + +int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) +{ + struct drm_radeon_private *radeon = dev->dev_private; + struct drm_radeon_cs *cs = data; + uint32_t *packets = NULL; + uint32_t cs_id; + void *ib = NULL; + long size; + int r; + + /* set command stream id to 0 which is fake id */ + cs_id = 0; + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + + if (radeon == NULL) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + if (!cs->dwords) { + return 0; + } + /* limit cs to 64K ib */ + if (cs->dwords > (16 * 1024)) { + return -EINVAL; + } + /* copy cs from userspace maybe we should copy into ib to save + * one copy but ib will be mapped wc so not good for cmd checking + * somethings worth testing i guess (Jerome) + */ + size = cs->dwords * sizeof(uint32_t); + packets = drm_alloc(size, DRM_MEM_DRIVER); + if (packets == NULL) { + return -ENOMEM; + } + if (DRM_COPY_FROM_USER(packets, (void __user *)(unsigned long)cs->packets, size)) { + r = -EFAULT; + goto out; + } + /* get ib */ + r = radeon->cs.ib_get(dev, &ib, cs->dwords); + if (r) { + goto out; + } + + /* now parse command stream */ + r = radeon->cs.parse(dev, ib, packets, cs->dwords); + if (r) { + goto out; + } + + /* emit cs id sequence */ + radeon->cs.id_emit(dev, &cs_id); + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); +out: + radeon->cs.ib_free(dev, ib, cs->dwords); + drm_free(packets, size, DRM_MEM_DRIVER); + return r; +} + +int radeon_cs_parse(struct drm_device *dev, void *ib, + uint32_t *packets, uint32_t dwords) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + volatile int rb; + + /* copy the packet into the IB */ + memcpy(ib, packets, dwords * sizeof(uint32_t)); + + /* read back last byte to flush WC buffers */ + rb = readl((ib + (dwords-1) * sizeof(uint32_t))); + + return 0; +} + +uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon) +{ + /* FIXME: protect with a spinlock */ + /* FIXME: check if wrap affect last reported wrap & sequence */ + radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF; + if (!radeon->cs.id_scnt) { + /* increment wrap counter */ + radeon->cs.id_wcnt += 0x01000000; + /* valid sequence counter start at 1 */ + radeon->cs.id_scnt = 1; + } + return (radeon->cs.id_scnt | radeon->cs.id_wcnt); +} + +void r100_cs_id_emit(struct drm_device *dev, uint32_t *id) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + /* ISYNC_CNTL should have CPSCRACTH bit set */ + *id = radeon_cs_id_get(dev_priv); + /* emit id in SCRATCH4 (not used yet in old drm) */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0)); + OUT_RING(*id); + ADVANCE_RING(); +} + +void r300_cs_id_emit(struct drm_device *dev, uint32_t *id) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + /* ISYNC_CNTL should not have CPSCRACTH bit set */ + *id = radeon_cs_id_get(dev_priv); + /* emit id in SCRATCH6 */ + BEGIN_RING(6); + OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0)); + OUT_RING(6); + OUT_RING(CP_PACKET0(R300_CP_RESYNC_DATA, 0)); + OUT_RING(*id); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FINISH); + ADVANCE_RING(); +} + +uint32_t r100_cs_id_last_get(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + return RADEON_READ(RADEON_SCRATCH_REG4); +} + +uint32_t r300_cs_id_last_get(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + return RADEON_READ(RADEON_SCRATCH_REG6); +} + +int radeon_cs_init(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (dev_priv->chip_family < CHIP_RV280) { + dev_priv->cs.id_emit = r100_cs_id_emit; + dev_priv->cs.id_last_get = r100_cs_id_last_get; + } else if (dev_priv->chip_family < CHIP_R600) { + dev_priv->cs.id_emit = r300_cs_id_emit; + dev_priv->cs.id_last_get = r300_cs_id_last_get; + } + + dev_priv->cs.parse = radeon_cs_parse; + /* ib get depends on memory manager or not so memory manager */ + return 0; +} diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 7fcf9305..c20de561 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -506,6 +506,7 @@ typedef struct { #define DRM_RADEON_GEM_SET_DOMAIN 0x23 #define DRM_RADEON_GEM_INDIRECT 0x24 // temporary for X server +#define DRM_RADEON_CS 0x25 #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) @@ -545,6 +546,7 @@ typedef struct { #define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain) #define DRM_IOCTL_RADEON_GEM_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INDIRECT, struct drm_radeon_gem_indirect) +#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) typedef struct drm_radeon_init { @@ -861,4 +863,17 @@ struct drm_radeon_gem_indirect { uint32_t used; }; +/* New interface which obsolete all previous interface. + */ + + +struct drm_radeon_cs { +// uint32_t __user *packets; + uint32_t dwords; + uint32_t cs_id; + uint64_t packets; + +}; + + #endif diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index b8f49404..c431fe4a 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -195,11 +195,11 @@ enum radeon_mac_model { #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ - (dev_priv->mm.ring_read_ptr ? readl(dev_priv->mm.ring_read_ptr_map.virtual + 0) : DRM_READ32((dev_priv)->ring_rptr, 0 )) : \ + (dev_priv->mm.ring_read.bo ? readl(dev_priv->mm.ring_read.kmap.virtual + 0) : DRM_READ32((dev_priv)->ring_rptr, 0 )) : \ RADEON_READ(RADEON_CP_RB_RPTR)) -#define SET_RING_HEAD(dev_priv,val) (dev_priv->mm.ring_read_ptr ? \ - writel((val), dev_priv->mm.ring_read_ptr_map.virtual) : \ +#define SET_RING_HEAD(dev_priv,val) (dev_priv->mm.ring_read.bo ? \ + writel((val), dev_priv->mm.ring_read.kmap.virtual) : \ DRM_WRITE32((dev_priv)->ring_rptr, 0, (val))) typedef struct drm_radeon_freelist { @@ -261,6 +261,11 @@ struct radeon_virt_surface { struct drm_file *file_priv; }; +struct radeon_mm_obj { + struct drm_buffer_object *bo; + struct drm_bo_kmap_obj kmap; +}; + struct radeon_mm_info { uint64_t vram_offset; // Offset into GPU space uint64_t vram_size; @@ -268,15 +273,10 @@ struct radeon_mm_info { uint64_t gart_start; uint64_t gart_size; - - struct drm_buffer_object *pcie_table; - struct drm_bo_kmap_obj pcie_table_map; - - struct drm_buffer_object *ring; - struct drm_bo_kmap_obj ring_map; - - struct drm_buffer_object *ring_read_ptr; - struct drm_bo_kmap_obj ring_read_ptr_map; + + struct radeon_mm_obj pcie_table; + struct radeon_mm_obj ring; + struct radeon_mm_obj ring_read; }; #include "radeon_mode.h" @@ -286,6 +286,25 @@ struct drm_radeon_master_private { drm_radeon_sarea_t *sarea_priv; }; +/* command submission struct */ +struct drm_radeon_cs_priv { + uint32_t id_wcnt; + uint32_t id_scnt; + uint32_t id_last_wcnt; + uint32_t id_last_scnt; + + int (*parse)(struct drm_device *dev, void *ib, + uint32_t *packets, uint32_t dwords); + void (*id_emit)(struct drm_device *dev, uint32_t *id); + uint32_t (*id_last_get)(struct drm_device *dev); + /* this ib handling callback are for hidding memory manager drm + * from memory manager less drm, free have to emit ib discard + * sequence into the ring */ + int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords); + uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib); + void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords); +}; + typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; @@ -392,7 +411,11 @@ typedef struct drm_radeon_private { u32 ram_width; enum radeon_pll_errata pll_errata; - + + struct radeon_mm_obj **ib_objs; + /* ib bitmap */ + uint64_t ib_alloc_bitmap; // TO DO replace with a real bitmap + struct drm_radeon_cs_priv cs; } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { @@ -669,14 +692,15 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, #define RADEON_SCRATCH_REG3 0x15ec #define RADEON_SCRATCH_REG4 0x15f0 #define RADEON_SCRATCH_REG5 0x15f4 +#define RADEON_SCRATCH_REG6 0x15f8 #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 #define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) #define GET_SCRATCH( x ) (dev_priv->writeback_works ? \ - (dev_priv->mm.ring_read_ptr ? \ - readl(dev_priv->mm.ring_read_ptr_map.virtual + RADEON_SCRATCHOFF(0)) : \ + (dev_priv->mm.ring_read.bo ? \ + readl(dev_priv->mm.ring_read.kmap.virtual + RADEON_SCRATCHOFF(0)) : \ DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(x))) : \ RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x))) @@ -1593,4 +1617,6 @@ extern void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on); extern int radeon_master_create(struct drm_device *dev, struct drm_master *master); extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master); extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master); +extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv); +extern int radeon_cs_init(struct drm_device *dev); #endif /* __RADEON_DRV_H__ */ diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 6de4b135..d56dac19 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3279,6 +3279,7 @@ struct drm_ioctl_desc radeon_ioctls[] = { DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_GEM_INDIRECT, radeon_gem_indirect_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), }; int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); From dc3a7c023dd089150ee2dc40755fde348252bedb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 17:27:24 +1000 Subject: [PATCH 02/49] r300: initial command stream parser for packet 0. this at least parses the DDX stream and lets me run gnome-terminal/metacity --- linux-core/radeon_reg.h | 1 + shared-core/r300_cmdbuf.c | 48 +++++++++++++++++++++++-- shared-core/radeon_cp.c | 2 ++ shared-core/radeon_cs.c | 73 +++++++++++++++++++++++++++++++++++++++ shared-core/radeon_drv.h | 7 ++++ 5 files changed, 128 insertions(+), 3 deletions(-) diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index a5be6a63..784b3b50 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -3125,6 +3125,7 @@ # define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 # define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) # define RADEON_CP_PACKET0_REG_MASK 0x000007ff +# define R300_CP_PACKET0_REG_MASK 0x00001fff # define RADEON_CP_PACKET1_REG0_MASK 0x000007ff # define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index e8f18dbc..f4111554 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -151,8 +151,6 @@ void r300_init_reg_flags(struct drm_device *dev) for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\ r300_reg_flags[i]|=(mark); -#define MARK_SAFE 1 -#define MARK_CHECK_OFFSET 2 #define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE) @@ -234,6 +232,11 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8); ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); + ADD_RANGE(R500_SU_REG_DEST, 1); + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV410) { + ADD_RANGE(R300_DST_PIPE_CONFIG, 1); + } + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { ADD_RANGE(R500_VAP_INDEX_OFFSET, 1); ADD_RANGE(R500_US_CONFIG, 2); @@ -243,6 +246,8 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R500_RS_INST_0, 16); ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2); ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2); + + ADD_RANGE(R500_GA_US_VECTOR_INDEX, 2); } else { ADD_RANGE(R300_PFS_CNTL_0, 3); ADD_RANGE(R300_PFS_NODE_0, 4); @@ -255,9 +260,39 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R300_RS_ROUTE_0, 8); } + + /* add 2d blit engine registers for DDX */ + ADD_RANGE(RADEON_SRC_Y_X, 3); /* 1434, 1438, 143c, + SRC_Y_X, DST_Y_X, DST_HEIGHT_WIDTH + */ + ADD_RANGE(RADEON_DP_GUI_MASTER_CNTL, 1); /* 146c */ + ADD_RANGE(RADEON_DP_BRUSH_BKGD_CLR, 2); /* 1478, 147c */ + ADD_RANGE(RADEON_DP_SRC_FRGD_CLR, 2); /* 15d8, 15dc */ + ADD_RANGE(RADEON_DP_CNTL, 1); /* 16c0 */ + ADD_RANGE(RADEON_DP_WRITE_MASK, 1); /* 16cc */ + ADD_RANGE(RADEON_DEFAULT_SC_BOTTOM_RIGHT, 1); /* 16e8 */ + + ADD_RANGE(RADEON_DSTCACHE_CTLSTAT, 1); + ADD_RANGE(RADEON_WAIT_UNTIL, 1); + + ADD_RANGE_MARK(RADEON_DST_OFFSET, 1, MARK_CHECK_OFFSET); + ADD_RANGE_MARK(RADEON_SRC_OFFSET, 1, MARK_CHECK_OFFSET); + + ADD_RANGE_MARK(RADEON_DST_PITCH_OFFSET, 1, MARK_CHECK_OFFSET); + ADD_RANGE_MARK(RADEON_SRC_PITCH_OFFSET, 1, MARK_CHECK_OFFSET); + + /* TODO SCISSOR */ + ADD_RANGE_MARK(R300_SC_SCISSOR0, 2, MARK_CHECK_SCISSOR); + + ADD_RANGE(R300_SC_CLIP_0_A, 2); + ADD_RANGE(R300_SC_CLIP_RULE, 1); + ADD_RANGE(R300_SC_SCREENDOOR, 1); + + ADD_RANGE(R300_VAP_PVS_CODE_CNTL_0, 4); + ADD_RANGE(R300_VAP_PVS_VECTOR_INDX_REG, 2); } -static __inline__ int r300_check_range(unsigned reg, int count) +int r300_check_range(unsigned reg, int count) { int i; if (reg & ~0xffff) @@ -268,6 +303,13 @@ static __inline__ int r300_check_range(unsigned reg, int count) return 0; } +int r300_get_reg_flags(unsigned reg) +{ + if (reg & ~0xffff) + return -1; + return r300_reg_flags[(reg >> 2)]; +} + static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * dev_priv, drm_radeon_kcmd_buffer_t diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 46f4290a..48f72ab0 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -2301,6 +2301,8 @@ int radeon_modeset_cp_init(struct drm_device *dev) dev_priv->new_memmap = 1; + r300_init_reg_flags(dev); + radeon_cp_load_microcode(dev_priv); DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring.bo->offset, dev_priv->mm.ring_read.bo->offset); diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 61fef79d..8c2aea89 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -88,11 +88,84 @@ out: return r; } +int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, + uint32_t offset_dw) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int hdr = packets[offset_dw]; + int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; + int need_reloc = 0; + int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + int count_dw = 1; + int ret; + + while (count_dw < num_dw) { + /* need to have something like the r300 validation here - + list of allowed registers */ + int flags; + + ret = r300_check_range(reg, 1); + switch(ret) { + case -1: + DRM_ERROR("Illegal register %x\n", reg); + break; + case 0: + break; + case 1: + flags = r300_get_reg_flags(reg); + if (flags == MARK_CHECK_OFFSET) + DRM_DEBUG("need to relocate %x %d\n", reg, flags); + else if (flags == MARK_CHECK_SCISSOR) { + DRM_DEBUG("need to validate scissor %x %d\n", reg, flags); + } else { + DRM_DEBUG("illegal register %x %d\n", reg, flags); + return -EINVAL; + } + break; + } + count_dw++; + reg += 4; + } + return 0; +} + int radeon_cs_parse(struct drm_device *dev, void *ib, uint32_t *packets, uint32_t dwords) { drm_radeon_private_t *dev_priv = dev->dev_private; volatile int rb; + int size_dw = dwords; + /* scan the packet for various things */ + int count_dw = 0; + int ret = 0; + + while (count_dw < size_dw && ret == 0) { + int hdr = packets[count_dw]; + int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; + int reg; + + switch (hdr & RADEON_CP_PACKET_MASK) { + case RADEON_CP_PACKET0: + ret = radeon_cs_packet0(dev, packets, count_dw); + break; + case RADEON_CP_PACKET1: + case RADEON_CP_PACKET2: + reg = hdr & RADEON_CP_PACKET0_REG_MASK; + DRM_DEBUG("Packet 1/2: %d %x\n", num_dw, reg); + break; + + case RADEON_CP_PACKET3: + reg = hdr & 0xff00; + DRM_DEBUG("Packet 3: %d %x\n", num_dw, reg); + break; + } + + count_dw += num_dw+2; + } + + if (ret) + return ret; + /* copy the packet into the IB */ memcpy(ib, packets, dwords * sizeof(uint32_t)); diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index c431fe4a..232102d5 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -1619,4 +1619,11 @@ extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *mas extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master); extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv); extern int radeon_cs_init(struct drm_device *dev); + +#define MARK_SAFE 1 +#define MARK_CHECK_OFFSET 2 +#define MARK_CHECK_SCISSOR 3 + +extern int r300_check_range(unsigned reg, int count); +extern int r300_get_reg_flags(unsigned reg); #endif /* __RADEON_DRV_H__ */ From 87520347b45e2f40a2d84831538a38d6a8d92439 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 17:42:53 +1000 Subject: [PATCH 03/49] r300: add some packet 3 decodes --- shared-core/radeon_cs.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 8c2aea89..00860c2e 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -156,7 +156,25 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, case RADEON_CP_PACKET3: reg = hdr & 0xff00; - DRM_DEBUG("Packet 3: %d %x\n", num_dw, reg); + + switch(reg) { + case RADEON_CNTL_HOSTDATA_BLT: + case RADEON_CNTL_BITBLT_MULTI: + case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ + case RADEON_CP_INDX_BUFFER: + DRM_ERROR("need relocate packet 3 for %x\n", reg); + break; + + case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ + case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ + case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ + case RADEON_WAIT_FOR_IDLE: + case RADEON_CP_NOP: + break; + default: + DRM_ERROR("unknown packet 3 %x\n", reg); + ret = -EINVAL; + } break; } From 42e373e903d960b38c605229ab102933b18cff73 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 18:18:28 +1000 Subject: [PATCH 04/49] radeon_cs: extract some offsets from packet data --- shared-core/radeon_cs.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 00860c2e..5cfe85be 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -88,6 +88,31 @@ out: return r; } +static __inline__ int radeon_cs_check_offset(struct drm_device *dev, + uint32_t reg, uint32_t val) +{ + uint32_t offset; + + switch(reg) { + case RADEON_DST_PITCH_OFFSET: + case RADEON_SRC_PITCH_OFFSET: + offset = val & ((1 << 22) - 1); + offset <<= 10; + break; + case R300_RB3D_COLOROFFSET0: + case R300_RB3D_DEPTHOFFSET: + offset = val; + break; + case R300_TX_OFFSET_0: + case R300_TX_OFFSET_0+4: + offset = val & 0xffffffe0; + break; + } + + DRM_ERROR("Offset check %x %x\n", reg, offset); + return 0; +} + int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, uint32_t offset_dw) { @@ -113,9 +138,11 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, break; case 1: flags = r300_get_reg_flags(reg); - if (flags == MARK_CHECK_OFFSET) + if (flags == MARK_CHECK_OFFSET) { + radeon_cs_check_offset(dev, reg, packets[offset_dw+count_dw]); + DRM_DEBUG("need to relocate %x %d\n", reg, flags); - else if (flags == MARK_CHECK_SCISSOR) { + } else if (flags == MARK_CHECK_SCISSOR) { DRM_DEBUG("need to validate scissor %x %d\n", reg, flags); } else { DRM_DEBUG("illegal register %x %d\n", reg, flags); @@ -159,6 +186,13 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: + { + uint32_t offset; + offset = packets[count_dw+2] & ((1 << 22) - 1); + offset <<= 10; + DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset); + break; + } case RADEON_CNTL_BITBLT_MULTI: case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ case RADEON_CP_INDX_BUFFER: From 4234f82acc70f41e005d8cc301da56634352425c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 Jul 2008 16:51:47 +1000 Subject: [PATCH 05/49] radeon_cs: add relocate hook for mm and non-mm relocations --- linux-core/radeon_gem.c | 38 ++++++++++++++++- shared-core/radeon_cs.c | 90 ++++++++++++++++++++++++++++++++++++---- shared-core/radeon_drv.h | 8 +++- 3 files changed, 124 insertions(+), 12 deletions(-) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 021bb9f9..859c1656 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -805,10 +805,45 @@ static int radeon_gem_ib_destroy(struct drm_device *dev) return 0; } +static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *reloc, uint32_t *offset) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + /* relocate the handle */ + int domains = reloc[2]; + struct drm_gem_object *obj; + int flags = 0; + int ret; + struct drm_radeon_gem_object *obj_priv; + + obj = drm_gem_object_lookup(dev, file_priv, reloc[1]); + if (!obj) + return false; + + obj_priv = obj->driver_private; + if (domains == RADEON_GEM_DOMAIN_VRAM) { + flags = DRM_BO_FLAG_MEM_VRAM; + } else { + flags = DRM_BO_FLAG_MEM_TT; + } + + ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0, NULL); + if (ret) + return ret; + + if (flags == DRM_BO_FLAG_MEM_VRAM) + *offset = obj_priv->bo->offset + dev_priv->fb_location; + else + *offset = obj_priv->bo->offset + dev_priv->gart_vm_start; + + /* BAD BAD BAD - LINKED LIST THE OBJS and UNREF ONCE IB is SUBMITTED */ + drm_gem_object_unreference(obj); + return 0; +} + /* allocate 1MB of 64k IBs the the kernel can keep mapped */ static int radeon_gem_ib_init(struct drm_device *dev) { - drm_radeon_private_t *dev_priv = dev->dev_private; int i; int ret; @@ -843,6 +878,7 @@ static int radeon_gem_ib_init(struct drm_device *dev) dev_priv->cs.ib_free = radeon_gem_ib_free; radeon_cs_init(dev); + dev_priv->cs.relocate = radeon_gem_relocate; return 0; free_all: diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 5cfe85be..f01334bc 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -74,7 +74,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) } /* now parse command stream */ - r = radeon->cs.parse(dev, ib, packets, cs->dwords); + r = radeon->cs.parse(dev, fpriv, ib, packets, cs->dwords); if (r) { goto out; } @@ -88,6 +88,69 @@ out: return r; } +/* for non-mm */ +static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_priv, uint32_t *reloc, uint32_t *offset) +{ + *offset = reloc[1]; + return 0; +} +#define RELOC_SIZE 2 +#define RADEON_2D_OFFSET_MASK 0x3fffff + +static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t hdr = packets[offset_dw]; + uint32_t reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + uint32_t val = packets[offset_dw + 1]; + uint32_t packet3_hdr = packets[offset_dw+2]; + uint32_t tmp, offset; + int ret; + + /* this is too strict we may want to expand the length in the future and have + old kernels ignore it. */ + if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { + DRM_ERROR("Packet 3 was %x should have been %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16)); + return -EINVAL; + } + + switch(reg) { + case RADEON_DST_PITCH_OFFSET: + case RADEON_SRC_PITCH_OFFSET: + /* pass in the start of the reloc */ + ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); + if (ret) + return ret; + tmp = (val & RADEON_2D_OFFSET_MASK) << 10; + val &= ~RADEON_2D_OFFSET_MASK; + offset += tmp; + offset >>= 10; + val |= offset; + break; + case R300_RB3D_COLOROFFSET0: + case R300_RB3D_DEPTHOFFSET: + case R300_TX_OFFSET_0: + case R300_TX_OFFSET_0+4: + offset = packets[offset_dw + 3]; + + ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); + if (ret) + return ret; + + offset &= 0xffffffe0; + val += offset; + break; + default: + break; + } + + + DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+1], val, offset); + packets[offset_dw + 1] = val; + + return 0; +} static __inline__ int radeon_cs_check_offset(struct drm_device *dev, uint32_t reg, uint32_t val) { @@ -113,11 +176,11 @@ static __inline__ int radeon_cs_check_offset(struct drm_device *dev, return 0; } -int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, - uint32_t offset_dw) +int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) { drm_radeon_private_t *dev_priv = dev->dev_private; - int hdr = packets[offset_dw]; + uint32_t hdr = packets[offset_dw]; int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; int need_reloc = 0; int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; @@ -139,9 +202,16 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, case 1: flags = r300_get_reg_flags(reg); if (flags == MARK_CHECK_OFFSET) { - radeon_cs_check_offset(dev, reg, packets[offset_dw+count_dw]); - + if (num_dw > 2) { + DRM_ERROR("Cannot relocate inside type stream of reg0 packets\n"); + return -EINVAL; + } + + ret = radeon_cs_relocate_offset(dev, file_priv, packets, offset_dw); + if (ret) + return ret; DRM_DEBUG("need to relocate %x %d\n", reg, flags); + /* okay it should be followed by a NOP */ } else if (flags == MARK_CHECK_SCISSOR) { DRM_DEBUG("need to validate scissor %x %d\n", reg, flags); } else { @@ -156,8 +226,8 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, return 0; } -int radeon_cs_parse(struct drm_device *dev, void *ib, - uint32_t *packets, uint32_t dwords) +int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, + void *ib, uint32_t *packets, uint32_t dwords) { drm_radeon_private_t *dev_priv = dev->dev_private; volatile int rb; @@ -173,7 +243,7 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, switch (hdr & RADEON_CP_PACKET_MASK) { case RADEON_CP_PACKET0: - ret = radeon_cs_packet0(dev, packets, count_dw); + ret = radeon_cs_packet0(dev, file_priv, packets, count_dw); break; case RADEON_CP_PACKET1: case RADEON_CP_PACKET2: @@ -191,6 +261,7 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, offset = packets[count_dw+2] & ((1 << 22) - 1); offset <<= 10; DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset); + /* okay it should be followed by a NOP */ break; } case RADEON_CNTL_BITBLT_MULTI: @@ -302,5 +373,6 @@ int radeon_cs_init(struct drm_device *dev) dev_priv->cs.parse = radeon_cs_parse; /* ib get depends on memory manager or not so memory manager */ + dev_priv->cs.relocate = radeon_nomm_relocate; return 0; } diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 232102d5..f79eade5 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -293,8 +293,8 @@ struct drm_radeon_cs_priv { uint32_t id_last_wcnt; uint32_t id_last_scnt; - int (*parse)(struct drm_device *dev, void *ib, - uint32_t *packets, uint32_t dwords); + int (*parse)(struct drm_device *dev, struct drm_file *file_priv, + void *ib, uint32_t *packets, uint32_t dwords); void (*id_emit)(struct drm_device *dev, uint32_t *id); uint32_t (*id_last_get)(struct drm_device *dev); /* this ib handling callback are for hidding memory manager drm @@ -303,6 +303,9 @@ struct drm_radeon_cs_priv { int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords); uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib); void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords); + /* do a relocation either MM or non-MM */ + bool (*relocate)(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *reloc, uint32_t *offset); }; typedef struct drm_radeon_private { @@ -391,6 +394,7 @@ typedef struct drm_radeon_private { int num_gb_pipes; + int mm_disabled; /* on OSes with no MM this will be 1*/ struct radeon_mm_info mm; drm_local_map_t *mmio; From 0452be882607f2d1601f4e592a11ccf543f5f9ca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 Jul 2008 18:05:11 +1000 Subject: [PATCH 06/49] radeon: move code around putting emit into cs --- linux-core/radeon_gem.c | 29 ++++++--------- shared-core/radeon_cs.c | 76 ++++++++++++++++++++++++++++++---------- shared-core/radeon_drv.h | 4 +-- 3 files changed, 69 insertions(+), 40 deletions(-) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 859c1656..9d122ac5 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -700,7 +700,7 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, #define RADEON_NUM_IB (RADEON_IB_MEMORY / RADEON_IB_SIZE) -int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords) +int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32_t *card_offset) { int i, index = -1; int ret; @@ -738,6 +738,15 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords) if (dwords > RADEON_IB_SIZE / sizeof(uint32_t)) return -EINVAL; + ret = drm_bo_do_validate(dev_priv->ib_objs[index]->bo, 0, + DRM_BO_FLAG_NO_EVICT, + 0, 0, NULL); + if (ret) { + DRM_ERROR("Failed to validate IB %d\n", index); + return -EINVAL; + } + + *card_offset = dev_priv->gart_vm_start + dev_priv->ib_objs[index]->bo->offset; *ib = dev_priv->ib_objs[index]->kmap.virtual; dev_priv->ib_alloc_bitmap |= (1 << i); return 0; @@ -754,24 +763,6 @@ static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords for (i = 0; i < RADEON_NUM_IB; i++) { if (dev_priv->ib_objs[i]->kmap.virtual == ib) { - ret = drm_bo_do_validate(dev_priv->ib_objs[i]->bo, 0, - DRM_BO_FLAG_NO_EVICT, - 0, 0, NULL); - if (ret) - DRM_ERROR("FAiled to validate\n"); - - DRM_DEBUG("validated IB %x, %d\n", dev_priv->ib_objs[i]->bo->offset, dwords); - BEGIN_RING(4); - - OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); - OUT_RING(dev_priv->gart_vm_start + dev_priv->ib_objs[i]->bo->offset); - OUT_RING(dwords); - OUT_RING(CP_PACKET2()); - - ADVANCE_RING(); - - COMMIT_RING(); - /* emit a fence object */ ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); if (ret) { diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index f01334bc..33a8ccd4 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -31,19 +31,21 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) { - struct drm_radeon_private *radeon = dev->dev_private; + struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_radeon_cs *cs = data; uint32_t *packets = NULL; uint32_t cs_id; + uint32_t card_offset; void *ib = NULL; long size; int r; + RING_LOCALS; /* set command stream id to 0 which is fake id */ cs_id = 0; DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); - if (radeon == NULL) { + if (dev_priv == NULL) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -68,22 +70,31 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) goto out; } /* get ib */ - r = radeon->cs.ib_get(dev, &ib, cs->dwords); + r = dev_priv->cs.ib_get(dev, &ib, cs->dwords, &card_offset); if (r) { goto out; } /* now parse command stream */ - r = radeon->cs.parse(dev, fpriv, ib, packets, cs->dwords); + r = dev_priv->cs.parse(dev, fpriv, ib, packets, cs->dwords); if (r) { goto out; } + BEGIN_RING(4); + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(card_offset); + OUT_RING(cs->dwords); + OUT_RING(CP_PACKET2()); + ADVANCE_RING(); + /* emit cs id sequence */ - radeon->cs.id_emit(dev, &cs_id); + dev_priv->cs.id_emit(dev, &cs_id); + COMMIT_RING(); + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); out: - radeon->cs.ib_free(dev, ib, cs->dwords); + dev_priv->cs.ib_free(dev, ib, cs->dwords); drm_free(packets, size, DRM_MEM_DRIVER); return r; } @@ -97,8 +108,8 @@ static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_pr #define RELOC_SIZE 2 #define RADEON_2D_OFFSET_MASK 0x3fffff -static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *packets, uint32_t offset_dw) +static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) { drm_radeon_private_t *dev_priv = dev->dev_private; uint32_t hdr = packets[offset_dw]; @@ -107,7 +118,7 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d uint32_t packet3_hdr = packets[offset_dw+2]; uint32_t tmp, offset; int ret; - + /* this is too strict we may want to expand the length in the future and have old kernels ignore it. */ if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { @@ -132,8 +143,6 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d case R300_RB3D_DEPTHOFFSET: case R300_TX_OFFSET_0: case R300_TX_OFFSET_0+4: - offset = packets[offset_dw + 3]; - ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); if (ret) return ret; @@ -151,6 +160,40 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d return 0; } + +static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t hdr = packets[offset_dw]; + int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; + uint32_t reg = hdr & 0xff00; + uint32_t offset, val, tmp; + int ret; + + switch(reg) { + case RADEON_CNTL_HOSTDATA_BLT: + { + val = packets[offset_dw + 2]; + ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + num_dw + 2, &offset); + if (ret) + return ret; + + tmp = (val & RADEON_2D_OFFSET_MASK) << 10; + val &= ~RADEON_2D_OFFSET_MASK; + offset += tmp; + offset >>= 10; + val |= offset; + + DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+2], val, offset); + packets[offset_dw + 2] = val; + } + default: + return -EINVAL; + } + return 0; +} + static __inline__ int radeon_cs_check_offset(struct drm_device *dev, uint32_t reg, uint32_t val) { @@ -207,7 +250,7 @@ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, return -EINVAL; } - ret = radeon_cs_relocate_offset(dev, file_priv, packets, offset_dw); + ret = radeon_cs_relocate_packet0(dev, file_priv, packets, offset_dw); if (ret) return ret; DRM_DEBUG("need to relocate %x %d\n", reg, flags); @@ -256,14 +299,9 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: - { - uint32_t offset; - offset = packets[count_dw+2] & ((1 << 22) - 1); - offset <<= 10; - DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset); - /* okay it should be followed by a NOP */ + radeon_cs_relocate_packet3(dev, file_priv, packets, count_dw); break; - } + case RADEON_CNTL_BITBLT_MULTI: case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ case RADEON_CP_INDX_BUFFER: diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index f79eade5..e55a9697 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -300,11 +300,11 @@ struct drm_radeon_cs_priv { /* this ib handling callback are for hidding memory manager drm * from memory manager less drm, free have to emit ib discard * sequence into the ring */ - int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords); + int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords, uint32_t *card_offset); uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib); void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords); /* do a relocation either MM or non-MM */ - bool (*relocate)(struct drm_device *dev, struct drm_file *file_priv, + int (*relocate)(struct drm_device *dev, struct drm_file *file_priv, uint32_t *reloc, uint32_t *offset); }; From d659302e0955598ae08316ab911a0fb74d5e2f2f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 30 Jul 2008 17:05:50 +1000 Subject: [PATCH 07/49] radeon: add some handles to the sarea + kernel mm available check --- shared-core/radeon_drm.h | 8 ++++++++ shared-core/radeon_state.c | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index c20de561..8ee1baa7 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -455,6 +455,13 @@ typedef struct { int tiling_enabled; /* set by drm, read by 2d + 3d clients */ unsigned int last_fence; + + uint32_t front_handle; + uint32_t back_handle; + uint32_t depth_handle; + uint32_t front_pitch; + uint32_t back_pitch; + uint32_t depth_pitch; } drm_radeon_sarea_t; @@ -705,6 +712,7 @@ typedef struct drm_radeon_indirect { #define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ #define RADEON_PARAM_FB_LOCATION 14 /* FB location */ #define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ +#define RADEON_PARAM_KERNEL_MM 16 typedef struct drm_radeon_getparam { int param; diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index d56dac19..00160fbf 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3117,6 +3117,10 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil case RADEON_PARAM_NUM_GB_PIPES: value = dev_priv->num_gb_pipes; break; + case RADEON_PARAM_KERNEL_MM: + /* BSD TODO */ + value = 1; + break; default: DRM_DEBUG( "Invalid parameter %d\n", param->param ); return -EINVAL; From fb5542aaa87aca9b6b312968abe0a6044812cf0e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 30 Jul 2008 17:06:11 +1000 Subject: [PATCH 08/49] radeon: hack gem to get an offset back for Mesa. --- linux-core/radeon_gem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 9d122ac5..e06cba5b 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -243,9 +243,12 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage)); /* validate into a pin with no fence */ - ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, - 0, NULL); + if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { + ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, + 0, NULL); + } else + ret = 0; args->offset = obj_priv->bo->offset; DRM_DEBUG("got here %p %p\n", obj, obj_priv->bo); From 9b8d71b5eb09857b07409731d3de182751f712a2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 31 Jul 2008 12:54:48 +1000 Subject: [PATCH 09/49] TTM: remove API and userspace objects. This removes all the TTM userspace API and all userspace objects. It also removes the drm_bo_lock.c code --- linux-core/Makefile.kernel | 7 +- linux-core/drmP.h | 18 - linux-core/drm_bo.c | 729 +-------------------------- linux-core/drm_bo_lock.c | 189 ------- linux-core/drm_crtc_helper.c | 44 -- linux-core/drm_drv.c | 30 -- linux-core/drm_fence.c | 298 +----------- linux-core/drm_fops.c | 43 -- linux-core/drm_object.c | 294 ----------- linux-core/drm_objects.h | 297 ++++++----- linux-core/drm_ttm.c | 2 +- linux-core/i915_buffer.c | 311 ------------ linux-core/i915_execbuf.c | 921 ----------------------------------- linux-core/i915_fence.c | 273 ----------- linux-core/radeon_gem.c | 15 +- shared-core/drm.h | 343 ------------- shared-core/i915_dma.c | 32 +- shared-core/i915_drm.h | 52 -- 18 files changed, 202 insertions(+), 3696 deletions(-) delete mode 100644 linux-core/drm_bo_lock.c delete mode 100644 linux-core/drm_object.c delete mode 100644 linux-core/i915_buffer.c delete mode 100644 linux-core/i915_execbuf.c delete mode 100644 linux-core/i915_fence.c diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 404944bf..b15a12ab 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -12,16 +12,15 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \ drm_memory_debug.o ati_pcigart.o drm_sman.o \ - drm_hashtab.o drm_memrange.o drm_object.o drm_compat.o \ - drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock.o \ + drm_hashtab.o drm_memrange.o drm_compat.o \ + drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o \ drm_crtc.o drm_edid.o drm_modes.o drm_crtc_helper.o \ drm_regman.o drm_vm_nopage_compat.o drm_gem.o tdfx-objs := tdfx_drv.o r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o i810-objs := i810_drv.o i810_dma.o -i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ - i915_buffer.o i915_execbuf.o i915_gem.o \ +i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_gem.o \ intel_display.o intel_crt.o intel_lvds.o intel_bios.o \ intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o \ intel_tv.o i915_compat.o intel_dvo.o dvo_ch7xxx.o \ diff --git a/linux-core/drmP.h b/linux-core/drmP.h index e3a08e79..4938881f 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -405,14 +405,6 @@ struct drm_buf_entry { struct drm_freelist freelist; }; - -enum drm_ref_type { - _DRM_REF_USE = 0, - _DRM_REF_TYPE1, - _DRM_NO_REF_TYPES -}; - - /** File private data */ struct drm_file { int authenticated; @@ -424,21 +416,11 @@ struct drm_file { struct drm_minor *minor; unsigned long lock_count; - /* - * The user object hash table is global and resides in the - * drm_device structure. We protect the lists and hash tables with the - * device struct_mutex. A bit coarse-grained but probably the best - * option. - */ - - struct list_head refd_objects; - /** Mapping of mm object handles to object pointers. */ struct idr object_idr; /** Lock for synchronization of access to object_idr. */ spinlock_t table_lock; - struct drm_open_hash refd_object_hash[_DRM_NO_REF_TYPES]; struct file *filp; void *driver_priv; diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 0021530b..84cf69bd 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -565,18 +565,6 @@ void drm_bo_usage_deref_locked(struct drm_buffer_object **bo) } EXPORT_SYMBOL(drm_bo_usage_deref_locked); -static void drm_bo_base_deref_locked(struct drm_file *file_priv, - struct drm_user_object *uo) -{ - struct drm_buffer_object *bo = - drm_user_object_entry(uo, struct drm_buffer_object, base); - - DRM_ASSERT_LOCKED(&bo->dev->struct_mutex); - - drm_bo_takedown_vm_locked(bo); - drm_bo_usage_deref_locked(&bo); -} - void drm_bo_usage_deref_unlocked(struct drm_buffer_object **bo) { struct drm_buffer_object *tmp_bo = *bo; @@ -1067,34 +1055,6 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo, return 0; } -/* - * Call dev->struct_mutex locked. - */ - -struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv, - uint32_t handle, int check_owner) -{ - struct drm_user_object *uo; - struct drm_buffer_object *bo; - - uo = drm_lookup_user_object(file_priv, handle); - - if (!uo || (uo->type != drm_buffer_type)) { - DRM_ERROR("Could not find buffer object 0x%08x\n", handle); - return NULL; - } - - if (check_owner && file_priv != uo->owner) { - if (!drm_lookup_ref_object(file_priv, uo, _DRM_REF_USE)) - return NULL; - } - - bo = drm_user_object_entry(uo, struct drm_buffer_object, base); - atomic_inc(&bo->usage); - return bo; -} -EXPORT_SYMBOL(drm_lookup_buffer_object); - /* * Call bo->mutex locked. * Returns -EBUSY if the buffer is currently rendered to or from. 0 otherwise. @@ -1157,149 +1117,6 @@ static int drm_bo_wait_unmapped(struct drm_buffer_object *bo, int no_wait) return ret; } -/* - * Fill in the ioctl reply argument with buffer info. - * Bo locked. - */ - -void drm_bo_fill_rep_arg(struct drm_buffer_object *bo, - struct drm_bo_info_rep *rep) -{ - if (!rep) - return; - - rep->handle = bo->base.hash.key; - rep->flags = bo->mem.flags; - rep->size = bo->num_pages * PAGE_SIZE; - rep->offset = bo->offset; - - /* - * drm_bo_type_device buffers have user-visible - * handles which can be used to share across - * processes. Hand that back to the application - */ - if (bo->type == drm_bo_type_device) - rep->arg_handle = bo->map_list.user_token; - else - rep->arg_handle = 0; - - rep->proposed_flags = bo->mem.proposed_flags; - rep->buffer_start = bo->buffer_start; - rep->fence_flags = bo->fence_type; - rep->rep_flags = 0; - rep->page_alignment = bo->mem.page_alignment; - - if ((bo->priv_flags & _DRM_BO_FLAG_UNFENCED) || drm_bo_quick_busy(bo, 1)) { - DRM_FLAG_MASKED(rep->rep_flags, DRM_BO_REP_BUSY, - DRM_BO_REP_BUSY); - } -} -EXPORT_SYMBOL(drm_bo_fill_rep_arg); - -/* - * Wait for buffer idle and register that we've mapped the buffer. - * Mapping is registered as a drm_ref_object with type _DRM_REF_TYPE1, - * so that if the client dies, the mapping is automatically - * unregistered. - */ - -static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle, - uint32_t map_flags, unsigned hint, - struct drm_bo_info_rep *rep) -{ - struct drm_buffer_object *bo; - struct drm_device *dev = file_priv->minor->dev; - int ret = 0; - int no_wait = hint & DRM_BO_HINT_DONT_BLOCK; - - mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, handle, 1); - mutex_unlock(&dev->struct_mutex); - - if (!bo) - return -EINVAL; - - mutex_lock(&bo->mutex); - do { - bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; - - ret = drm_bo_wait(bo, 0, 1, no_wait, 1); - if (unlikely(ret)) - goto out; - - if (bo->mem.flags & DRM_BO_FLAG_CACHED_MAPPED) - drm_bo_evict_cached(bo); - - } while (unlikely(bo->priv_flags & _DRM_BO_FLAG_UNLOCKED)); - - atomic_inc(&bo->mapped); - mutex_lock(&dev->struct_mutex); - ret = drm_add_ref_object(file_priv, &bo->base, _DRM_REF_TYPE1); - mutex_unlock(&dev->struct_mutex); - if (ret) { - if (atomic_dec_and_test(&bo->mapped)) - wake_up_all(&bo->event_queue); - - } else - drm_bo_fill_rep_arg(bo, rep); - - out: - mutex_unlock(&bo->mutex); - drm_bo_usage_deref_unlocked(&bo); - - return ret; -} - -static int drm_buffer_object_unmap(struct drm_file *file_priv, uint32_t handle) -{ - struct drm_device *dev = file_priv->minor->dev; - struct drm_buffer_object *bo; - struct drm_ref_object *ro; - int ret = 0; - - mutex_lock(&dev->struct_mutex); - - bo = drm_lookup_buffer_object(file_priv, handle, 1); - if (!bo) { - ret = -EINVAL; - goto out; - } - - ro = drm_lookup_ref_object(file_priv, &bo->base, _DRM_REF_TYPE1); - if (!ro) { - ret = -EINVAL; - goto out; - } - - drm_remove_ref_object(file_priv, ro); - drm_bo_usage_deref_locked(&bo); -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -/* - * Call struct-sem locked. - */ - -static void drm_buffer_user_object_unmap(struct drm_file *file_priv, - struct drm_user_object *uo, - enum drm_ref_type action) -{ - struct drm_buffer_object *bo = - drm_user_object_entry(uo, struct drm_buffer_object, base); - - /* - * We DON'T want to take the bo->lock here, because we want to - * hold it when we wait for unmapped buffer. - */ - - BUG_ON(action != _DRM_REF_TYPE1); - - if (atomic_dec_and_test(&bo->mapped)) - wake_up_all(&bo->event_queue); -} - /* * bo->mutex locked. * Note that new_mem_flags are NOT transferred to the bo->mem.proposed_flags. @@ -1594,8 +1411,7 @@ static int drm_bo_prepare_for_validate(struct drm_buffer_object *bo, int drm_bo_do_validate(struct drm_buffer_object *bo, uint64_t flags, uint64_t mask, uint32_t hint, - uint32_t fence_class, - struct drm_bo_info_rep *rep) + uint32_t fence_class) { int ret; int no_wait = (hint & DRM_BO_HINT_DONT_BLOCK) != 0; @@ -1622,132 +1438,12 @@ int drm_bo_do_validate(struct drm_buffer_object *bo, BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNLOCKED); out: - if (rep) - drm_bo_fill_rep_arg(bo, rep); - mutex_unlock(&bo->mutex); return ret; } EXPORT_SYMBOL(drm_bo_do_validate); -/** - * drm_bo_handle_validate - * - * @file_priv: the drm file private, used to get a handle to the user context - * - * @handle: the buffer object handle - * - * @flags: access rights, mapping parameters and cacheability. See - * the DRM_BO_FLAG_* values in drm.h - * - * @mask: Which flag values to change; this allows callers to modify - * things without knowing the current state of other flags. - * - * @hint: changes the proceedure for this operation, see the DRM_BO_HINT_* - * values in drm.h. - * - * @fence_class: a driver-specific way of doing fences. Presumably, - * this would be used if the driver had more than one submission and - * fencing mechanism. At this point, there isn't any use of this - * from the user mode code. - * - * @rep: To be stuffed with the reply from validation - * - * @bp_rep: To be stuffed with the buffer object pointer - * - * Perform drm_bo_do_validate on a buffer referenced by a user-space handle instead - * of a pointer to a buffer object. Optionally return a pointer to the buffer object. - * This is a convenience wrapper only. - */ - -int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, - uint64_t flags, uint64_t mask, - uint32_t hint, - uint32_t fence_class, - struct drm_bo_info_rep *rep, - struct drm_buffer_object **bo_rep) -{ - struct drm_device *dev = file_priv->minor->dev; - struct drm_buffer_object *bo; - int ret; - - mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, handle, 1); - mutex_unlock(&dev->struct_mutex); - - if (!bo) - return -EINVAL; - - if (bo->base.owner != file_priv) - mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE); - - ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, rep); - - if (!ret && bo_rep) - *bo_rep = bo; - else - drm_bo_usage_deref_unlocked(&bo); - - return ret; -} -EXPORT_SYMBOL(drm_bo_handle_validate); - - -static int drm_bo_handle_info(struct drm_file *file_priv, uint32_t handle, - struct drm_bo_info_rep *rep) -{ - struct drm_device *dev = file_priv->minor->dev; - struct drm_buffer_object *bo; - - mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, handle, 1); - mutex_unlock(&dev->struct_mutex); - - if (!bo) - return -EINVAL; - - mutex_lock(&bo->mutex); - - /* - * FIXME: Quick busy here? - */ - - drm_bo_busy(bo, 1); - drm_bo_fill_rep_arg(bo, rep); - mutex_unlock(&bo->mutex); - drm_bo_usage_deref_unlocked(&bo); - return 0; -} - -static int drm_bo_handle_wait(struct drm_file *file_priv, uint32_t handle, - uint32_t hint, - struct drm_bo_info_rep *rep) -{ - struct drm_device *dev = file_priv->minor->dev; - struct drm_buffer_object *bo; - int no_wait = hint & DRM_BO_HINT_DONT_BLOCK; - int ret; - - mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, handle, 1); - mutex_unlock(&dev->struct_mutex); - - if (!bo) - return -EINVAL; - - mutex_lock(&bo->mutex); - ret = drm_bo_wait(bo, hint & DRM_BO_HINT_WAIT_LAZY, 1, no_wait, 1); - if (ret) - goto out; - - drm_bo_fill_rep_arg(bo, rep); -out: - mutex_unlock(&bo->mutex); - drm_bo_usage_deref_unlocked(&bo); - return ret; -} - int drm_buffer_object_create(struct drm_device *dev, unsigned long size, enum drm_bo_type type, @@ -1822,7 +1518,7 @@ int drm_buffer_object_create(struct drm_device *dev, mutex_unlock(&bo->mutex); ret = drm_bo_do_validate(bo, 0, 0, hint | DRM_BO_HINT_DONT_FENCE, - 0, NULL); + 0); if (ret) goto out_err_unlocked; @@ -1837,230 +1533,6 @@ out_err_unlocked: } EXPORT_SYMBOL(drm_buffer_object_create); - -int drm_bo_add_user_object(struct drm_file *file_priv, - struct drm_buffer_object *bo, int shareable) -{ - struct drm_device *dev = file_priv->minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm_add_user_object(file_priv, &bo->base, shareable); - if (ret) - goto out; - - bo->base.remove = drm_bo_base_deref_locked; - bo->base.type = drm_buffer_type; - bo->base.ref_struct_locked = NULL; - bo->base.unref = drm_buffer_user_object_unmap; - -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} -EXPORT_SYMBOL(drm_bo_add_user_object); - -int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_create_arg *arg = data; - struct drm_bo_create_req *req = &arg->d.req; - struct drm_bo_info_rep *rep = &arg->d.rep; - struct drm_buffer_object *entry; - enum drm_bo_type bo_type; - int ret = 0; - - DRM_DEBUG("drm_bo_create_ioctl: %dkb, %dkb align\n", - (int)(req->size / 1024), req->page_alignment * 4); - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - /* - * If the buffer creation request comes in with a starting address, - * that points at the desired user pages to map. Otherwise, create - * a drm_bo_type_device buffer, which uses pages allocated from the kernel - */ - bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_device; - - /* - * User buffers cannot be shared - */ - if (bo_type == drm_bo_type_user) - req->flags &= ~DRM_BO_FLAG_SHAREABLE; - - ret = drm_buffer_object_create(file_priv->minor->dev, - req->size, bo_type, req->flags, - req->hint, req->page_alignment, - req->buffer_start, &entry); - if (ret) - goto out; - - ret = drm_bo_add_user_object(file_priv, entry, - req->flags & DRM_BO_FLAG_SHAREABLE); - if (ret) { - drm_bo_usage_deref_unlocked(&entry); - goto out; - } - - mutex_lock(&entry->mutex); - drm_bo_fill_rep_arg(entry, rep); - mutex_unlock(&entry->mutex); - -out: - return ret; -} - -int drm_bo_setstatus_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv) -{ - struct drm_bo_map_wait_idle_arg *arg = data; - struct drm_bo_info_req *req = &arg->d.req; - struct drm_bo_info_rep *rep = &arg->d.rep; - struct drm_buffer_object *bo; - int ret; - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - ret = drm_bo_read_lock(&dev->bm.bm_lock, 1); - if (ret) - return ret; - - mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, req->handle, 1); - mutex_unlock(&dev->struct_mutex); - - if (!bo) - return -EINVAL; - - if (bo->base.owner != file_priv) - req->mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE); - - ret = drm_bo_do_validate(bo, req->flags, req->mask, - req->hint | DRM_BO_HINT_DONT_FENCE, - bo->fence_class, rep); - - drm_bo_usage_deref_unlocked(&bo); - - (void) drm_bo_read_unlock(&dev->bm.bm_lock); - - return ret; -} - -int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_map_wait_idle_arg *arg = data; - struct drm_bo_info_req *req = &arg->d.req; - struct drm_bo_info_rep *rep = &arg->d.rep; - int ret; - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - ret = drm_buffer_object_map(file_priv, req->handle, req->mask, - req->hint, rep); - if (ret) - return ret; - - return 0; -} - -int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_handle_arg *arg = data; - int ret; - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - ret = drm_buffer_object_unmap(file_priv, arg->handle); - return ret; -} - - -int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_reference_info_arg *arg = data; - struct drm_bo_handle_arg *req = &arg->d.req; - struct drm_bo_info_rep *rep = &arg->d.rep; - struct drm_user_object *uo; - int ret; - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - ret = drm_user_object_ref(file_priv, req->handle, - drm_buffer_type, &uo); - if (ret) - return ret; - - ret = drm_bo_handle_info(file_priv, req->handle, rep); - if (ret) - return ret; - - return 0; -} - -int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_handle_arg *arg = data; - int ret = 0; - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - ret = drm_user_object_unref(file_priv, arg->handle, drm_buffer_type); - return ret; -} - -int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_reference_info_arg *arg = data; - struct drm_bo_handle_arg *req = &arg->d.req; - struct drm_bo_info_rep *rep = &arg->d.rep; - int ret; - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - ret = drm_bo_handle_info(file_priv, req->handle, rep); - if (ret) - return ret; - - return 0; -} - -int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_map_wait_idle_arg *arg = data; - struct drm_bo_info_req *req = &arg->d.req; - struct drm_bo_info_rep *rep = &arg->d.rep; - int ret; - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - ret = drm_bo_handle_wait(file_priv, req->handle, - req->hint, rep); - if (ret) - return ret; - - return 0; -} - static int drm_bo_leave_list(struct drm_buffer_object *bo, uint32_t mem_type, int free_pinned, @@ -2435,191 +1907,6 @@ out_unlock: } EXPORT_SYMBOL(drm_bo_driver_init); -int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_mm_init_arg *arg = data; - struct drm_buffer_manager *bm = &dev->bm; - struct drm_bo_driver *driver = dev->driver->bo_driver; - int ret; - - if (!driver) { - DRM_ERROR("Buffer objects are not supported by this driver\n"); - return -EINVAL; - } - - ret = drm_bo_write_lock(&bm->bm_lock, 1, file_priv); - if (ret) - return ret; - - ret = -EINVAL; - if (arg->magic != DRM_BO_INIT_MAGIC) { - DRM_ERROR("You are using an old libdrm that is not compatible with\n" - "\tthe kernel DRM module. Please upgrade your libdrm.\n"); - return -EINVAL; - } - if (arg->major != DRM_BO_INIT_MAJOR) { - DRM_ERROR("libdrm and kernel DRM buffer object interface major\n" - "\tversion don't match. Got %d, expected %d.\n", - arg->major, DRM_BO_INIT_MAJOR); - return -EINVAL; - } - - mutex_lock(&dev->struct_mutex); - if (!bm->initialized) { - DRM_ERROR("DRM memory manager was not initialized.\n"); - goto out; - } - if (arg->mem_type == 0) { - DRM_ERROR("System memory buffers already initialized.\n"); - goto out; - } - ret = drm_bo_init_mm(dev, arg->mem_type, - arg->p_offset, arg->p_size, 0); - -out: - mutex_unlock(&dev->struct_mutex); - (void) drm_bo_write_unlock(&bm->bm_lock, file_priv); - - if (ret) - return ret; - - return 0; -} - -int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_mm_type_arg *arg = data; - struct drm_buffer_manager *bm = &dev->bm; - struct drm_bo_driver *driver = dev->driver->bo_driver; - int ret; - - if (!driver) { - DRM_ERROR("Buffer objects are not supported by this driver\n"); - return -EINVAL; - } - - ret = drm_bo_write_lock(&bm->bm_lock, 0, file_priv); - if (ret) - return ret; - - mutex_lock(&dev->struct_mutex); - ret = -EINVAL; - if (!bm->initialized) { - DRM_ERROR("DRM memory manager was not initialized\n"); - goto out; - } - if (arg->mem_type == 0) { - DRM_ERROR("No takedown for System memory buffers.\n"); - goto out; - } - ret = 0; - if ((ret = drm_bo_clean_mm(dev, arg->mem_type, 0))) { - if (ret == -EINVAL) - DRM_ERROR("Memory manager type %d not clean. " - "Delaying takedown\n", arg->mem_type); - ret = 0; - } -out: - mutex_unlock(&dev->struct_mutex); - (void) drm_bo_write_unlock(&bm->bm_lock, file_priv); - - if (ret) - return ret; - - return 0; -} - -int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_mm_type_arg *arg = data; - struct drm_bo_driver *driver = dev->driver->bo_driver; - int ret; - - if (!driver) { - DRM_ERROR("Buffer objects are not supported by this driver\n"); - return -EINVAL; - } - - if (arg->lock_flags & DRM_BO_LOCK_IGNORE_NO_EVICT) { - DRM_ERROR("Lock flag DRM_BO_LOCK_IGNORE_NO_EVICT not supported yet.\n"); - return -EINVAL; - } - - if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) { - ret = drm_bo_write_lock(&dev->bm.bm_lock, 1, file_priv); - if (ret) - return ret; - } - - mutex_lock(&dev->struct_mutex); - ret = drm_bo_lock_mm(dev, arg->mem_type); - mutex_unlock(&dev->struct_mutex); - if (ret) { - (void) drm_bo_write_unlock(&dev->bm.bm_lock, file_priv); - return ret; - } - - return 0; -} - -int drm_mm_unlock_ioctl(struct drm_device *dev, - void *data, - struct drm_file *file_priv) -{ - struct drm_mm_type_arg *arg = data; - struct drm_bo_driver *driver = dev->driver->bo_driver; - int ret; - - if (!driver) { - DRM_ERROR("Buffer objects are not supported by this driver\n"); - return -EINVAL; - } - - if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) { - ret = drm_bo_write_unlock(&dev->bm.bm_lock, file_priv); - if (ret) - return ret; - } - - return 0; -} - -int drm_mm_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_mm_info_arg *arg = data; - struct drm_buffer_manager *bm = &dev->bm; - struct drm_bo_driver *driver = dev->driver->bo_driver; - struct drm_mem_type_manager *man; - int ret = 0; - int mem_type = arg->mem_type; - - if (!driver) { - DRM_ERROR("Buffer objects are not supported by this driver\n"); - return -EINVAL; - } - - if (mem_type >= DRM_BO_MEM_TYPES) { - DRM_ERROR("Illegal memory type %d\n", arg->mem_type); - return -EINVAL; - } - - mutex_lock(&dev->struct_mutex); - if (!bm->initialized) { - DRM_ERROR("DRM memory manager was not initialized\n"); - ret = -EINVAL; - goto out; - } - - - man = &bm->man[arg->mem_type]; - - arg->p_size = man->size; - -out: - mutex_unlock(&dev->struct_mutex); - - return ret; -} /* * buffer object vm functions. */ @@ -2792,15 +2079,3 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo) return 0; } - -int drm_bo_version_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_bo_version_arg *arg = (struct drm_bo_version_arg *)data; - - arg->major = DRM_BO_INIT_MAJOR; - arg->minor = DRM_BO_INIT_MINOR; - arg->patchlevel = DRM_BO_INIT_PATCH; - - return 0; -} diff --git a/linux-core/drm_bo_lock.c b/linux-core/drm_bo_lock.c deleted file mode 100644 index 08b1c6be..00000000 --- a/linux-core/drm_bo_lock.c +++ /dev/null @@ -1,189 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellström - */ - -/* - * This file implements a simple replacement for the buffer manager use - * of the heavyweight hardware lock. - * The lock is a read-write lock. Taking it in read mode is fast, and - * intended for in-kernel use only. - * Taking it in write mode is slow. - * - * The write mode is used only when there is a need to block all - * user-space processes from allocating a - * new memory area. - * Typical use in write mode is X server VT switching, and it's allowed - * to leave kernel space with the write lock held. If a user-space process - * dies while having the write-lock, it will be released during the file - * descriptor release. - * - * The read lock is typically placed at the start of an IOCTL- or - * user-space callable function that may end up allocating a memory area. - * This includes setstatus, super-ioctls and no_pfn; the latter may move - * unmappable regions to mappable. It's a bug to leave kernel space with the - * read lock held. - * - * Both read- and write lock taking may be interruptible for low signal-delivery - * latency. The locking functions will return -EAGAIN if interrupted by a - * signal. - * - * Locking order: The lock should be taken BEFORE any kernel mutexes - * or spinlocks. - */ - -#include "drmP.h" - -void drm_bo_init_lock(struct drm_bo_lock *lock) -{ - DRM_INIT_WAITQUEUE(&lock->queue); - atomic_set(&lock->write_lock_pending, 0); - atomic_set(&lock->readers, 0); -} - -void drm_bo_read_unlock(struct drm_bo_lock *lock) -{ - if (atomic_dec_and_test(&lock->readers)) - wake_up_all(&lock->queue); -} -EXPORT_SYMBOL(drm_bo_read_unlock); - -int drm_bo_read_lock(struct drm_bo_lock *lock, int interruptible) -{ - while (unlikely(atomic_read(&lock->write_lock_pending) != 0)) { - int ret; - - if (!interruptible) { - wait_event(lock->queue, - atomic_read(&lock->write_lock_pending) == 0); - continue; - } - ret = wait_event_interruptible - (lock->queue, atomic_read(&lock->write_lock_pending) == 0); - if (ret) - return -EAGAIN; - } - - while (unlikely(!atomic_add_unless(&lock->readers, 1, -1))) { - int ret; - if (!interruptible) { - wait_event(lock->queue, - atomic_read(&lock->readers) != -1); - continue; - } - ret = wait_event_interruptible - (lock->queue, atomic_read(&lock->readers) != -1); - if (ret) - return -EAGAIN; - } - return 0; -} -EXPORT_SYMBOL(drm_bo_read_lock); - -static int __drm_bo_write_unlock(struct drm_bo_lock *lock) -{ - if (unlikely(atomic_cmpxchg(&lock->readers, -1, 0) != -1)) - return -EINVAL; - wake_up_all(&lock->queue); - return 0; -} - -static void drm_bo_write_lock_remove(struct drm_file *file_priv, - struct drm_user_object *item) -{ - struct drm_bo_lock *lock = container_of(item, struct drm_bo_lock, base); - int ret; - - ret = __drm_bo_write_unlock(lock); - BUG_ON(ret); -} - -int drm_bo_write_lock(struct drm_bo_lock *lock, int interruptible, - struct drm_file *file_priv) -{ - int ret = 0; - struct drm_device *dev; - - atomic_inc(&lock->write_lock_pending); - - while (unlikely(atomic_cmpxchg(&lock->readers, 0, -1) != 0)) { - if (!interruptible) { - wait_event(lock->queue, - atomic_read(&lock->readers) == 0); - continue; - } - ret = wait_event_interruptible - (lock->queue, atomic_read(&lock->readers) == 0); - - if (ret) { - atomic_dec(&lock->write_lock_pending); - wake_up_all(&lock->queue); - return -EAGAIN; - } - } - - /* - * Add a dummy user-object, the destructor of which will - * make sure the lock is released if the client dies - * while holding it. - */ - - if (atomic_dec_and_test(&lock->write_lock_pending)) - wake_up_all(&lock->queue); - dev = file_priv->minor->dev; - mutex_lock(&dev->struct_mutex); - ret = drm_add_user_object(file_priv, &lock->base, 0); - lock->base.remove = &drm_bo_write_lock_remove; - lock->base.type = drm_lock_type; - if (ret) - (void)__drm_bo_write_unlock(lock); - - mutex_unlock(&dev->struct_mutex); - - return ret; -} - -int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv) -{ - struct drm_device *dev = file_priv->minor->dev; - struct drm_ref_object *ro; - - mutex_lock(&dev->struct_mutex); - - if (lock->base.owner != file_priv) { - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - ro = drm_lookup_ref_object(file_priv, &lock->base, _DRM_REF_USE); - BUG_ON(!ro); - drm_remove_ref_object(file_priv, ro); - lock->base.owner = NULL; - - mutex_unlock(&dev->struct_mutex); - return 0; -} diff --git a/linux-core/drm_crtc_helper.c b/linux-core/drm_crtc_helper.c index e0d93606..ee1dc258 100644 --- a/linux-core/drm_crtc_helper.c +++ b/linux-core/drm_crtc_helper.c @@ -715,48 +715,4 @@ int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, } EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); -/** - * drm_get_buffer_object - find the buffer object for a given handle - * @dev: DRM device - * @bo: pointer to caller's buffer_object pointer - * @handle: handle to lookup - * - * LOCKING: - * Must take @dev's struct_mutex to protect buffer object lookup. - * - * Given @handle, lookup the buffer object in @dev and put it in the caller's - * @bo pointer. - * - * RETURNS: - * Zero on success, -EINVAL if the handle couldn't be found. - */ -int drm_get_buffer_object(struct drm_device *dev, struct drm_buffer_object **bo, unsigned long handle) -{ - struct drm_user_object *uo; - struct drm_hash_item *hash; - int ret; - - *bo = NULL; - - mutex_lock(&dev->struct_mutex); - ret = drm_ht_find_item(&dev->object_hash, handle, &hash); - if (ret) { - DRM_ERROR("Couldn't find handle.\n"); - ret = -EINVAL; - goto out_err; - } - - uo = drm_hash_entry(hash, struct drm_user_object, hash); - if (uo->type != drm_buffer_type) { - ret = -EINVAL; - goto out_err; - } - - *bo = drm_user_object_entry(uo, struct drm_buffer_object, base); - ret = 0; -out_err: - mutex_unlock(&dev->struct_mutex); - return ret; -} -EXPORT_SYMBOL(drm_get_buffer_object); diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 9113fa54..2c3e29f0 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -146,36 +146,6 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), - DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_REFERENCE, drm_fence_reference_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_UNREFERENCE, drm_fence_unreference_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_SIGNALED, drm_fence_signaled_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_FLUSH, drm_fence_flush_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_WAIT, drm_fence_wait_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_EMIT, drm_fence_emit_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_FENCE_BUFFERS, drm_fence_buffers_ioctl, DRM_AUTH), - - DRM_IOCTL_DEF(DRM_IOCTL_BO_CREATE, drm_bo_create_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_MAP, drm_bo_map_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_UNMAP, drm_bo_unmap_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_REFERENCE, drm_bo_reference_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_UNREFERENCE, drm_bo_unreference_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0), - - DRM_IOCTL_DEF(DRM_IOCTL_MM_INFO, drm_mm_info_ioctl, 0), - DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0), DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 7c78e09f..7130d1b0 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -134,8 +134,8 @@ void drm_fence_handler(struct drm_device *dev, uint32_t fence_class, if (new_type) { fence->signaled_types |= new_type; - DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n", - fence->base.hash.key, fence->signaled_types); + DRM_DEBUG("Fence %p signaled 0x%08x\n", + fence, fence->signaled_types); if (driver->needed_flush) fc->pending_flush |= driver->needed_flush(fence); @@ -147,8 +147,8 @@ void drm_fence_handler(struct drm_device *dev, uint32_t fence_class, fc->waiting_types |= fence->waiting_types & ~fence->signaled_types; if (!(fence->type & ~fence->signaled_types)) { - DRM_DEBUG("Fence completely signaled 0x%08lx\n", - fence->base.hash.key); + DRM_DEBUG("Fence completely signaled %p\n", + fence); list_del_init(&fence->ring); } } @@ -196,10 +196,9 @@ void drm_fence_usage_deref_locked(struct drm_fence_object **fence) *fence = NULL; if (atomic_dec_and_test(&tmp_fence->usage)) { drm_fence_unring(dev, &tmp_fence->ring); - DRM_DEBUG("Destroyed a fence object 0x%08lx\n", - tmp_fence->base.hash.key); + DRM_DEBUG("Destroyed a fence object %p\n", + tmp_fence); atomic_dec(&fm->count); - BUG_ON(!list_empty(&tmp_fence->base.list)); drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE); } } @@ -217,7 +216,6 @@ void drm_fence_usage_deref_unlocked(struct drm_fence_object **fence) if (atomic_read(&tmp_fence->usage) == 0) { drm_fence_unring(dev, &tmp_fence->ring); atomic_dec(&fm->count); - BUG_ON(!list_empty(&tmp_fence->base.list)); drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE); } mutex_unlock(&dev->struct_mutex); @@ -244,15 +242,6 @@ void drm_fence_reference_unlocked(struct drm_fence_object **dst, } EXPORT_SYMBOL(drm_fence_reference_unlocked); -static void drm_fence_object_destroy(struct drm_file *priv, - struct drm_user_object *base) -{ - struct drm_fence_object *fence = - drm_user_object_entry(base, struct drm_fence_object, base); - - drm_fence_usage_deref_locked(&fence); -} - int drm_fence_object_signaled(struct drm_fence_object *fence, uint32_t mask) { unsigned long flags; @@ -477,7 +466,6 @@ static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class, * Avoid hitting BUG() for kernel-only fence objects. */ - INIT_LIST_HEAD(&fence->base.list); fence->fence_class = fence_class; fence->type = type; fence->signaled_types = 0; @@ -493,26 +481,6 @@ static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class, return ret; } -int drm_fence_add_user_object(struct drm_file *priv, - struct drm_fence_object *fence, int shareable) -{ - struct drm_device *dev = priv->minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm_add_user_object(priv, &fence->base, shareable); - if (ret) - goto out; - atomic_inc(&fence->usage); - fence->base.type = drm_fence_type; - fence->base.remove = &drm_fence_object_destroy; - DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key); -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} -EXPORT_SYMBOL(drm_fence_add_user_object); - int drm_fence_object_create(struct drm_device *dev, uint32_t fence_class, uint32_t type, unsigned flags, struct drm_fence_object **c_fence) @@ -569,261 +537,7 @@ void drm_fence_manager_init(struct drm_device *dev) write_unlock_irqrestore(&fm->lock, flags); } -void drm_fence_fill_arg(struct drm_fence_object *fence, - struct drm_fence_arg *arg) -{ - struct drm_device *dev = fence->dev; - struct drm_fence_manager *fm = &dev->fm; - unsigned long irq_flags; - - read_lock_irqsave(&fm->lock, irq_flags); - arg->handle = fence->base.hash.key; - arg->fence_class = fence->fence_class; - arg->type = fence->type; - arg->signaled = fence->signaled_types; - arg->error = fence->error; - arg->sequence = fence->sequence; - read_unlock_irqrestore(&fm->lock, irq_flags); -} -EXPORT_SYMBOL(drm_fence_fill_arg); - void drm_fence_manager_takedown(struct drm_device *dev) { } -struct drm_fence_object *drm_lookup_fence_object(struct drm_file *priv, - uint32_t handle) -{ - struct drm_device *dev = priv->minor->dev; - struct drm_user_object *uo; - struct drm_fence_object *fence; - - mutex_lock(&dev->struct_mutex); - uo = drm_lookup_user_object(priv, handle); - if (!uo || (uo->type != drm_fence_type)) { - mutex_unlock(&dev->struct_mutex); - return NULL; - } - fence = drm_fence_reference_locked(drm_user_object_entry(uo, struct drm_fence_object, base)); - mutex_unlock(&dev->struct_mutex); - return fence; -} - -int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - struct drm_fence_object *fence; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - if (arg->flags & DRM_FENCE_FLAG_EMIT) - LOCK_TEST_WITH_RETURN(dev, file_priv); - ret = drm_fence_object_create(dev, arg->fence_class, - arg->type, arg->flags, &fence); - if (ret) - return ret; - ret = drm_fence_add_user_object(file_priv, fence, - arg->flags & - DRM_FENCE_FLAG_SHAREABLE); - if (ret) { - drm_fence_usage_deref_unlocked(&fence); - return ret; - } - - /* - * usage > 0. No need to lock dev->struct_mutex; - */ - - arg->handle = fence->base.hash.key; - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} - -int drm_fence_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - struct drm_fence_object *fence; - struct drm_user_object *uo; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - ret = drm_user_object_ref(file_priv, arg->handle, drm_fence_type, &uo); - if (ret) - return ret; - fence = drm_lookup_fence_object(file_priv, arg->handle); - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} - - -int drm_fence_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - return drm_user_object_unref(file_priv, arg->handle, drm_fence_type); -} - -int drm_fence_signaled_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - struct drm_fence_object *fence; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - fence = drm_lookup_fence_object(file_priv, arg->handle); - if (!fence) - return -EINVAL; - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} - -int drm_fence_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - struct drm_fence_object *fence; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - fence = drm_lookup_fence_object(file_priv, arg->handle); - if (!fence) - return -EINVAL; - ret = drm_fence_object_flush(fence, arg->type); - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} - - -int drm_fence_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - struct drm_fence_object *fence; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - fence = drm_lookup_fence_object(file_priv, arg->handle); - if (!fence) - return -EINVAL; - ret = drm_fence_object_wait(fence, - arg->flags & DRM_FENCE_FLAG_WAIT_LAZY, - 0, arg->type); - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} - - -int drm_fence_emit_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - struct drm_fence_object *fence; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - LOCK_TEST_WITH_RETURN(dev, file_priv); - fence = drm_lookup_fence_object(file_priv, arg->handle); - if (!fence) - return -EINVAL; - ret = drm_fence_object_emit(fence, arg->flags, arg->fence_class, - arg->type); - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} - -int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - int ret; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_arg *arg = data; - struct drm_fence_object *fence; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized\n"); - return -EINVAL; - } - LOCK_TEST_WITH_RETURN(dev, file_priv); - ret = drm_fence_buffer_objects(dev, NULL, arg->flags, - NULL, &fence); - if (ret) - return ret; - - if (!(arg->flags & DRM_FENCE_FLAG_NO_USER)) { - ret = drm_fence_add_user_object(file_priv, fence, - arg->flags & - DRM_FENCE_FLAG_SHAREABLE); - if (ret) - return ret; - } - - arg->handle = fence->base.hash.key; - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index 3b3a0a3c..8eb20b47 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -221,7 +221,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp, int minor_id = iminor(inode); struct drm_file *priv; int ret; - int i, j; if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */ @@ -246,22 +245,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->lock_count = 0; INIT_LIST_HEAD(&priv->lhead); - INIT_LIST_HEAD(&priv->refd_objects); INIT_LIST_HEAD(&priv->fbs); - for (i = 0; i < _DRM_NO_REF_TYPES; ++i) { - ret = drm_ht_create(&priv->refd_object_hash[i], - DRM_FILE_HASH_ORDER); - if (ret) - break; - } - - if (ret) { - for (j = 0; j < i; ++j) - drm_ht_remove(&priv->refd_object_hash[j]); - goto out_free; - } - if (dev->driver->driver_features & DRIVER_GEM) drm_gem_open(dev, priv); @@ -346,33 +331,6 @@ int drm_fasync(int fd, struct file *filp, int on) } EXPORT_SYMBOL(drm_fasync); -static void drm_object_release(struct file *filp) -{ - struct drm_file *priv = filp->private_data; - struct list_head *head; - struct drm_ref_object *ref_object; - int i; - - /* - * Free leftover ref objects created by me. Note that we cannot use - * list_for_each() here, as the struct_mutex may be temporarily - * released by the remove_() functions, and thus the lists may be - * altered. - * Also, a drm_remove_ref_object() will not remove it - * from the list unless its refcount is 1. - */ - - head = &priv->refd_objects; - while (head->next != head) { - ref_object = list_entry(head->next, struct drm_ref_object, list); - drm_remove_ref_object(priv, ref_object); - head = &priv->refd_objects; - } - - for (i = 0; i < _DRM_NO_REF_TYPES; ++i) - drm_ht_remove(&priv->refd_object_hash[i]); -} - /** * Release file. * @@ -512,7 +470,6 @@ int drm_release(struct inode *inode, struct file *filp) file_priv->is_master = 0; mutex_lock(&dev->struct_mutex); - drm_object_release(filp); list_del(&file_priv->lhead); diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c deleted file mode 100644 index 2994b716..00000000 --- a/linux-core/drm_object.c +++ /dev/null @@ -1,294 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellström - */ - -#include "drmP.h" - -int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item, - int shareable) -{ - struct drm_device *dev = priv->minor->dev; - int ret; - - DRM_ASSERT_LOCKED(&dev->struct_mutex); - - /* The refcount will be bumped to 1 when we add the ref object below. */ - atomic_set(&item->refcount, 0); - item->shareable = shareable; - item->owner = priv; - - ret = drm_ht_just_insert_please(&dev->object_hash, &item->hash, - (unsigned long)item, 31, 0, 0); - if (ret) - return ret; - - ret = drm_add_ref_object(priv, item, _DRM_REF_USE); - if (ret) - ret = drm_ht_remove_item(&dev->object_hash, &item->hash); - - return ret; -} -EXPORT_SYMBOL(drm_add_user_object); - -struct drm_user_object *drm_lookup_user_object(struct drm_file *priv, uint32_t key) -{ - struct drm_device *dev = priv->minor->dev; - struct drm_hash_item *hash; - int ret; - struct drm_user_object *item; - - DRM_ASSERT_LOCKED(&dev->struct_mutex); - - ret = drm_ht_find_item(&dev->object_hash, key, &hash); - if (ret) - return NULL; - - item = drm_hash_entry(hash, struct drm_user_object, hash); - - if (priv != item->owner) { - struct drm_open_hash *ht = &priv->refd_object_hash[_DRM_REF_USE]; - ret = drm_ht_find_item(ht, (unsigned long)item, &hash); - if (ret) { - DRM_ERROR("Object not registered for usage\n"); - return NULL; - } - } - return item; -} -EXPORT_SYMBOL(drm_lookup_user_object); - -static void drm_deref_user_object(struct drm_file *priv, struct drm_user_object *item) -{ - struct drm_device *dev = priv->minor->dev; - int ret; - - if (atomic_dec_and_test(&item->refcount)) { - ret = drm_ht_remove_item(&dev->object_hash, &item->hash); - BUG_ON(ret); - item->remove(priv, item); - } -} - -static int drm_object_ref_action(struct drm_file *priv, struct drm_user_object *ro, - enum drm_ref_type action) -{ - int ret = 0; - - switch (action) { - case _DRM_REF_USE: - atomic_inc(&ro->refcount); - break; - default: - if (!ro->ref_struct_locked) { - break; - } else { - ro->ref_struct_locked(priv, ro, action); - } - } - return ret; -} - -int drm_add_ref_object(struct drm_file *priv, struct drm_user_object *referenced_object, - enum drm_ref_type ref_action) -{ - int ret = 0; - struct drm_ref_object *item; - struct drm_open_hash *ht = &priv->refd_object_hash[ref_action]; - - DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); - if (!referenced_object->shareable && priv != referenced_object->owner) { - DRM_ERROR("Not allowed to reference this object\n"); - return -EINVAL; - } - - /* - * If this is not a usage reference, Check that usage has been registered - * first. Otherwise strange things may happen on destruction. - */ - - if ((ref_action != _DRM_REF_USE) && priv != referenced_object->owner) { - item = - drm_lookup_ref_object(priv, referenced_object, - _DRM_REF_USE); - if (!item) { - DRM_ERROR - ("Object not registered for usage by this client\n"); - return -EINVAL; - } - } - - if (NULL != - (item = - drm_lookup_ref_object(priv, referenced_object, ref_action))) { - atomic_inc(&item->refcount); - return drm_object_ref_action(priv, referenced_object, - ref_action); - } - - item = drm_ctl_calloc(1, sizeof(*item), DRM_MEM_OBJECTS); - if (item == NULL) { - DRM_ERROR("Could not allocate reference object\n"); - return -ENOMEM; - } - - atomic_set(&item->refcount, 1); - item->hash.key = (unsigned long)referenced_object; - ret = drm_ht_insert_item(ht, &item->hash); - item->unref_action = ref_action; - - if (ret) - goto out; - - list_add(&item->list, &priv->refd_objects); - ret = drm_object_ref_action(priv, referenced_object, ref_action); -out: - return ret; -} - -struct drm_ref_object *drm_lookup_ref_object(struct drm_file *priv, - struct drm_user_object *referenced_object, - enum drm_ref_type ref_action) -{ - struct drm_hash_item *hash; - int ret; - - DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); - ret = drm_ht_find_item(&priv->refd_object_hash[ref_action], - (unsigned long)referenced_object, &hash); - if (ret) - return NULL; - - return drm_hash_entry(hash, struct drm_ref_object, hash); -} -EXPORT_SYMBOL(drm_lookup_ref_object); - -static void drm_remove_other_references(struct drm_file *priv, - struct drm_user_object *ro) -{ - int i; - struct drm_open_hash *ht; - struct drm_hash_item *hash; - struct drm_ref_object *item; - - for (i = _DRM_REF_USE + 1; i < _DRM_NO_REF_TYPES; ++i) { - ht = &priv->refd_object_hash[i]; - while (!drm_ht_find_item(ht, (unsigned long)ro, &hash)) { - item = drm_hash_entry(hash, struct drm_ref_object, hash); - drm_remove_ref_object(priv, item); - } - } -} - -void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item) -{ - int ret; - struct drm_user_object *user_object = (struct drm_user_object *) item->hash.key; - struct drm_open_hash *ht = &priv->refd_object_hash[item->unref_action]; - enum drm_ref_type unref_action; - - DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); - unref_action = item->unref_action; - if (atomic_dec_and_test(&item->refcount)) { - ret = drm_ht_remove_item(ht, &item->hash); - BUG_ON(ret); - list_del_init(&item->list); - if (unref_action == _DRM_REF_USE) - drm_remove_other_references(priv, user_object); - drm_ctl_free(item, sizeof(*item), DRM_MEM_OBJECTS); - } - - switch (unref_action) { - case _DRM_REF_USE: - drm_deref_user_object(priv, user_object); - break; - default: - BUG_ON(!user_object->unref); - user_object->unref(priv, user_object, unref_action); - break; - } - -} -EXPORT_SYMBOL(drm_remove_ref_object); - -int drm_user_object_ref(struct drm_file *priv, uint32_t user_token, - enum drm_object_type type, struct drm_user_object **object) -{ - struct drm_device *dev = priv->minor->dev; - struct drm_user_object *uo; - struct drm_hash_item *hash; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm_ht_find_item(&dev->object_hash, user_token, &hash); - if (ret) { - DRM_ERROR("Could not find user object to reference.\n"); - goto out_err; - } - uo = drm_hash_entry(hash, struct drm_user_object, hash); - if (uo->type != type) { - ret = -EINVAL; - goto out_err; - } - ret = drm_add_ref_object(priv, uo, _DRM_REF_USE); - if (ret) - goto out_err; - mutex_unlock(&dev->struct_mutex); - *object = uo; - return 0; -out_err: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -int drm_user_object_unref(struct drm_file *priv, uint32_t user_token, - enum drm_object_type type) -{ - struct drm_device *dev = priv->minor->dev; - struct drm_user_object *uo; - struct drm_ref_object *ro; - int ret; - - mutex_lock(&dev->struct_mutex); - uo = drm_lookup_user_object(priv, user_token); - if (!uo || (uo->type != type)) { - ret = -EINVAL; - goto out_err; - } - ro = drm_lookup_ref_object(priv, uo, _DRM_REF_USE); - if (!ro) { - ret = -EINVAL; - goto out_err; - } - drm_remove_ref_object(priv, ro); - mutex_unlock(&dev->struct_mutex); - return 0; -out_err: - mutex_unlock(&dev->struct_mutex); - return ret; -} diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 96cfc113..032687f7 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -34,110 +34,201 @@ struct drm_device; struct drm_bo_mem_reg; -/*************************************************** - * User space objects. (drm_object.c) - */ - -#define drm_user_object_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) - -enum drm_object_type { - drm_fence_type, - drm_buffer_type, - drm_lock_type, - /* - * Add other user space object types here. - */ - drm_driver_type0 = 256, - drm_driver_type1, - drm_driver_type2, - drm_driver_type3, - drm_driver_type4 -}; - -/* - * A user object is a structure that helps the drm give out user handles - * to kernel internal objects and to keep track of these objects so that - * they can be destroyed, for example when the user space process exits. - * Designed to be accessible using a user space 32-bit handle. - */ - -struct drm_user_object { - struct drm_hash_item hash; - struct list_head list; - enum drm_object_type type; - atomic_t refcount; - int shareable; - struct drm_file *owner; - void (*ref_struct_locked) (struct drm_file *priv, - struct drm_user_object *obj, - enum drm_ref_type ref_action); - void (*unref) (struct drm_file *priv, struct drm_user_object *obj, - enum drm_ref_type unref_action); - void (*remove) (struct drm_file *priv, struct drm_user_object *obj); -}; - -/* - * A ref object is a structure which is used to - * keep track of references to user objects and to keep track of these - * references so that they can be destroyed for example when the user space - * process exits. Designed to be accessible using a pointer to the _user_ object. - */ - -struct drm_ref_object { - struct drm_hash_item hash; - struct list_head list; - atomic_t refcount; - enum drm_ref_type unref_action; -}; - +#define DRM_FENCE_FLAG_EMIT 0x00000001 +#define DRM_FENCE_FLAG_SHAREABLE 0x00000002 /** - * Must be called with the struct_mutex held. + * On hardware with no interrupt events for operation completion, + * indicates that the kernel should sleep while waiting for any blocking + * operation to complete rather than spinning. + * + * Has no effect otherwise. + */ +#define DRM_FENCE_FLAG_WAIT_LAZY 0x00000004 +#define DRM_FENCE_FLAG_NO_USER 0x00000010 + +/* Reserved for driver use */ +#define DRM_FENCE_MASK_DRIVER 0xFF000000 + +#define DRM_FENCE_TYPE_EXE 0x00000001 + +struct drm_fence_arg { + unsigned int handle; + unsigned int fence_class; + unsigned int type; + unsigned int flags; + unsigned int signaled; + unsigned int error; + unsigned int sequence; + unsigned int pad64; + uint64_t expand_pad[2]; /*Future expansion */ +}; + +/* Buffer permissions, referring to how the GPU uses the buffers. + * these translate to fence types used for the buffers. + * Typically a texture buffer is read, A destination buffer is write and + * a command (batch-) buffer is exe. Can be or-ed together. */ -extern int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item, - int shareable); +#define DRM_BO_FLAG_READ (1ULL << 0) +#define DRM_BO_FLAG_WRITE (1ULL << 1) +#define DRM_BO_FLAG_EXE (1ULL << 2) + +/* + * All of the bits related to access mode + */ +#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE) +/* + * Status flags. Can be read to determine the actual state of a buffer. + * Can also be set in the buffer mask before validation. + */ + +/* + * Mask: Never evict this buffer. Not even with force. This type of buffer is only + * available to root and must be manually removed before buffer manager shutdown + * or lock. + * Flags: Acknowledge + */ +#define DRM_BO_FLAG_NO_EVICT (1ULL << 4) + +/* + * Mask: Require that the buffer is placed in mappable memory when validated. + * If not set the buffer may or may not be in mappable memory when validated. + * Flags: If set, the buffer is in mappable memory. + */ +#define DRM_BO_FLAG_MAPPABLE (1ULL << 5) + +/* Mask: The buffer should be shareable with other processes. + * Flags: The buffer is shareable with other processes. + */ +#define DRM_BO_FLAG_SHAREABLE (1ULL << 6) + +/* Mask: If set, place the buffer in cache-coherent memory if available. + * If clear, never place the buffer in cache coherent memory if validated. + * Flags: The buffer is currently in cache-coherent memory. + */ +#define DRM_BO_FLAG_CACHED (1ULL << 7) + +/* Mask: Make sure that every time this buffer is validated, + * it ends up on the same location provided that the memory mask is the same. + * The buffer will also not be evicted when claiming space for + * other buffers. Basically a pinned buffer but it may be thrown out as + * part of buffer manager shutdown or locking. + * Flags: Acknowledge. + */ +#define DRM_BO_FLAG_NO_MOVE (1ULL << 8) + +/* Mask: Make sure the buffer is in cached memory when mapped. In conjunction + * with DRM_BO_FLAG_CACHED it also allows the buffer to be bound into the GART + * with unsnooped PTEs instead of snooped, by using chipset-specific cache + * flushing at bind time. A better name might be DRM_BO_FLAG_TT_UNSNOOPED, + * as the eviction to local memory (TTM unbind) on map is just a side effect + * to prevent aggressive cache prefetch from the GPU disturbing the cache + * management that the DRM is doing. + * + * Flags: Acknowledge. + * Buffers allocated with this flag should not be used for suballocators + * This type may have issues on CPUs with over-aggressive caching + * http://marc.info/?l=linux-kernel&m=102376926732464&w=2 + */ +#define DRM_BO_FLAG_CACHED_MAPPED (1ULL << 19) + + +/* Mask: Force DRM_BO_FLAG_CACHED flag strictly also if it is set. + * Flags: Acknowledge. + */ +#define DRM_BO_FLAG_FORCE_CACHING (1ULL << 13) + +/* + * Mask: Force DRM_BO_FLAG_MAPPABLE flag strictly also if it is clear. + * Flags: Acknowledge. + */ +#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14) +#define DRM_BO_FLAG_TILE (1ULL << 15) + +/* + * Memory type flags that can be or'ed together in the mask, but only + * one appears in flags. + */ + +/* System memory */ +#define DRM_BO_FLAG_MEM_LOCAL (1ULL << 24) +/* Translation table memory */ +#define DRM_BO_FLAG_MEM_TT (1ULL << 25) +/* Vram memory */ +#define DRM_BO_FLAG_MEM_VRAM (1ULL << 26) +/* Up to the driver to define. */ +#define DRM_BO_FLAG_MEM_PRIV0 (1ULL << 27) +#define DRM_BO_FLAG_MEM_PRIV1 (1ULL << 28) +#define DRM_BO_FLAG_MEM_PRIV2 (1ULL << 29) +#define DRM_BO_FLAG_MEM_PRIV3 (1ULL << 30) +#define DRM_BO_FLAG_MEM_PRIV4 (1ULL << 31) +/* We can add more of these now with a 64-bit flag type */ + +/* + * This is a mask covering all of the memory type flags; easier to just + * use a single constant than a bunch of | values. It covers + * DRM_BO_FLAG_MEM_LOCAL through DRM_BO_FLAG_MEM_PRIV4 + */ +#define DRM_BO_MASK_MEM 0x00000000FF000000ULL +/* + * This adds all of the CPU-mapping options in with the memory + * type to label all bits which change how the page gets mapped + */ +#define DRM_BO_MASK_MEMTYPE (DRM_BO_MASK_MEM | \ + DRM_BO_FLAG_CACHED_MAPPED | \ + DRM_BO_FLAG_CACHED | \ + DRM_BO_FLAG_MAPPABLE) + +/* Driver-private flags */ +#define DRM_BO_MASK_DRIVER 0xFFFF000000000000ULL + +/* + * Don't block on validate and map. Instead, return EBUSY. + */ +#define DRM_BO_HINT_DONT_BLOCK 0x00000002 +/* + * Don't place this buffer on the unfenced list. This means + * that the buffer will not end up having a fence associated + * with it as a result of this operation + */ +#define DRM_BO_HINT_DONT_FENCE 0x00000004 /** - * Must be called with the struct_mutex held. + * On hardware with no interrupt events for operation completion, + * indicates that the kernel should sleep while waiting for any blocking + * operation to complete rather than spinning. + * + * Has no effect otherwise. */ - -extern struct drm_user_object *drm_lookup_user_object(struct drm_file *priv, - uint32_t key); - +#define DRM_BO_HINT_WAIT_LAZY 0x00000008 /* - * Must be called with the struct_mutex held. May temporarily release it. + * The client has compute relocations refering to this buffer using the + * offset in the presumed_offset field. If that offset ends up matching + * where this buffer lands, the kernel is free to skip executing those + * relocations */ +#define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010 -extern int drm_add_ref_object(struct drm_file *priv, - struct drm_user_object *referenced_object, - enum drm_ref_type ref_action); -/* - * Must be called with the struct_mutex held. - */ +#define DRM_BO_MEM_LOCAL 0 +#define DRM_BO_MEM_TT 1 +#define DRM_BO_MEM_VRAM 2 +#define DRM_BO_MEM_PRIV0 3 +#define DRM_BO_MEM_PRIV1 4 +#define DRM_BO_MEM_PRIV2 5 +#define DRM_BO_MEM_PRIV3 6 +#define DRM_BO_MEM_PRIV4 7 -struct drm_ref_object *drm_lookup_ref_object(struct drm_file *priv, - struct drm_user_object *referenced_object, - enum drm_ref_type ref_action); -/* - * Must be called with the struct_mutex held. - * If "item" has been obtained by a call to drm_lookup_ref_object. You may not - * release the struct_mutex before calling drm_remove_ref_object. - * This function may temporarily release the struct_mutex. - */ +#define DRM_BO_MEM_TYPES 8 /* For now. */ + +#define DRM_BO_LOCK_UNLOCK_BM (1 << 0) +#define DRM_BO_LOCK_IGNORE_NO_EVICT (1 << 1) -extern void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item); -extern int drm_user_object_ref(struct drm_file *priv, uint32_t user_token, - enum drm_object_type type, - struct drm_user_object **object); -extern int drm_user_object_unref(struct drm_file *priv, uint32_t user_token, - enum drm_object_type type); /*************************************************** * Fence objects. (drm_fence.c) */ struct drm_fence_object { - struct drm_user_object base; struct drm_device *dev; atomic_t usage; @@ -470,7 +561,6 @@ enum drm_bo_type { struct drm_buffer_object { struct drm_device *dev; - struct drm_user_object base; /* * If there is a possibility that the usage variable is zero, @@ -546,7 +636,7 @@ struct drm_mem_type_manager { }; struct drm_bo_lock { - struct drm_user_object base; + // struct drm_user_object base; wait_queue_head_t queue; atomic_t write_lock_pending; atomic_t readers; @@ -655,22 +745,10 @@ struct drm_bo_driver { /* * buffer objects (drm_bo.c) */ -extern int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int drm_bo_do_validate(struct drm_buffer_object *bo, + uint64_t flags, uint64_t mask, uint32_t hint, + uint32_t fence_class); extern int drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, int pin); -extern int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_setstatus_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mm_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_version_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_driver_finish(struct drm_device *dev); extern int drm_bo_driver_init(struct drm_device *dev); extern int drm_bo_pci_offset(struct drm_device *dev, @@ -707,18 +785,9 @@ extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type, int kern_c extern int drm_bo_init_mm(struct drm_device *dev, unsigned type, unsigned long p_offset, unsigned long p_size, int kern_init); -extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, - uint64_t flags, uint64_t mask, uint32_t hint, - uint32_t fence_class, - struct drm_bo_info_rep *rep, - struct drm_buffer_object **bo_rep); extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv, uint32_t handle, int check_owner); -extern int drm_bo_do_validate(struct drm_buffer_object *bo, - uint64_t flags, uint64_t mask, uint32_t hint, - uint32_t fence_class, - struct drm_bo_info_rep *rep); extern int drm_bo_evict_cached(struct drm_buffer_object *bo); extern void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo); @@ -766,8 +835,6 @@ extern int drm_bo_pfn_prot(struct drm_buffer_object *bo, unsigned long dst_offset, unsigned long *pfn, pgprot_t *prot); -extern void drm_bo_fill_rep_arg(struct drm_buffer_object *bo, - struct drm_bo_info_rep *rep); /* diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 80a8ff5d..b58a1ada 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -72,7 +72,7 @@ void drm_ttm_cache_flush(struct page *pages[], unsigned long num_pages) return; } #endif - if (on_each_cpu(drm_ttm_ipi_handler, NULL, 1, 1) != 0) + if (on_each_cpu(drm_ttm_ipi_handler, NULL,1) != 0) DRM_ERROR("Timed out waiting for drm cache flush.\n"); } EXPORT_SYMBOL(drm_ttm_cache_flush); diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c deleted file mode 100644 index 4224b737..00000000 --- a/linux-core/i915_buffer.c +++ /dev/null @@ -1,311 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström - */ - -#include "drmP.h" -#include "i915_drm.h" -#include "i915_drv.h" - -struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev) -{ - return drm_agp_init_ttm(dev); -} - -int i915_fence_type(struct drm_buffer_object *bo, - uint32_t *fclass, - uint32_t *type) -{ - if (bo->mem.proposed_flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) - *type = 3; - else - *type = 1; - return 0; -} - -int i915_invalidate_caches(struct drm_device *dev, uint64_t flags) -{ - /* - * FIXME: Only emit once per batchbuffer submission. - */ - - uint32_t flush_cmd = MI_NO_WRITE_FLUSH; - - if (flags & DRM_BO_FLAG_READ) - flush_cmd |= MI_READ_FLUSH; - if (flags & DRM_BO_FLAG_EXE) - flush_cmd |= MI_EXE_FLUSH; - - return i915_emit_mi_flush(dev, flush_cmd); -} - -int i915_init_mem_type(struct drm_device *dev, uint32_t type, - struct drm_mem_type_manager *man) -{ - switch (type) { - case DRM_BO_MEM_LOCAL: - man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_MEMTYPE_CACHED; - man->drm_bus_maptype = 0; - man->gpu_offset = 0; - break; - case DRM_BO_MEM_TT: - if (!(drm_core_has_AGP(dev) && dev->agp)) { - DRM_ERROR("AGP is not enabled for memory type %u\n", - (unsigned)type); - return -EINVAL; - } - man->io_offset = dev->agp->agp_info.aper_base; - man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024; - man->io_addr = NULL; - man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; - man->drm_bus_maptype = _DRM_AGP; - man->gpu_offset = 0; - break; - case DRM_BO_MEM_VRAM: - if (!(drm_core_has_AGP(dev) && dev->agp)) { - DRM_ERROR("AGP is not enabled for memory type %u\n", - (unsigned)type); - return -EINVAL; - } - man->io_offset = dev->agp->agp_info.aper_base; - man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024; - man->io_addr = NULL; - man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_NEEDS_IOREMAP; - man->drm_bus_maptype = _DRM_AGP; - man->gpu_offset = 0; - break; - case DRM_BO_MEM_PRIV0: /* for OS preallocated space */ - DRM_ERROR("PRIV0 not used yet.\n"); - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; -} - -/* - * i915_evict_flags: - * - * @bo: the buffer object to be evicted - * - * Return the bo flags for a buffer which is not mapped to the hardware. - * These will be placed in proposed_flags so that when the move is - * finished, they'll end up in bo->mem.flags - */ -uint64_t i915_evict_flags(struct drm_buffer_object *bo) -{ - switch (bo->mem.mem_type) { - case DRM_BO_MEM_LOCAL: - case DRM_BO_MEM_TT: - return DRM_BO_FLAG_MEM_LOCAL; - default: - return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED; - } -} - -#if 0 /* See comment below */ - -static void i915_emit_copy_blit(struct drm_device * dev, - uint32_t src_offset, - uint32_t dst_offset, - uint32_t pages, int direction) -{ - uint32_t cur_pages; - uint32_t stride = PAGE_SIZE; - struct drm_i915_private *dev_priv = dev->dev_private; - RING_LOCALS; - - if (!dev_priv) - return; - - i915_kernel_lost_context(dev); - while (pages > 0) { - cur_pages = pages; - if (cur_pages > 2048) - cur_pages = 2048; - pages -= cur_pages; - - BEGIN_LP_RING(6); - OUT_RING(SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - OUT_RING((stride & 0xffff) | (0xcc << 16) | (1 << 24) | - (1 << 25) | (direction ? (1 << 30) : 0)); - OUT_RING((cur_pages << 16) | PAGE_SIZE); - OUT_RING(dst_offset); - OUT_RING(stride & 0xffff); - OUT_RING(src_offset); - ADVANCE_LP_RING(); - } - return; -} - -static int i915_move_blit(struct drm_buffer_object * bo, - int evict, int no_wait, struct drm_bo_mem_reg * new_mem) -{ - struct drm_bo_mem_reg *old_mem = &bo->mem; - int dir = 0; - - if ((old_mem->mem_type == new_mem->mem_type) && - (new_mem->mm_node->start < - old_mem->mm_node->start + old_mem->mm_node->size)) { - dir = 1; - } - - i915_emit_copy_blit(bo->dev, - old_mem->mm_node->start << PAGE_SHIFT, - new_mem->mm_node->start << PAGE_SHIFT, - new_mem->num_pages, dir); - - i915_emit_mi_flush(bo->dev, MI_READ_FLUSH | MI_EXE_FLUSH); - - return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0, - DRM_FENCE_TYPE_EXE | - DRM_I915_FENCE_TYPE_RW, - DRM_I915_FENCE_FLAG_FLUSHED, new_mem); -} - -/* - * Flip destination ttm into cached-coherent AGP, - * then blit and subsequently move out again. - */ - -static int i915_move_flip(struct drm_buffer_object * bo, - int evict, int no_wait, struct drm_bo_mem_reg * new_mem) -{ - struct drm_device *dev = bo->dev; - struct drm_bo_mem_reg tmp_mem; - int ret; - - tmp_mem = *new_mem; - tmp_mem.mm_node = NULL; - tmp_mem.mask = DRM_BO_FLAG_MEM_TT | - DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING; - - ret = drm_bo_mem_space(bo, &tmp_mem, no_wait); - if (ret) - return ret; - - ret = drm_bind_ttm(bo->ttm, &tmp_mem); - if (ret) - goto out_cleanup; - - ret = i915_move_blit(bo, 1, no_wait, &tmp_mem); - if (ret) - goto out_cleanup; - - ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem); -out_cleanup: - if (tmp_mem.mm_node) { - mutex_lock(&dev->struct_mutex); - if (tmp_mem.mm_node != bo->pinned_node) - drm_mm_put_block(tmp_mem.mm_node); - tmp_mem.mm_node = NULL; - mutex_unlock(&dev->struct_mutex); - } - return ret; -} - -#endif - -/* - * Disable i915_move_flip for now, since we can't guarantee that the hardware - * lock is held here. To re-enable we need to make sure either - * a) The X server is using DRM to submit commands to the ring, or - * b) DRM can use the HP ring for these blits. This means i915 needs to - * implement a new ring submission mechanism and fence class. - */ -int i915_move(struct drm_buffer_object *bo, - int evict, int no_wait, struct drm_bo_mem_reg *new_mem) -{ - struct drm_bo_mem_reg *old_mem = &bo->mem; - - if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { - if (1) /*i915_move_flip(bo, evict, no_wait, new_mem)*/ - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } else { - if (1) /*i915_move_blit(bo, evict, no_wait, new_mem)*/ - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } - return 0; -} - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) -static inline void clflush(volatile void *__p) -{ - asm volatile("clflush %0" : "+m" (*(char __force *)__p)); -} -#endif - -static inline void drm_cache_flush_addr(void *virt) -{ -#ifdef cpu_has_clflush - int i; - - for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) - clflush(virt+i); -#endif -} - -static inline void drm_cache_flush_page(struct page *p) -{ - drm_cache_flush_addr(page_address(p)); -} - -void i915_flush_ttm(struct drm_ttm *ttm) -{ - int i; - - if (!ttm) - return; - - DRM_MEMORYBARRIER(); - -#ifdef CONFIG_X86_32 -#ifndef cpu_has_clflush -#define cpu_has_clflush 0 -#endif - /* Hopefully nobody has built an x86-64 processor without clflush */ - if (!cpu_has_clflush) { - wbinvd(); - DRM_MEMORYBARRIER(); - return; - } -#endif - - for (i = ttm->num_pages - 1; i >= 0; i--) - drm_cache_flush_page(drm_ttm_get_page(ttm, i)); - - DRM_MEMORYBARRIER(); -} diff --git a/linux-core/i915_execbuf.c b/linux-core/i915_execbuf.c deleted file mode 100644 index 932882dd..00000000 --- a/linux-core/i915_execbuf.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * Copyright 2003-2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Hellstrom - * Dave Airlie - * Keith Packard - * ... ? - */ - -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" - -#if DRM_DEBUG_CODE -#define DRM_DEBUG_RELOCATION (drm_debug != 0) -#else -#define DRM_DEBUG_RELOCATION 0 -#endif - -enum i915_buf_idle { - I915_RELOC_UNCHECKED, - I915_RELOC_IDLE, - I915_RELOC_BUSY -}; - -struct i915_relocatee_info { - struct drm_buffer_object *buf; - unsigned long offset; - uint32_t *data_page; - unsigned page_offset; - struct drm_bo_kmap_obj kmap; - int is_iomem; - int dst; - int idle; - int performed_ring_relocs; -#ifdef DRM_KMAP_ATOMIC_PROT_PFN - unsigned long pfn; - pgprot_t pg_prot; -#endif -}; - -struct drm_i915_validate_buffer { - struct drm_buffer_object *buffer; - int presumed_offset_correct; - void __user *data; - int ret; - enum i915_buf_idle idle; -}; - -/* - * I'd like to use MI_STORE_DATA_IMM here, but I can't make - * it work. Seems like GART writes are broken with that - * instruction. Also I'm not sure that MI_FLUSH will - * act as a memory barrier for that instruction. It will - * for this single dword 2D blit. - */ - -static void i915_emit_ring_reloc(struct drm_device *dev, uint32_t offset, - uint32_t value) -{ - struct drm_i915_private *dev_priv = - (struct drm_i915_private *)dev->dev_private; - - RING_LOCALS; - i915_kernel_lost_context(dev); - BEGIN_LP_RING(6); - OUT_RING((0x02 << 29) | (0x40 << 22) | (0x3 << 20) | (0x3)); - OUT_RING((0x3 << 24) | (0xF0 << 16) | (0x40)); - OUT_RING((0x1 << 16) | (0x4)); - OUT_RING(offset); - OUT_RING(value); - OUT_RING(0); - ADVANCE_LP_RING(); -} - -static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer - *buffers, unsigned num_buffers) -{ - while (num_buffers--) - drm_bo_usage_deref_locked(&buffers[num_buffers].buffer); -} - -int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, - struct drm_i915_validate_buffer *buffers, - struct i915_relocatee_info *relocatee, uint32_t * reloc) -{ - unsigned index; - unsigned long new_cmd_offset; - u32 val; - int ret, i; - int buf_index = -1; - - /* - * FIXME: O(relocs * buffers) complexity. - */ - - for (i = 0; i <= num_buffers; i++) - if (buffers[i].buffer) - if (reloc[2] == buffers[i].buffer->base.hash.key) - buf_index = i; - - if (buf_index == -1) { - DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]); - return -EINVAL; - } - - /* - * Short-circuit relocations that were correctly - * guessed by the client - */ - if (buffers[buf_index].presumed_offset_correct && !DRM_DEBUG_RELOCATION) - return 0; - - new_cmd_offset = reloc[0]; - if (!relocatee->data_page || - !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { - struct drm_bo_mem_reg *mem = &relocatee->buf->mem; - - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - relocatee->offset = new_cmd_offset; - - if (unlikely(relocatee->idle == I915_RELOC_UNCHECKED)) { - ret = drm_bo_wait(relocatee->buf, 0, 1, 0, 0); - if (ret) - return ret; - relocatee->idle = I915_RELOC_IDLE; - } - - if (unlikely((mem->mem_type != DRM_BO_MEM_LOCAL) && - (mem->flags & DRM_BO_FLAG_CACHED_MAPPED))) - drm_bo_evict_cached(relocatee->buf); - - ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, - 1, &relocatee->kmap); - if (ret) { - DRM_ERROR - ("Could not map command buffer to apply relocs\n %08lx", - new_cmd_offset); - return ret; - } - relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, - &relocatee->is_iomem); - relocatee->page_offset = (relocatee->offset & PAGE_MASK); - } - - val = buffers[buf_index].buffer->offset; - index = (reloc[0] - relocatee->page_offset) >> 2; - - /* add in validate */ - val = val + reloc[1]; - - if (DRM_DEBUG_RELOCATION) { - if (buffers[buf_index].presumed_offset_correct && - relocatee->data_page[index] != val) { - DRM_DEBUG - ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", - reloc[0], reloc[1], buf_index, - relocatee->data_page[index], val); - } - } - - if (relocatee->is_iomem) - iowrite32(val, relocatee->data_page + index); - else - relocatee->data_page[index] = val; - return 0; -} - -int i915_process_relocs(struct drm_file *file_priv, - uint32_t buf_handle, - uint32_t __user ** reloc_user_ptr, - struct i915_relocatee_info *relocatee, - struct drm_i915_validate_buffer *buffers, - uint32_t num_buffers) -{ - int ret, reloc_stride; - uint32_t cur_offset; - uint32_t reloc_count; - uint32_t reloc_type; - uint32_t reloc_buf_size; - uint32_t *reloc_buf = NULL; - int i; - - /* do a copy from user from the user ptr */ - ret = get_user(reloc_count, *reloc_user_ptr); - if (ret) { - DRM_ERROR("Could not map relocation buffer.\n"); - goto out; - } - - ret = get_user(reloc_type, (*reloc_user_ptr) + 1); - if (ret) { - DRM_ERROR("Could not map relocation buffer.\n"); - goto out; - } - - if (reloc_type != 0) { - DRM_ERROR("Unsupported relocation type requested\n"); - ret = -EINVAL; - goto out; - } - - reloc_buf_size = - (I915_RELOC_HEADER + - (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); - reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); - if (!reloc_buf) { - DRM_ERROR("Out of memory for reloc buffer\n"); - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) { - ret = -EFAULT; - goto out; - } - - /* get next relocate buffer handle */ - *reloc_user_ptr = (uint32_t *) * (unsigned long *)&reloc_buf[2]; - - reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ - - DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, - *reloc_user_ptr); - - for (i = 0; i < reloc_count; i++) { - cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE); - - ret = i915_apply_reloc(file_priv, num_buffers, buffers, - relocatee, reloc_buf + cur_offset); - if (ret) - goto out; - } - - out: - if (reloc_buf) - kfree(reloc_buf); - - if (relocatee->data_page) { - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - } - - return ret; -} - -static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, - uint32_t __user * reloc_user_ptr, - struct drm_i915_validate_buffer *buffers, - uint32_t buf_count) -{ - struct drm_device *dev = file_priv->minor->dev; - struct i915_relocatee_info relocatee; - int ret = 0; - int b; - - /* - * Short circuit relocations when all previous - * buffers offsets were correctly guessed by - * the client - */ - if (!DRM_DEBUG_RELOCATION) { - for (b = 0; b < buf_count; b++) - if (!buffers[b].presumed_offset_correct) - break; - - if (b == buf_count) - return 0; - } - - memset(&relocatee, 0, sizeof(relocatee)); - relocatee.idle = I915_RELOC_UNCHECKED; - - mutex_lock(&dev->struct_mutex); - relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1); - mutex_unlock(&dev->struct_mutex); - if (!relocatee.buf) { - DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle); - ret = -EINVAL; - goto out_err; - } - - mutex_lock(&relocatee.buf->mutex); - while (reloc_user_ptr) { - ret = - i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, - &relocatee, buffers, buf_count); - if (ret) { - DRM_ERROR("process relocs failed\n"); - goto out_err1; - } - } - - out_err1: - mutex_unlock(&relocatee.buf->mutex); - drm_bo_usage_deref_unlocked(&relocatee.buf); - out_err: - return ret; -} - -static void i915_clear_relocatee(struct i915_relocatee_info *relocatee) -{ - if (relocatee->data_page) { -#ifndef DRM_KMAP_ATOMIC_PROT_PFN - drm_bo_kunmap(&relocatee->kmap); -#else - kunmap_atomic(relocatee->data_page, KM_USER0); -#endif - relocatee->data_page = NULL; - } - relocatee->buf = NULL; - relocatee->dst = ~0; -} - -static int i915_update_relocatee(struct i915_relocatee_info *relocatee, - struct drm_i915_validate_buffer *buffers, - unsigned int dst, unsigned long dst_offset) -{ - int ret; - - if (unlikely(dst != relocatee->dst || NULL == relocatee->buf)) { - i915_clear_relocatee(relocatee); - relocatee->dst = dst; - relocatee->buf = buffers[dst].buffer; - relocatee->idle = buffers[dst].idle; - - /* - * Check for buffer idle. If the buffer is busy, revert to - * ring relocations. - */ - - if (relocatee->idle == I915_RELOC_UNCHECKED) { - preempt_enable(); - mutex_lock(&relocatee->buf->mutex); - - ret = drm_bo_wait(relocatee->buf, 0, 1, 1, 0); - if (ret == 0) - relocatee->idle = I915_RELOC_IDLE; - else { - relocatee->idle = I915_RELOC_BUSY; - relocatee->performed_ring_relocs = 1; - } - mutex_unlock(&relocatee->buf->mutex); - preempt_disable(); - buffers[dst].idle = relocatee->idle; - } - } - - if (relocatee->idle == I915_RELOC_BUSY) - return 0; - - if (unlikely(dst_offset > relocatee->buf->num_pages * PAGE_SIZE)) { - DRM_ERROR("Relocation destination out of bounds.\n"); - return -EINVAL; - } - if (unlikely(!drm_bo_same_page(relocatee->page_offset, dst_offset) || - NULL == relocatee->data_page)) { -#ifdef DRM_KMAP_ATOMIC_PROT_PFN - if (NULL != relocatee->data_page) { - kunmap_atomic(relocatee->data_page, KM_USER0); - relocatee->data_page = NULL; - } - ret = drm_bo_pfn_prot(relocatee->buf, dst_offset, - &relocatee->pfn, &relocatee->pg_prot); - if (ret) { - DRM_ERROR("Can't map relocation destination.\n"); - return -EINVAL; - } - relocatee->data_page = - kmap_atomic_prot_pfn(relocatee->pfn, KM_USER0, - relocatee->pg_prot); -#else - if (NULL != relocatee->data_page) { - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - } - - ret = drm_bo_kmap(relocatee->buf, dst_offset >> PAGE_SHIFT, - 1, &relocatee->kmap); - if (ret) { - DRM_ERROR("Can't map relocation destination.\n"); - return ret; - } - - relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, - &relocatee->is_iomem); -#endif - relocatee->page_offset = dst_offset & PAGE_MASK; - } - return 0; -} - -static int i915_apply_post_reloc(uint32_t reloc[], - struct drm_i915_validate_buffer *buffers, - uint32_t num_buffers, - struct i915_relocatee_info *relocatee) -{ - uint32_t reloc_buffer = reloc[2]; - uint32_t dst_buffer = reloc[3]; - uint32_t val; - uint32_t index; - int ret; - - if (likely(buffers[reloc_buffer].presumed_offset_correct)) - return 0; - if (unlikely(reloc_buffer >= num_buffers)) { - DRM_ERROR("Invalid reloc buffer index.\n"); - return -EINVAL; - } - if (unlikely(dst_buffer >= num_buffers)) { - DRM_ERROR("Invalid dest buffer index.\n"); - return -EINVAL; - } - - ret = i915_update_relocatee(relocatee, buffers, dst_buffer, reloc[0]); - if (unlikely(ret)) - return ret; - - val = buffers[reloc_buffer].buffer->offset; - index = (reloc[0] - relocatee->page_offset) >> 2; - val = val + reloc[1]; - - if (relocatee->idle == I915_RELOC_BUSY) { - i915_emit_ring_reloc(relocatee->buf->dev, - relocatee->buf->offset + reloc[0], val); - return 0; - } -#ifdef DRM_KMAP_ATOMIC_PROT_PFN - relocatee->data_page[index] = val; -#else - if (likely(relocatee->is_iomem)) - iowrite32(val, relocatee->data_page + index); - else - relocatee->data_page[index] = val; -#endif - - return 0; -} - -static int i915_post_relocs(struct drm_file *file_priv, - uint32_t __user * new_reloc_ptr, - struct drm_i915_validate_buffer *buffers, - unsigned int num_buffers) -{ - uint32_t *reloc; - uint32_t reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); - uint32_t header_size = I915_RELOC_HEADER * sizeof(uint32_t); - struct i915_relocatee_info relocatee; - uint32_t reloc_type; - uint32_t num_relocs; - uint32_t count; - int ret = 0; - int i; - int short_circuit = 1; - uint32_t __user *reloc_ptr; - uint64_t new_reloc_data; - uint32_t reloc_buf_size; - uint32_t *reloc_buf; - - for (i = 0; i < num_buffers; ++i) { - if (unlikely(!buffers[i].presumed_offset_correct)) { - short_circuit = 0; - break; - } - } - - if (likely(short_circuit)) - return 0; - - memset(&relocatee, 0, sizeof(relocatee)); - - while (new_reloc_ptr) { - reloc_ptr = new_reloc_ptr; - - ret = get_user(num_relocs, reloc_ptr); - if (unlikely(ret)) - goto out; - if (unlikely(!access_ok(VERIFY_READ, reloc_ptr, - header_size + - num_relocs * reloc_stride))) - return -EFAULT; - - ret = __get_user(reloc_type, reloc_ptr + 1); - if (unlikely(ret)) - goto out; - - if (unlikely(reloc_type != 1)) { - DRM_ERROR("Unsupported relocation type requested.\n"); - ret = -EINVAL; - goto out; - } - - ret = __get_user(new_reloc_data, reloc_ptr + 2); - new_reloc_ptr = (uint32_t __user *) (unsigned long) - new_reloc_data; - - reloc_ptr += I915_RELOC_HEADER; - - if (num_relocs == 0) - goto out; - - reloc_buf_size = - (num_relocs * I915_RELOC0_STRIDE) * sizeof(uint32_t); - reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); - if (!reloc_buf) { - DRM_ERROR("Out of memory for reloc buffer\n"); - ret = -ENOMEM; - goto out; - } - - if (__copy_from_user(reloc_buf, reloc_ptr, reloc_buf_size)) { - ret = -EFAULT; - goto out; - } - reloc = reloc_buf; - preempt_disable(); - for (count = 0; count < num_relocs; ++count) { - ret = i915_apply_post_reloc(reloc, buffers, - num_buffers, &relocatee); - if (unlikely(ret)) { - preempt_enable(); - goto out; - } - reloc += I915_RELOC0_STRIDE; - } - preempt_enable(); - - if (reloc_buf) { - kfree(reloc_buf); - reloc_buf = NULL; - } - i915_clear_relocatee(&relocatee); - } - - out: - /* - * Flush ring relocs so the command parser will pick them up. - */ - - if (relocatee.performed_ring_relocs) - (void)i915_emit_mi_flush(file_priv->minor->dev, 0); - - i915_clear_relocatee(&relocatee); - if (reloc_buf) { - kfree(reloc_buf); - reloc_buf = NULL; - } - - return ret; -} - -static int i915_check_presumed(struct drm_i915_op_arg *arg, - struct drm_buffer_object *bo, - uint32_t __user * data, int *presumed_ok) -{ - struct drm_bo_op_req *req = &arg->d.req; - uint32_t hint_offset; - uint32_t hint = req->bo_req.hint; - - *presumed_ok = 0; - - if (!(hint & DRM_BO_HINT_PRESUMED_OFFSET)) - return 0; - if (bo->offset == req->bo_req.presumed_offset) { - *presumed_ok = 1; - return 0; - } - - /* - * We need to turn off the HINT_PRESUMED_OFFSET for this buffer in - * the user-space IOCTL argument list, since the buffer has moved, - * we're about to apply relocations and we might subsequently - * hit an -EAGAIN. In that case the argument list will be reused by - * user-space, but the presumed offset is no longer valid. - * - * Needless to say, this is a bit ugly. - */ - - hint_offset = (uint32_t *) & req->bo_req.hint - (uint32_t *) arg; - hint &= ~DRM_BO_HINT_PRESUMED_OFFSET; - return __put_user(hint, data + hint_offset); -} - -/* - * Validate, add fence and relocate a block of bos from a userspace list - */ -int i915_validate_buffer_list(struct drm_file *file_priv, - unsigned int fence_class, uint64_t data, - struct drm_i915_validate_buffer *buffers, - uint32_t * num_buffers, - uint32_t __user ** post_relocs) -{ - struct drm_i915_op_arg arg; - struct drm_bo_op_req *req = &arg.d.req; - int ret = 0; - unsigned buf_count = 0; - uint32_t buf_handle; - uint32_t __user *reloc_user_ptr; - struct drm_i915_validate_buffer *item = buffers; - *post_relocs = NULL; - - do { - if (buf_count >= *num_buffers) { - DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers); - ret = -EINVAL; - goto out_err; - } - item = buffers + buf_count; - item->buffer = NULL; - item->presumed_offset_correct = 0; - item->idle = I915_RELOC_UNCHECKED; - - if (copy_from_user - (&arg, (void __user *)(unsigned long)data, sizeof(arg))) { - ret = -EFAULT; - goto out_err; - } - - ret = 0; - if (req->op != drm_bo_validate) { - DRM_ERROR - ("Buffer object operation wasn't \"validate\".\n"); - ret = -EINVAL; - goto out_err; - } - item->ret = 0; - item->data = (void __user *)(unsigned long)data; - - buf_handle = req->bo_req.handle; - reloc_user_ptr = (uint32_t *) (unsigned long)arg.reloc_ptr; - - /* - * Switch mode to post-validation relocations? - */ - - if (unlikely((buf_count == 0) && (*post_relocs == NULL) && - (reloc_user_ptr != NULL))) { - uint32_t reloc_type; - - ret = get_user(reloc_type, reloc_user_ptr + 1); - if (ret) - goto out_err; - - if (reloc_type == 1) - *post_relocs = reloc_user_ptr; - - } - - if ((*post_relocs == NULL) && (reloc_user_ptr != NULL)) { - ret = - i915_exec_reloc(file_priv, buf_handle, - reloc_user_ptr, buffers, buf_count); - if (ret) - goto out_err; - DRM_MEMORYBARRIER(); - } - - ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.flags, - req->bo_req.mask, req->bo_req.hint, - req->bo_req.fence_class, - NULL, &item->buffer); - if (ret) { - DRM_ERROR("error on handle validate %d\n", ret); - goto out_err; - } - - buf_count++; - - ret = i915_check_presumed(&arg, item->buffer, - (uint32_t __user *) - (unsigned long)data, - &item->presumed_offset_correct); - if (ret) - goto out_err; - - data = arg.next; - } while (data != 0); - out_err: - *num_buffers = buf_count; - item->ret = (ret != -EAGAIN) ? ret : 0; - return ret; -} - -/* - * Remove all buffers from the unfenced list. - * If the execbuffer operation was aborted, for example due to a signal, - * this also make sure that buffers retain their original state and - * fence pointers. - * Copy back buffer information to user-space unless we were interrupted - * by a signal. In which case the IOCTL must be rerun. - */ - -static int i915_handle_copyback(struct drm_device *dev, - struct drm_i915_validate_buffer *buffers, - unsigned int num_buffers, int ret) -{ - int err = ret; - int i; - struct drm_i915_op_arg arg; - struct drm_buffer_object *bo; - - if (ret) - drm_putback_buffer_objects(dev); - - if (ret != -EAGAIN) { - for (i = 0; i < num_buffers; ++i) { - arg.handled = 1; - arg.d.rep.ret = buffers->ret; - bo = buffers->buffer; - mutex_lock(&bo->mutex); - drm_bo_fill_rep_arg(bo, &arg.d.rep.bo_info); - mutex_unlock(&bo->mutex); - if (__copy_to_user(buffers->data, &arg, sizeof(arg))) - err = -EFAULT; - buffers++; - } - } - - return err; -} - -/* - * Create a fence object, and if that fails, pretend that everything is - * OK and just idle the GPU. - */ - -void i915_fence_or_sync(struct drm_file *file_priv, - uint32_t fence_flags, - struct drm_fence_arg *fence_arg, - struct drm_fence_object **fence_p) -{ - struct drm_device *dev = file_priv->minor->dev; - int ret; - struct drm_fence_object *fence; - - ret = drm_fence_buffer_objects(dev, NULL, fence_flags, NULL, &fence); - - if (ret) { - - /* - * Fence creation failed. - * Fall back to synchronous operation and idle the engine. - */ - - (void)i915_emit_mi_flush(dev, MI_READ_FLUSH); - (void)i915_quiescent(dev); - - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - - /* - * Communicate to user-space that - * fence creation has failed and that - * the engine is idle. - */ - - fence_arg->handle = ~0; - fence_arg->error = ret; - } - drm_putback_buffer_objects(dev); - if (fence_p) - *fence_p = NULL; - return; - } - - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - - ret = drm_fence_add_user_object(file_priv, fence, - fence_flags & - DRM_FENCE_FLAG_SHAREABLE); - if (!ret) - drm_fence_fill_arg(fence, fence_arg); - else { - /* - * Fence user object creation failed. - * We must idle the engine here as well, as user- - * space expects a fence object to wait on. Since we - * have a fence object we wait for it to signal - * to indicate engine "sufficiently" idle. - */ - - (void)drm_fence_object_wait(fence, 0, 1, fence->type); - drm_fence_usage_deref_unlocked(&fence); - fence_arg->handle = ~0; - fence_arg->error = ret; - } - } - - if (fence_p) - *fence_p = fence; - else if (fence) - drm_fence_usage_deref_unlocked(&fence); -} - -int i915_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) - dev->dev_private; - struct drm_i915_master_private *master_priv = - (struct drm_i915_master_private *) - dev->primary->master->driver_priv; - struct drm_i915_sarea *sarea_priv = (struct drm_i915_sarea *) - master_priv->sarea_priv; - struct drm_i915_execbuffer *exec_buf = data; - struct drm_i915_batchbuffer *batch = &exec_buf->batch; - struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; - int num_buffers; - int ret; - uint32_t __user *post_relocs; - - if (!dev_priv->allow_batchbuffer) { - DRM_ERROR("Batchbuffer ioctl disabled\n"); - return -EINVAL; - } - - if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, - batch->num_cliprects * - sizeof(struct - drm_clip_rect))) - return -EFAULT; - - if (exec_buf->num_buffers > dev_priv->max_validate_buffers) - return -EINVAL; - - ret = drm_bo_read_lock(&dev->bm.bm_lock, 1); - if (ret) - return ret; - - /* - * The cmdbuf_mutex makes sure the validate-submit-fence - * operation is atomic. - */ - - ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); - if (ret) { - drm_bo_read_unlock(&dev->bm.bm_lock); - return -EAGAIN; - } - - num_buffers = exec_buf->num_buffers; - - if (!dev_priv->val_bufs) { - dev_priv->val_bufs = - vmalloc(sizeof(struct drm_i915_validate_buffer) * - dev_priv->max_validate_buffers); - } - if (!dev_priv->val_bufs) { - drm_bo_read_unlock(&dev->bm.bm_lock); - mutex_unlock(&dev_priv->cmdbuf_mutex); - return -ENOMEM; - } - - /* validate buffer list + fixup relocations */ - ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, - dev_priv->val_bufs, &num_buffers, - &post_relocs); - if (ret) - goto out_err0; - - if (post_relocs) { - ret = i915_post_relocs(file_priv, post_relocs, - dev_priv->val_bufs, num_buffers); - if (ret) - goto out_err0; - } - - /* make sure all previous memory operations have passed */ - DRM_MEMORYBARRIER(); - - if (!post_relocs) { - drm_agp_chipset_flush(dev); - batch->start = - dev_priv->val_bufs[num_buffers - 1].buffer->offset; - } else { - batch->start += dev_priv->val_bufs[0].buffer->offset; - } - - DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n", - batch->start, batch->used, batch->num_cliprects); - - ret = i915_dispatch_batchbuffer(dev, batch); - if (ret) - goto out_err0; - if (sarea_priv) - sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - i915_fence_or_sync(file_priv, fence_arg->flags, fence_arg, NULL); - - out_err0: - ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret); - mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers); - mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev_priv->cmdbuf_mutex); - drm_bo_read_unlock(&dev->bm.bm_lock); - return ret; -} diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c deleted file mode 100644 index 436b7e1f..00000000 --- a/linux-core/i915_fence.c +++ /dev/null @@ -1,273 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström - */ - -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" - -/* - * Initiate a sync flush if it's not already pending. - */ - -static inline void i915_initiate_rwflush(struct drm_i915_private *dev_priv, - struct drm_fence_class_manager *fc) -{ - if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) && - !dev_priv->flush_pending) { - dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv); - dev_priv->flush_flags = fc->pending_flush; - dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0); - I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); - dev_priv->flush_pending = 1; - fc->pending_flush &= ~DRM_I915_FENCE_TYPE_RW; - } -} - -static inline void i915_report_rwflush(struct drm_device *dev, - struct drm_i915_private *dev_priv) -{ - if (unlikely(dev_priv->flush_pending)) { - - uint32_t flush_flags; - uint32_t i_status; - uint32_t flush_sequence; - - i_status = READ_HWSP(dev_priv, 0); - if ((i_status & (1 << 12)) != - (dev_priv->saved_flush_status & (1 << 12))) { - flush_flags = dev_priv->flush_flags; - flush_sequence = dev_priv->flush_sequence; - dev_priv->flush_pending = 0; - drm_fence_handler(dev, 0, flush_sequence, - flush_flags, 0); - } - } -} - -static void i915_fence_flush(struct drm_device *dev, - uint32_t fence_class) -{ - struct drm_i915_private *dev_priv = - (struct drm_i915_private *) dev->dev_private; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[0]; - unsigned long irq_flags; - - if (unlikely(!dev_priv)) - return; - - write_lock_irqsave(&fm->lock, irq_flags); - i915_initiate_rwflush(dev_priv, fc); - write_unlock_irqrestore(&fm->lock, irq_flags); -} - - -static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class, - uint32_t waiting_types) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[0]; - uint32_t sequence; - - if (unlikely(!dev_priv)) - return; - - /* - * First, report any executed sync flush: - */ - - i915_report_rwflush(dev, dev_priv); - - /* - * Report A new breadcrumb, and adjust IRQs. - */ - - if (waiting_types & DRM_FENCE_TYPE_EXE) { - - sequence = READ_BREADCRUMB(dev_priv); - drm_fence_handler(dev, 0, sequence, - DRM_FENCE_TYPE_EXE, 0); - - if (dev_priv->fence_irq_on && - !(fc->waiting_types & DRM_FENCE_TYPE_EXE)) { - i915_user_irq_off(dev); - dev_priv->fence_irq_on = 0; - } else if (!dev_priv->fence_irq_on && - (fc->waiting_types & DRM_FENCE_TYPE_EXE)) { - i915_user_irq_on(dev); - dev_priv->fence_irq_on = 1; - } - } - - /* - * There may be new RW flushes pending. Start them. - */ - - i915_initiate_rwflush(dev_priv, fc); - - /* - * And possibly, but unlikely, they finish immediately. - */ - - i915_report_rwflush(dev, dev_priv); - -} - -static int i915_fence_emit_sequence(struct drm_device *dev, uint32_t class, - uint32_t flags, uint32_t *sequence, - uint32_t *native_type) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - if (unlikely(!dev_priv)) - return -EINVAL; - - i915_emit_irq(dev); - *sequence = (uint32_t) dev_priv->counter; - *native_type = DRM_FENCE_TYPE_EXE; - if (flags & DRM_I915_FENCE_FLAG_FLUSHED) - *native_type |= DRM_I915_FENCE_TYPE_RW; - - return 0; -} - -void i915_fence_handler(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[0]; - - write_lock(&fm->lock); - if (likely(dev_priv->fence_irq_on)) - i915_fence_poll(dev, 0, fc->waiting_types); - write_unlock(&fm->lock); -} - -/* - * We need a separate wait function since we need to poll for - * sync flushes. - */ - -static int i915_fence_wait(struct drm_fence_object *fence, - int lazy, int interruptible, uint32_t mask) -{ - struct drm_device *dev = fence->dev; - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[0]; - int ret; - unsigned long _end = jiffies + 3 * DRM_HZ; - - drm_fence_object_flush(fence, mask); - if (likely(interruptible)) - ret = wait_event_interruptible_timeout - (fc->fence_queue, drm_fence_object_signaled(fence, DRM_FENCE_TYPE_EXE), - 3 * DRM_HZ); - else - ret = wait_event_timeout - (fc->fence_queue, drm_fence_object_signaled(fence, DRM_FENCE_TYPE_EXE), - 3 * DRM_HZ); - - if (unlikely(ret == -ERESTARTSYS)) - return -EAGAIN; - - if (unlikely(ret == 0)) - return -EBUSY; - - if (likely(mask == DRM_FENCE_TYPE_EXE || - drm_fence_object_signaled(fence, mask))) - return 0; - - /* - * Remove this code snippet when fixed. HWSTAM doesn't let - * flush info through... - */ - - if (unlikely(dev_priv && !dev_priv->irq_enabled)) { - unsigned long irq_flags; - - DRM_ERROR("X server disabled IRQs before releasing frame buffer.\n"); - msleep(100); - dev_priv->flush_pending = 0; - write_lock_irqsave(&fm->lock, irq_flags); - drm_fence_handler(dev, fence->fence_class, - fence->sequence, fence->type, 0); - write_unlock_irqrestore(&fm->lock, irq_flags); - } - - /* - * Poll for sync flush completion. - */ - - return drm_fence_wait_polling(fence, lazy, interruptible, mask, _end); -} - -static uint32_t i915_fence_needed_flush(struct drm_fence_object *fence) -{ - uint32_t flush_flags = fence->waiting_types & - ~(DRM_FENCE_TYPE_EXE | fence->signaled_types); - - if (likely(flush_flags == 0 || - ((flush_flags & ~fence->native_types) == 0) || - (fence->signaled_types != DRM_FENCE_TYPE_EXE))) - return 0; - else { - struct drm_device *dev = fence->dev; - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - struct drm_fence_driver *driver = dev->driver->fence_driver; - - if (unlikely(!dev_priv)) - return 0; - - if (dev_priv->flush_pending) { - uint32_t diff = (dev_priv->flush_sequence - fence->sequence) & - driver->sequence_mask; - - if (diff < driver->wrap_diff) - return 0; - } - } - return flush_flags; -} - -struct drm_fence_driver i915_fence_driver = { - .num_classes = 1, - .wrap_diff = (1U << (BREADCRUMB_BITS - 1)), - .flush_diff = (1U << (BREADCRUMB_BITS - 2)), - .sequence_mask = BREADCRUMB_MASK, - .has_irq = NULL, - .emit = i915_fence_emit_sequence, - .flush = i915_fence_flush, - .poll = i915_fence_poll, - .needed_flush = i915_fence_needed_flush, - .wait = i915_fence_wait, -}; diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index e06cba5b..1aa3afbf 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -245,8 +245,7 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, - 0, NULL); + DRM_BO_HINT_DONT_FENCE, 0); } else ret = 0; @@ -276,8 +275,7 @@ int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, /* validate into a pin with no fence */ ret = drm_bo_do_validate(obj_priv->bo, DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, - 0, NULL); + DRM_BO_HINT_DONT_FENCE, 0); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); @@ -321,7 +319,7 @@ int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, //VB_AGE_TEST_WITH_RETURN(dev_priv); ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - 0 , 0, NULL); + 0 , 0); if (ret) return ret; @@ -693,7 +691,7 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, obj_priv = obj->driver_private; ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, 0, NULL); + DRM_BO_HINT_DONT_FENCE, 0); return ret; } @@ -743,7 +741,7 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32 ret = drm_bo_do_validate(dev_priv->ib_objs[index]->bo, 0, DRM_BO_FLAG_NO_EVICT, - 0, 0, NULL); + 0, 0); if (ret) { DRM_ERROR("Failed to validate IB %d\n", index); return -EINVAL; @@ -761,7 +759,6 @@ static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords struct drm_fence_object *fence; int ret; int i; - RING_LOCALS; for (i = 0; i < RADEON_NUM_IB; i++) { @@ -821,7 +818,7 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri flags = DRM_BO_FLAG_MEM_TT; } - ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0, NULL); + ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0); if (ret) return ret; diff --git a/shared-core/drm.h b/shared-core/drm.h index 7aba2939..76d2c4c5 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -675,324 +675,6 @@ struct drm_set_version { int drm_dd_minor; }; - -#define DRM_FENCE_FLAG_EMIT 0x00000001 -#define DRM_FENCE_FLAG_SHAREABLE 0x00000002 -/** - * On hardware with no interrupt events for operation completion, - * indicates that the kernel should sleep while waiting for any blocking - * operation to complete rather than spinning. - * - * Has no effect otherwise. - */ -#define DRM_FENCE_FLAG_WAIT_LAZY 0x00000004 -#define DRM_FENCE_FLAG_NO_USER 0x00000010 - -/* Reserved for driver use */ -#define DRM_FENCE_MASK_DRIVER 0xFF000000 - -#define DRM_FENCE_TYPE_EXE 0x00000001 - -struct drm_fence_arg { - unsigned int handle; - unsigned int fence_class; - unsigned int type; - unsigned int flags; - unsigned int signaled; - unsigned int error; - unsigned int sequence; - unsigned int pad64; - uint64_t expand_pad[2]; /*Future expansion */ -}; - -/* Buffer permissions, referring to how the GPU uses the buffers. - * these translate to fence types used for the buffers. - * Typically a texture buffer is read, A destination buffer is write and - * a command (batch-) buffer is exe. Can be or-ed together. - */ - -#define DRM_BO_FLAG_READ (1ULL << 0) -#define DRM_BO_FLAG_WRITE (1ULL << 1) -#define DRM_BO_FLAG_EXE (1ULL << 2) - -/* - * All of the bits related to access mode - */ -#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE) -/* - * Status flags. Can be read to determine the actual state of a buffer. - * Can also be set in the buffer mask before validation. - */ - -/* - * Mask: Never evict this buffer. Not even with force. This type of buffer is only - * available to root and must be manually removed before buffer manager shutdown - * or lock. - * Flags: Acknowledge - */ -#define DRM_BO_FLAG_NO_EVICT (1ULL << 4) - -/* - * Mask: Require that the buffer is placed in mappable memory when validated. - * If not set the buffer may or may not be in mappable memory when validated. - * Flags: If set, the buffer is in mappable memory. - */ -#define DRM_BO_FLAG_MAPPABLE (1ULL << 5) - -/* Mask: The buffer should be shareable with other processes. - * Flags: The buffer is shareable with other processes. - */ -#define DRM_BO_FLAG_SHAREABLE (1ULL << 6) - -/* Mask: If set, place the buffer in cache-coherent memory if available. - * If clear, never place the buffer in cache coherent memory if validated. - * Flags: The buffer is currently in cache-coherent memory. - */ -#define DRM_BO_FLAG_CACHED (1ULL << 7) - -/* Mask: Make sure that every time this buffer is validated, - * it ends up on the same location provided that the memory mask is the same. - * The buffer will also not be evicted when claiming space for - * other buffers. Basically a pinned buffer but it may be thrown out as - * part of buffer manager shutdown or locking. - * Flags: Acknowledge. - */ -#define DRM_BO_FLAG_NO_MOVE (1ULL << 8) - -/* Mask: Make sure the buffer is in cached memory when mapped. In conjunction - * with DRM_BO_FLAG_CACHED it also allows the buffer to be bound into the GART - * with unsnooped PTEs instead of snooped, by using chipset-specific cache - * flushing at bind time. A better name might be DRM_BO_FLAG_TT_UNSNOOPED, - * as the eviction to local memory (TTM unbind) on map is just a side effect - * to prevent aggressive cache prefetch from the GPU disturbing the cache - * management that the DRM is doing. - * - * Flags: Acknowledge. - * Buffers allocated with this flag should not be used for suballocators - * This type may have issues on CPUs with over-aggressive caching - * http://marc.info/?l=linux-kernel&m=102376926732464&w=2 - */ -#define DRM_BO_FLAG_CACHED_MAPPED (1ULL << 19) - - -/* Mask: Force DRM_BO_FLAG_CACHED flag strictly also if it is set. - * Flags: Acknowledge. - */ -#define DRM_BO_FLAG_FORCE_CACHING (1ULL << 13) - -/* - * Mask: Force DRM_BO_FLAG_MAPPABLE flag strictly also if it is clear. - * Flags: Acknowledge. - */ -#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14) -#define DRM_BO_FLAG_TILE (1ULL << 15) - -/* - * Memory type flags that can be or'ed together in the mask, but only - * one appears in flags. - */ - -/* System memory */ -#define DRM_BO_FLAG_MEM_LOCAL (1ULL << 24) -/* Translation table memory */ -#define DRM_BO_FLAG_MEM_TT (1ULL << 25) -/* Vram memory */ -#define DRM_BO_FLAG_MEM_VRAM (1ULL << 26) -/* Up to the driver to define. */ -#define DRM_BO_FLAG_MEM_PRIV0 (1ULL << 27) -#define DRM_BO_FLAG_MEM_PRIV1 (1ULL << 28) -#define DRM_BO_FLAG_MEM_PRIV2 (1ULL << 29) -#define DRM_BO_FLAG_MEM_PRIV3 (1ULL << 30) -#define DRM_BO_FLAG_MEM_PRIV4 (1ULL << 31) -/* We can add more of these now with a 64-bit flag type */ - -/* - * This is a mask covering all of the memory type flags; easier to just - * use a single constant than a bunch of | values. It covers - * DRM_BO_FLAG_MEM_LOCAL through DRM_BO_FLAG_MEM_PRIV4 - */ -#define DRM_BO_MASK_MEM 0x00000000FF000000ULL -/* - * This adds all of the CPU-mapping options in with the memory - * type to label all bits which change how the page gets mapped - */ -#define DRM_BO_MASK_MEMTYPE (DRM_BO_MASK_MEM | \ - DRM_BO_FLAG_CACHED_MAPPED | \ - DRM_BO_FLAG_CACHED | \ - DRM_BO_FLAG_MAPPABLE) - -/* Driver-private flags */ -#define DRM_BO_MASK_DRIVER 0xFFFF000000000000ULL - -/* - * Don't block on validate and map. Instead, return EBUSY. - */ -#define DRM_BO_HINT_DONT_BLOCK 0x00000002 -/* - * Don't place this buffer on the unfenced list. This means - * that the buffer will not end up having a fence associated - * with it as a result of this operation - */ -#define DRM_BO_HINT_DONT_FENCE 0x00000004 -/** - * On hardware with no interrupt events for operation completion, - * indicates that the kernel should sleep while waiting for any blocking - * operation to complete rather than spinning. - * - * Has no effect otherwise. - */ -#define DRM_BO_HINT_WAIT_LAZY 0x00000008 -/* - * The client has compute relocations refering to this buffer using the - * offset in the presumed_offset field. If that offset ends up matching - * where this buffer lands, the kernel is free to skip executing those - * relocations - */ -#define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010 - -#define DRM_BO_INIT_MAGIC 0xfe769812 -#define DRM_BO_INIT_MAJOR 1 -#define DRM_BO_INIT_MINOR 0 -#define DRM_BO_INIT_PATCH 0 - - -struct drm_bo_info_req { - uint64_t mask; - uint64_t flags; - unsigned int handle; - unsigned int hint; - unsigned int fence_class; - unsigned int desired_tile_stride; - unsigned int tile_info; - unsigned int pad64; - uint64_t presumed_offset; -}; - -struct drm_bo_create_req { - uint64_t flags; - uint64_t size; - uint64_t buffer_start; - unsigned int hint; - unsigned int page_alignment; -}; - - -/* - * Reply flags - */ - -#define DRM_BO_REP_BUSY 0x00000001 - -struct drm_bo_info_rep { - uint64_t flags; - uint64_t proposed_flags; - uint64_t size; - uint64_t offset; - uint64_t arg_handle; - uint64_t buffer_start; - unsigned int handle; - unsigned int fence_flags; - unsigned int rep_flags; - unsigned int page_alignment; - unsigned int desired_tile_stride; - unsigned int hw_tile_stride; - unsigned int tile_info; - unsigned int pad64; - uint64_t expand_pad[4]; /*Future expansion */ -}; - -struct drm_bo_arg_rep { - struct drm_bo_info_rep bo_info; - int ret; - unsigned int pad64; -}; - -struct drm_bo_create_arg { - union { - struct drm_bo_create_req req; - struct drm_bo_info_rep rep; - } d; -}; - -struct drm_bo_handle_arg { - unsigned int handle; -}; - -struct drm_bo_reference_info_arg { - union { - struct drm_bo_handle_arg req; - struct drm_bo_info_rep rep; - } d; -}; - -struct drm_bo_map_wait_idle_arg { - union { - struct drm_bo_info_req req; - struct drm_bo_info_rep rep; - } d; -}; - -struct drm_bo_op_req { - enum { - drm_bo_validate, - drm_bo_fence, - drm_bo_ref_fence, - } op; - unsigned int arg_handle; - struct drm_bo_info_req bo_req; -}; - - -struct drm_bo_op_arg { - uint64_t next; - union { - struct drm_bo_op_req req; - struct drm_bo_arg_rep rep; - } d; - int handled; - unsigned int pad64; -}; - - -#define DRM_BO_MEM_LOCAL 0 -#define DRM_BO_MEM_TT 1 -#define DRM_BO_MEM_VRAM 2 -#define DRM_BO_MEM_PRIV0 3 -#define DRM_BO_MEM_PRIV1 4 -#define DRM_BO_MEM_PRIV2 5 -#define DRM_BO_MEM_PRIV3 6 -#define DRM_BO_MEM_PRIV4 7 - -#define DRM_BO_MEM_TYPES 8 /* For now. */ - -#define DRM_BO_LOCK_UNLOCK_BM (1 << 0) -#define DRM_BO_LOCK_IGNORE_NO_EVICT (1 << 1) - -struct drm_bo_version_arg { - uint32_t major; - uint32_t minor; - uint32_t patchlevel; -}; - -struct drm_mm_type_arg { - unsigned int mem_type; - unsigned int lock_flags; -}; - -struct drm_mm_init_arg { - unsigned int magic; - unsigned int major; - unsigned int minor; - unsigned int mem_type; - uint64_t p_offset; - uint64_t p_size; -}; - -struct drm_mm_info_arg { - unsigned int mem_type; - uint64_t p_size; -}; - struct drm_gem_close { /** Handle of the object to be closed. */ uint32_t handle; @@ -1337,31 +1019,6 @@ struct drm_mode_crtc_lut { #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) -#define DRM_IOCTL_MM_INIT DRM_IOWR(0xc0, struct drm_mm_init_arg) -#define DRM_IOCTL_MM_TAKEDOWN DRM_IOWR(0xc1, struct drm_mm_type_arg) -#define DRM_IOCTL_MM_LOCK DRM_IOWR(0xc2, struct drm_mm_type_arg) -#define DRM_IOCTL_MM_UNLOCK DRM_IOWR(0xc3, struct drm_mm_type_arg) - -#define DRM_IOCTL_FENCE_CREATE DRM_IOWR(0xc4, struct drm_fence_arg) -#define DRM_IOCTL_FENCE_REFERENCE DRM_IOWR(0xc6, struct drm_fence_arg) -#define DRM_IOCTL_FENCE_UNREFERENCE DRM_IOWR(0xc7, struct drm_fence_arg) -#define DRM_IOCTL_FENCE_SIGNALED DRM_IOWR(0xc8, struct drm_fence_arg) -#define DRM_IOCTL_FENCE_FLUSH DRM_IOWR(0xc9, struct drm_fence_arg) -#define DRM_IOCTL_FENCE_WAIT DRM_IOWR(0xca, struct drm_fence_arg) -#define DRM_IOCTL_FENCE_EMIT DRM_IOWR(0xcb, struct drm_fence_arg) -#define DRM_IOCTL_FENCE_BUFFERS DRM_IOWR(0xcc, struct drm_fence_arg) - -#define DRM_IOCTL_BO_CREATE DRM_IOWR(0xcd, struct drm_bo_create_arg) -#define DRM_IOCTL_BO_MAP DRM_IOWR(0xcf, struct drm_bo_map_wait_idle_arg) -#define DRM_IOCTL_BO_UNMAP DRM_IOWR(0xd0, struct drm_bo_handle_arg) -#define DRM_IOCTL_BO_REFERENCE DRM_IOWR(0xd1, struct drm_bo_reference_info_arg) -#define DRM_IOCTL_BO_UNREFERENCE DRM_IOWR(0xd2, struct drm_bo_handle_arg) -#define DRM_IOCTL_BO_SETSTATUS DRM_IOWR(0xd3, struct drm_bo_map_wait_idle_arg) -#define DRM_IOCTL_BO_INFO DRM_IOWR(0xd4, struct drm_bo_reference_info_arg) -#define DRM_IOCTL_BO_WAIT_IDLE DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg) -#define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) -#define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg) - #define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) #define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) #define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA2, struct drm_mode_get_connector) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 09c53676..3e6a6626 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -148,7 +148,7 @@ int i915_dma_cleanup(struct drm_device * dev) return 0; } -#if defined(I915_HAVE_BUFFER) && defined(DRI2) +#if defined(DRI2) #define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16) #define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff) #define DRI2_SAREA_BLOCK_NEXT(p) \ @@ -226,12 +226,7 @@ static int i915_initialize(struct drm_device * dev, } } -#ifdef I915_HAVE_BUFFER - if (!drm_core_check_feature(dev, DRIVER_MODESET)) { - dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS; - } -#endif - + if (init->ring_size != 0) { dev_priv->ring.Size = init->ring_size; dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; @@ -285,10 +280,6 @@ static int i915_initialize(struct drm_device * dev, } DRM_DEBUG("Enabled hardware status page\n"); -#ifdef I915_HAVE_BUFFER - if (!drm_core_check_feature(dev, DRIVER_MODESET)) { - mutex_init(&dev_priv->cmdbuf_mutex); - } #ifdef DRI2 if (init->func == I915_INIT_DMA2) { int ret = setup_dri2_sarea(dev, file_priv, init); @@ -299,7 +290,6 @@ static int i915_initialize(struct drm_device * dev, } } #endif /* DRI2 */ -#endif /* I915_HAVE_BUFFER */ return 0; } @@ -565,9 +555,6 @@ int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush) static int i915_dispatch_cmdbuffer(struct drm_device * dev, struct drm_i915_cmdbuffer * cmd) { -#ifdef I915_HAVE_FENCE - struct drm_i915_private *dev_priv = dev->dev_private; -#endif int nbox = cmd->num_cliprects; int i = 0, count, ret; @@ -594,10 +581,6 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, } i915_emit_breadcrumb(dev); -#ifdef I915_HAVE_FENCE - if (unlikely((dev_priv->counter & 0xFF) == 0)) - drm_fence_flush_old(dev, 0, dev_priv->counter); -#endif return 0; } @@ -648,10 +631,6 @@ int i915_dispatch_batchbuffer(struct drm_device * dev, } i915_emit_breadcrumb(dev); -#ifdef I915_HAVE_FENCE - if (unlikely((dev_priv->counter & 0xFF) == 0)) - drm_fence_flush_old(dev, 0, dev_priv->counter); -#endif return 0; } @@ -724,10 +703,6 @@ void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) i915_do_dispatch_flip(dev, i, sync); i915_emit_breadcrumb(dev); -#ifdef I915_HAVE_FENCE - if (unlikely(!sync && ((dev_priv->counter & 0xFF) == 0))) - drm_fence_flush_old(dev, 0, dev_priv->counter); -#endif } int i915_quiescent(struct drm_device *dev) @@ -1077,9 +1052,6 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_MMIO, i915_mmio, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH), -#ifdef I915_HAVE_BUFFER - DRM_IOCTL_DEF(DRM_I915_EXECBUFFER, i915_execbuffer, DRM_AUTH), -#endif DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 8ba71687..611f943a 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -375,58 +375,6 @@ typedef struct drm_i915_hws_addr { uint64_t addr; } drm_i915_hws_addr_t; -/* - * Relocation header is 4 uint32_ts - * 0 - 32 bit reloc count - * 1 - 32-bit relocation type - * 2-3 - 64-bit user buffer handle ptr for another list of relocs. - */ -#define I915_RELOC_HEADER 4 - -/* - * type 0 relocation has 4-uint32_t stride - * 0 - offset into buffer - * 1 - delta to add in - * 2 - buffer handle - * 3 - reserved (for optimisations later). - */ -/* - * type 1 relocation has 4-uint32_t stride. - * Hangs off the first item in the op list. - * Performed after all valiations are done. - * Try to group relocs into the same relocatee together for - * performance reasons. - * 0 - offset into buffer - * 1 - delta to add in - * 2 - buffer index in op list. - * 3 - relocatee index in op list. - */ -#define I915_RELOC_TYPE_0 0 -#define I915_RELOC0_STRIDE 4 -#define I915_RELOC_TYPE_1 1 -#define I915_RELOC1_STRIDE 4 - - -struct drm_i915_op_arg { - uint64_t next; - uint64_t reloc_ptr; - int handled; - unsigned int pad64; - union { - struct drm_bo_op_req req; - struct drm_bo_arg_rep rep; - } d; - -}; - -struct drm_i915_execbuffer { - uint64_t ops_list; - uint32_t num_buffers; - struct drm_i915_batchbuffer batch; - drm_context_t context; /* for lockless use in the future */ - struct drm_fence_arg fence_arg; -}; - struct drm_i915_gem_init { /** * Beginning offset in the GTT to be managed by the DRM memory From 55761b2fe706f8f68ca3a8827b950fd01af1650b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 31 Jul 2008 13:12:36 +1000 Subject: [PATCH 10/49] drm: add fault handler support so as to be more like possible upstream (cherry picked from commit 10d5b037b85706037df89bf0275436797e4eb559) --- linux-core/drm_compat.c | 99 +++++++++++++++++++++++++++++++++++++++++ linux-core/drm_compat.h | 3 ++ linux-core/drm_vm.c | 35 ++++++++------- 3 files changed, 120 insertions(+), 17 deletions(-) diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index aa825f32..d06b9d24 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -806,3 +806,102 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, EXPORT_SYMBOL(kmap_atomic_prot_pfn); #endif +#ifdef DRM_FULL_MM_COMPAT +#ifdef DRM_NO_FAULT +unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, + unsigned long address) +{ + struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data; + unsigned long page_offset; + struct page *page = NULL; + struct drm_ttm *ttm; + struct drm_device *dev; + unsigned long pfn; + int err; + unsigned long bus_base; + unsigned long bus_offset; + unsigned long bus_size; + unsigned long ret = NOPFN_REFAULT; + + if (address > vma->vm_end) + return NOPFN_SIGBUS; + + dev = bo->dev; + err = drm_bo_read_lock(&dev->bm.bm_lock, 1); + if (err) + return NOPFN_REFAULT; + + err = mutex_lock_interruptible(&bo->mutex); + if (err) { + drm_bo_read_unlock(&dev->bm.bm_lock); + return NOPFN_REFAULT; + } + + err = drm_bo_wait(bo, 0, 1, 0, 1); + if (err) { + ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; + goto out_unlock; + } + + bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; + + /* + * If buffer happens to be in a non-mappable location, + * move it to a mappable. + */ + + if (!(bo->mem.flags & DRM_BO_FLAG_MAPPABLE)) { + uint32_t new_flags = bo->mem.proposed_flags | + DRM_BO_FLAG_MAPPABLE | + DRM_BO_FLAG_FORCE_MAPPABLE; + err = drm_bo_move_buffer(bo, new_flags, 0, 0); + if (err) { + ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + goto out_unlock; + } + } + + err = drm_bo_pci_offset(dev, &bo->mem, &bus_base, &bus_offset, + &bus_size); + + if (err) { + ret = NOPFN_SIGBUS; + goto out_unlock; + } + + page_offset = (address - vma->vm_start) >> PAGE_SHIFT; + + if (bus_size) { + struct drm_mem_type_manager *man = &dev->bm.man[bo->mem.mem_type]; + + pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) + page_offset; + vma->vm_page_prot = drm_io_prot(man->drm_bus_maptype, vma); + } else { + ttm = bo->ttm; + + drm_ttm_fixup_caching(ttm); + page = drm_ttm_get_page(ttm, page_offset); + if (!page) { + ret = NOPFN_OOM; + goto out_unlock; + } + pfn = page_to_pfn(page); + vma->vm_page_prot = (bo->mem.flags & DRM_BO_FLAG_CACHED) ? + vm_get_page_prot(vma->vm_flags) : + drm_io_prot(_DRM_TTM, vma); + } + + err = vm_insert_pfn(vma, address, pfn); + if (err) { + ret = (err != -EAGAIN) ? NOPFN_OOM : NOPFN_REFAULT; + goto out_unlock; + } +out_unlock: + BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNLOCKED); + mutex_unlock(&bo->mutex); + drm_bo_read_unlock(&dev->bm.bm_lock); + return ret; +} +#endif +#endif diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index cfa4fc6d..19dc1f67 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -319,6 +319,9 @@ extern int drm_bo_map_bound(struct vm_area_struct *vma); /* fixme when functions are upstreamed - upstreamed for 2.6.23 */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) #define DRM_IDR_COMPAT_FN +#define DRM_NO_FAULT +extern unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, + unsigned long address); #endif #ifdef DRM_IDR_COMPAT_FN int idr_for_each(struct idr *idp, diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 6618c0ae..0d5242d3 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -685,8 +685,8 @@ EXPORT_SYMBOL(drm_mmap); * \c Pagefault method for buffer objects. * * \param vma Virtual memory area. - * \param address File offset. - * \return Error or refault. The pfn is manually inserted. + * \param vmf vm fault data + * \return Error or VM_FAULT_NOPAGE:. The pfn is manually inserted. * * It's important that pfns are inserted while holding the bo->mutex lock. * otherwise we might race with unmap_mapping_range() which is always @@ -699,8 +699,8 @@ EXPORT_SYMBOL(drm_mmap); */ #ifdef DRM_FULL_MM_COMPAT -static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, - unsigned long address) +static int drm_bo_vm_fault(struct vm_area_struct *vma, + struct vm_fault *vmf) { struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data; unsigned long page_offset; @@ -712,25 +712,22 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, unsigned long bus_base; unsigned long bus_offset; unsigned long bus_size; - unsigned long ret = NOPFN_REFAULT; - - if (address > vma->vm_end) - return NOPFN_SIGBUS; + unsigned long ret = VM_FAULT_NOPAGE; dev = bo->dev; err = drm_bo_read_lock(&dev->bm.bm_lock, 1); if (err) - return NOPFN_REFAULT; + return VM_FAULT_NOPAGE; err = mutex_lock_interruptible(&bo->mutex); if (err) { drm_bo_read_unlock(&dev->bm.bm_lock); - return NOPFN_REFAULT; + return VM_FAULT_NOPAGE; } err = drm_bo_wait(bo, 0, 1, 0, 1); if (err) { - ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + ret = (err != -EAGAIN) ? VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; goto out_unlock; } @@ -748,7 +745,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, DRM_BO_FLAG_FORCE_MAPPABLE; err = drm_bo_move_buffer(bo, new_flags, 0, 0); if (err) { - ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + ret = (err != -EAGAIN) ? VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; goto out_unlock; } } @@ -757,11 +754,11 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, &bus_size); if (err) { - ret = NOPFN_SIGBUS; + ret = VM_FAULT_SIGBUS; goto out_unlock; } - page_offset = (address - vma->vm_start) >> PAGE_SHIFT; + page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT; if (bus_size) { struct drm_mem_type_manager *man = &dev->bm.man[bo->mem.mem_type]; @@ -774,7 +771,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, drm_ttm_fixup_caching(ttm); page = drm_ttm_get_page(ttm, page_offset); if (!page) { - ret = NOPFN_OOM; + ret = VM_FAULT_OOM; goto out_unlock; } pfn = page_to_pfn(page); @@ -783,9 +780,9 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, drm_io_prot(_DRM_TTM, vma); } - err = vm_insert_pfn(vma, address, pfn); + err = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); if (err) { - ret = (err != -EAGAIN) ? NOPFN_OOM : NOPFN_REFAULT; + ret = (err != -EAGAIN) ? VM_FAULT_OOM : VM_FAULT_NOPAGE; goto out_unlock; } out_unlock: @@ -849,7 +846,11 @@ static void drm_bo_vm_close(struct vm_area_struct *vma) static struct vm_operations_struct drm_bo_vm_ops = { #ifdef DRM_FULL_MM_COMPAT +#ifdef DRM_NO_FAULT .nopfn = drm_bo_vm_nopfn, +#else + .fault = drm_bo_vm_fault, +#endif #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) .nopfn = drm_bo_vm_nopfn, From d2d7f3069dac4bc5ddd3c8da4d3955f690274276 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 31 Jul 2008 13:13:21 +1000 Subject: [PATCH 11/49] drm: userspace rip out TTM API --- libdrm/intel/intel_bufmgr_fake.c | 2 +- libdrm/xf86drm.c | 530 ------------------------------- linux-core/drm_bo.c | 5 +- linux-core/drm_objects.h | 17 - linux-core/drm_vm.c | 6 - shared-core/i915_dma.c | 1 - 6 files changed, 3 insertions(+), 558 deletions(-) diff --git a/libdrm/intel/intel_bufmgr_fake.c b/libdrm/intel/intel_bufmgr_fake.c index e988eb58..e7ed893f 100644 --- a/libdrm/intel/intel_bufmgr_fake.c +++ b/libdrm/intel/intel_bufmgr_fake.c @@ -649,7 +649,7 @@ intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, bo_fake->refcount = 1; bo_fake->id = ++bufmgr_fake->buf_nr; bo_fake->name = name; - bo_fake->flags = BM_PINNED | DRM_BO_FLAG_NO_MOVE; + bo_fake->flags = BM_PINNED; bo_fake->is_static = 1; DBG("drm_bo_alloc_static: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name, diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index 4b4d009b..1fd3a697 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -2357,165 +2357,6 @@ int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data, } -/* - * Valid flags are - * DRM_FENCE_FLAG_EMIT - * DRM_FENCE_FLAG_SHAREABLE - * DRM_FENCE_MASK_DRIVER - */ - -int drmFenceCreate(int fd, unsigned flags, int fence_class, unsigned type, - drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.flags = flags; - arg.type = type; - arg.fence_class = fence_class; - - if (drmIoctl(fd, DRM_IOCTL_FENCE_CREATE, &arg)) - return -errno; - fence->handle = arg.handle; - fence->fence_class = arg.fence_class; - fence->type = arg.type; - fence->flags = arg.flags; - fence->signaled = 0; - return 0; -} - -/* - * Valid flags are - * DRM_FENCE_FLAG_SHAREABLE - * DRM_FENCE_MASK_DRIVER - */ - -int drmFenceBuffers(int fd, unsigned flags, uint32_t fence_class, drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.flags = flags; - arg.fence_class = fence_class; - - if (drmIoctl(fd, DRM_IOCTL_FENCE_BUFFERS, &arg)) - return -errno; - fence->handle = arg.handle; - fence->fence_class = arg.fence_class; - fence->type = arg.type; - fence->flags = arg.flags; - fence->sequence = arg.sequence; - fence->signaled = 0; - return 0; -} - -int drmFenceReference(int fd, unsigned handle, drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = handle; - - if (drmIoctl(fd, DRM_IOCTL_FENCE_REFERENCE, &arg)) - return -errno; - fence->handle = arg.handle; - fence->fence_class = arg.fence_class; - fence->type = arg.type; - fence->flags = arg.flags; - fence->signaled = arg.signaled; - return 0; -} - -int drmFenceUnreference(int fd, const drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - - if (drmIoctl(fd, DRM_IOCTL_FENCE_UNREFERENCE, &arg)) - return -errno; - return 0; -} - -int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - arg.type = flush_type; - - if (drmIoctl(fd, DRM_IOCTL_FENCE_FLUSH, &arg)) - return -errno; - fence->fence_class = arg.fence_class; - fence->type = arg.type; - fence->signaled = arg.signaled; - return arg.error; -} - -int drmFenceUpdate(int fd, drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - - if (drmIoctl(fd, DRM_IOCTL_FENCE_SIGNALED, &arg)) - return -errno; - fence->fence_class = arg.fence_class; - fence->type = arg.type; - fence->signaled = arg.signaled; - return 0; -} - -int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType, - int *signaled) -{ - if ((fence->flags & DRM_FENCE_FLAG_SHAREABLE) || - ((fenceType & fence->signaled) != fenceType)) { - int ret = drmFenceFlush(fd, fence, fenceType); - if (ret) - return ret; - } - - *signaled = ((fenceType & fence->signaled) == fenceType); - - return 0; -} - -/* - * Valid flags are - * DRM_FENCE_FLAG_SHAREABLE - * DRM_FENCE_MASK_DRIVER - */ - - -int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.fence_class = fence->fence_class; - arg.flags = flags; - arg.handle = fence->handle; - arg.type = emit_type; - - if (drmIoctl(fd, DRM_IOCTL_FENCE_EMIT, &arg)) - return -errno; - fence->fence_class = arg.fence_class; - fence->type = arg.type; - fence->signaled = arg.signaled; - fence->sequence = arg.sequence; - return 0; -} - -/* - * Valid flags are - * DRM_FENCE_FLAG_WAIT_LAZY - * DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS - */ - #define DRM_IOCTL_TIMEOUT_USEC 3000000UL static unsigned long @@ -2558,377 +2399,6 @@ drmIoctlTimeout(int fd, unsigned long request, void *argp) - -int drmFenceWait(int fd, unsigned flags, drmFence *fence, unsigned flush_type) -{ - drm_fence_arg_t arg; - int ret; - - if (flush_type == 0) { - flush_type = fence->type; - } - - if (!(fence->flags & DRM_FENCE_FLAG_SHAREABLE)) { - if ((flush_type & fence->signaled) == flush_type) { - return 0; - } - } - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - arg.type = flush_type; - arg.flags = flags; - - - ret = drmIoctlTimeout(fd, DRM_IOCTL_FENCE_WAIT, &arg); - if (ret) - return ret; - - fence->fence_class = arg.fence_class; - fence->type = arg.type; - fence->signaled = arg.signaled; - return arg.error; -} - -static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf) -{ - buf->handle = rep->handle; - buf->flags = rep->flags; - buf->size = rep->size; - buf->offset = rep->offset; - buf->mapHandle = rep->arg_handle; - buf->proposedFlags = rep->proposed_flags; - buf->start = rep->buffer_start; - buf->fenceFlags = rep->fence_flags; - buf->replyFlags = rep->rep_flags; - buf->pageAlignment = rep->page_alignment; - buf->tileInfo = rep->tile_info; - buf->hwTileStride = rep->hw_tile_stride; - buf->desiredTileStride = rep->desired_tile_stride; -} - - - -int drmBOCreate(int fd, unsigned long size, - unsigned pageAlignment, void *user_buffer, - uint64_t flags, - unsigned hint, drmBO *buf) -{ - struct drm_bo_create_arg arg; - struct drm_bo_create_req *req = &arg.d.req; - struct drm_bo_info_rep *rep = &arg.d.rep; - int ret; - - memset(buf, 0, sizeof(*buf)); - memset(&arg, 0, sizeof(arg)); - req->flags = flags; - req->hint = hint; - req->size = size; - req->page_alignment = pageAlignment; - req->buffer_start = (unsigned long) user_buffer; - - buf->virtual = NULL; - - ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_CREATE, &arg); - if (ret) - return ret; - - drmBOCopyReply(rep, buf); - buf->virtual = user_buffer; - buf->mapCount = 0; - - return 0; -} - -int drmBOReference(int fd, unsigned handle, drmBO *buf) -{ - struct drm_bo_reference_info_arg arg; - struct drm_bo_handle_arg *req = &arg.d.req; - struct drm_bo_info_rep *rep = &arg.d.rep; - - memset(&arg, 0, sizeof(arg)); - req->handle = handle; - - if (drmIoctl(fd, DRM_IOCTL_BO_REFERENCE, &arg)) - return -errno; - - drmBOCopyReply(rep, buf); - buf->mapVirtual = NULL; - buf->mapCount = 0; - buf->virtual = NULL; - - return 0; -} - -int drmBOUnreference(int fd, drmBO *buf) -{ - struct drm_bo_handle_arg arg; - - if (buf->mapVirtual && buf->mapHandle) { - (void) munmap(buf->mapVirtual, buf->start + buf->size); - buf->mapVirtual = NULL; - buf->virtual = NULL; - } - - memset(&arg, 0, sizeof(arg)); - arg.handle = buf->handle; - - if (drmIoctl(fd, DRM_IOCTL_BO_UNREFERENCE, &arg)) - return -errno; - - buf->handle = 0; - return 0; -} - - -/* - * Flags can be DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE or'ed together - * Hint currently be DRM_BO_HINT_DONT_BLOCK, which makes the - * call return an -EBUSY if it can' immediately honor the mapping request. - */ - -int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint, - void **address) -{ - struct drm_bo_map_wait_idle_arg arg; - struct drm_bo_info_req *req = &arg.d.req; - struct drm_bo_info_rep *rep = &arg.d.rep; - int ret = 0; - - /* - * Make sure we have a virtual address of the buffer. - */ - - if (!buf->virtual) { - drmAddress virtual; - virtual = mmap(0, buf->size + buf->start, - PROT_READ | PROT_WRITE, MAP_SHARED, - fd, buf->mapHandle); - if (virtual == MAP_FAILED) { - ret = -errno; - } - if (ret) - return ret; - buf->mapVirtual = virtual; - buf->virtual = ((char *) virtual) + buf->start; - } - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->mask = mapFlags; - req->hint = mapHint; - - /* - * May hang if the buffer object is busy. - * This IOCTL synchronizes the buffer. - */ - - ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_MAP, &arg); - if (ret) - return ret; - - drmBOCopyReply(rep, buf); - buf->mapFlags = mapFlags; - ++buf->mapCount; - *address = buf->virtual; - - return 0; -} - - -int drmBOUnmap(int fd, drmBO *buf) -{ - struct drm_bo_handle_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = buf->handle; - - if (drmIoctl(fd, DRM_IOCTL_BO_UNMAP, &arg)) { - return -errno; - } - buf->mapCount--; - return 0; -} - -int drmBOSetStatus(int fd, drmBO *buf, - uint64_t flags, uint64_t mask, - unsigned int hint, - unsigned int desired_tile_stride, - unsigned int tile_info) -{ - - struct drm_bo_map_wait_idle_arg arg; - struct drm_bo_info_req *req = &arg.d.req; - struct drm_bo_info_rep *rep = &arg.d.rep; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - req->mask = mask; - req->flags = flags; - req->handle = buf->handle; - req->hint = hint; - req->desired_tile_stride = desired_tile_stride; - req->tile_info = tile_info; - - ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_SETSTATUS, &arg); - if (ret) - return ret; - - drmBOCopyReply(rep, buf); - return 0; -} - - -int drmBOInfo(int fd, drmBO *buf) -{ - struct drm_bo_reference_info_arg arg; - struct drm_bo_handle_arg *req = &arg.d.req; - struct drm_bo_info_rep *rep = &arg.d.rep; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - - ret = drmIoctl(fd, DRM_IOCTL_BO_INFO, &arg); - if (ret) - return -errno; - - drmBOCopyReply(rep, buf); - return 0; -} - -int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint) -{ - struct drm_bo_map_wait_idle_arg arg; - struct drm_bo_info_req *req = &arg.d.req; - struct drm_bo_info_rep *rep = &arg.d.rep; - int ret = 0; - - if ((buf->flags & DRM_BO_FLAG_SHAREABLE) || - (buf->replyFlags & DRM_BO_REP_BUSY)) { - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->hint = hint; - - ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_WAIT_IDLE, &arg); - if (ret) - return ret; - - drmBOCopyReply(rep, buf); - } - return 0; -} - -int drmBOBusy(int fd, drmBO *buf, int *busy) -{ - int ret = drmBOInfo(fd, buf); - - if (ret) - return ret; - - *busy = (buf->replyFlags & DRM_BO_REP_BUSY); - return 0; -} - -int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, - unsigned memType) -{ - struct drm_mm_init_arg arg; - - memset(&arg, 0, sizeof(arg)); - - arg.magic = DRM_BO_INIT_MAGIC; - arg.major = DRM_BO_INIT_MAJOR; - arg.minor = DRM_BO_INIT_MINOR; - arg.p_offset = pOffset; - arg.p_size = pSize; - arg.mem_type = memType; - - if (drmIoctl(fd, DRM_IOCTL_MM_INIT, &arg)) - return -errno; - return 0; -} - -int drmMMTakedown(int fd, unsigned memType) -{ - struct drm_mm_type_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.mem_type = memType; - - if (drmIoctl(fd, DRM_IOCTL_MM_TAKEDOWN, &arg)) - return -errno; - return 0; -} - -/* - * If this function returns an error, and lockBM was set to 1, - * the buffer manager is NOT locked. - */ - -int drmMMLock(int fd, unsigned memType, int lockBM, int ignoreNoEvict) -{ - struct drm_mm_type_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.mem_type = memType; - arg.lock_flags |= (lockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0; - arg.lock_flags |= (ignoreNoEvict) ? DRM_BO_LOCK_IGNORE_NO_EVICT : 0; - - return drmIoctlTimeout(fd, DRM_IOCTL_MM_LOCK, &arg); -} - -int drmMMUnlock(int fd, unsigned memType, int unlockBM) -{ - struct drm_mm_type_arg arg; - - memset(&arg, 0, sizeof(arg)); - - arg.mem_type = memType; - arg.lock_flags |= (unlockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0; - - return drmIoctlTimeout(fd, DRM_IOCTL_MM_UNLOCK, &arg); -} - -int drmMMInfo(int fd, unsigned memType, uint64_t *size) -{ - struct drm_mm_info_arg arg; - - memset(&arg, 0, sizeof(arg)); - - arg.mem_type = memType; - - if (drmIoctl(fd, DRM_IOCTL_MM_INFO, &arg)) - return -errno; - - *size = arg.p_size; - return 0; -} - -int drmBOVersion(int fd, unsigned int *major, - unsigned int *minor, - unsigned int *patchlevel) -{ - struct drm_bo_version_arg arg; - int ret; - - memset(&arg, 0, sizeof(arg)); - ret = drmIoctl(fd, DRM_IOCTL_BO_VERSION, &arg); - if (ret) - return -errno; - - if (major) - *major = arg.major; - if (minor) - *minor = arg.minor; - if (patchlevel) - *patchlevel = arg.patchlevel; - - return 0; -} - - - #define DRM_MAX_FDS 16 static struct { char *BusID; diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 84cf69bd..a1c1be89 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1061,7 +1061,7 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo, * Doesn't do any fence flushing as opposed to the drm_bo_busy function. */ -static int drm_bo_quick_busy(struct drm_buffer_object *bo, int check_unfenced) +int drm_bo_quick_busy(struct drm_buffer_object *bo, int check_unfenced) { struct drm_fence_object *fence = bo->fence; @@ -1712,7 +1712,7 @@ EXPORT_SYMBOL(drm_bo_clean_mm); *point since we have the hardware lock. */ -static int drm_bo_lock_mm(struct drm_device *dev, unsigned mem_type) +int drm_bo_lock_mm(struct drm_device *dev, unsigned mem_type) { int ret; struct drm_buffer_manager *bm = &dev->bm; @@ -1861,7 +1861,6 @@ int drm_bo_driver_init(struct drm_device *dev) int ret = -EINVAL; bm->dummy_read_page = NULL; - drm_bo_init_lock(&bm->bm_lock); mutex_lock(&dev->struct_mutex); if (!driver) goto out_unlock; diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 032687f7..a8aa84db 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -879,23 +879,6 @@ extern int drm_mem_reg_ioremap(struct drm_device *dev, struct drm_bo_mem_reg * m void **virtual); extern void drm_mem_reg_iounmap(struct drm_device *dev, struct drm_bo_mem_reg * mem, void *virtual); -/* - * drm_bo_lock.c - * Simple replacement for the hardware lock on buffer manager init and clean. - */ - - -extern void drm_bo_init_lock(struct drm_bo_lock *lock); -extern void drm_bo_read_unlock(struct drm_bo_lock *lock); -extern int drm_bo_read_lock(struct drm_bo_lock *lock, - int interruptible); -extern int drm_bo_write_lock(struct drm_bo_lock *lock, - int interruptible, - struct drm_file *file_priv); - -extern int drm_bo_write_unlock(struct drm_bo_lock *lock, - struct drm_file *file_priv); - #ifdef CONFIG_DEBUG_MUTEXES #define DRM_ASSERT_LOCKED(_mutex) \ BUG_ON(!mutex_is_locked(_mutex) || \ diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 0d5242d3..9a215161 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -715,13 +715,8 @@ static int drm_bo_vm_fault(struct vm_area_struct *vma, unsigned long ret = VM_FAULT_NOPAGE; dev = bo->dev; - err = drm_bo_read_lock(&dev->bm.bm_lock, 1); - if (err) - return VM_FAULT_NOPAGE; - err = mutex_lock_interruptible(&bo->mutex); if (err) { - drm_bo_read_unlock(&dev->bm.bm_lock); return VM_FAULT_NOPAGE; } @@ -788,7 +783,6 @@ static int drm_bo_vm_fault(struct vm_area_struct *vma, out_unlock: BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNLOCKED); mutex_unlock(&bo->mutex); - drm_bo_read_unlock(&dev->bm.bm_lock); return ret; } #endif diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3e6a6626..bd52a057 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -689,7 +689,6 @@ static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; int i; From 296073dc5f0bf3f8b74a7d6db48b05c09a1b9242 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 31 Jul 2008 14:39:25 +1000 Subject: [PATCH 12/49] drm: remove object hash --- linux-core/drmP.h | 2 -- linux-core/drm_drv.c | 1 - linux-core/drm_stub.c | 6 ------ 3 files changed, 9 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 4938881f..59d44ac2 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -166,7 +166,6 @@ typedef unsigned long uintptr_t; #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) #define DRM_MAP_HASH_OFFSET 0x10000000 #define DRM_MAP_HASH_ORDER 12 -#define DRM_OBJECT_HASH_ORDER 12 #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1) #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16) /* @@ -888,7 +887,6 @@ struct drm_device { int map_count; /**< Number of mappable regions */ struct drm_open_hash map_hash; /**< User token hash table for maps */ struct drm_memrange offset_manager; /**< User token manager */ - struct drm_open_hash object_hash; /**< User token hash table for objects */ struct address_space *dev_mapping; /**< For unmap_mapping_range() */ struct page *ttm_dummy_page; diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 2c3e29f0..c3cc620a 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -399,7 +399,6 @@ static void drm_cleanup(struct drm_device * dev) drm_ctxbitmap_cleanup(dev); drm_ht_remove(&dev->map_hash); drm_memrange_takedown(&dev->offset_manager); - drm_ht_remove(&dev->object_hash); drm_put_minor(dev, &dev->primary); if (drm_core_check_feature(dev, DRIVER_MODESET)) diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index c62b901d..97533d72 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -207,12 +207,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, return -ENOMEM; } - if (drm_ht_create(&dev->object_hash, DRM_OBJECT_HASH_ORDER)) { - drm_ht_remove(&dev->map_hash); - drm_memrange_takedown(&dev->offset_manager); - return -ENOMEM; - } - /* the DRM has 6 counters */ dev->counters = 6; dev->types[0] = _DRM_STAT_LOCK; From 922f74f3c95fae39ffe8cf0659fa47e0bc354076 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:52:58 +1000 Subject: [PATCH 13/49] drm: remove unneeded debugging --- linux-core/ati_pcigart.c | 1 - 1 file changed, 1 deletion(-) diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index 3aa445e8..48c7988f 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -111,7 +111,6 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info /* we need to support large memory configurations */ if (!entry) { - DRM_ERROR("no scatter/gather memory!\n"); return 0; } From 129c8a11814741a997e3d039ab4be542d38e5ed8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:53:14 +1000 Subject: [PATCH 14/49] modesetting: pick_crtcs can't be static --- linux-core/drm_crtc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/drm_crtc_helper.c b/linux-core/drm_crtc_helper.c index ee1dc258..dc18dbb4 100644 --- a/linux-core/drm_crtc_helper.c +++ b/linux-core/drm_crtc_helper.c @@ -203,7 +203,7 @@ EXPORT_SYMBOL(drm_helper_disable_unused_functions); * LOCKING: * Caller must hold mode config lock. */ -static void drm_pick_crtcs (struct drm_device *dev) +void drm_pick_crtcs (struct drm_device *dev) { int c, o, assigned; struct drm_connector *connector, *connector_equal; From af6efc3d778b96164849f822331938c4cdf8f4b2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:53:45 +1000 Subject: [PATCH 15/49] i915/radeon: use rmmap locked --- shared-core/i915_init.c | 2 +- shared-core/radeon_cp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 3a652e8d..dc218688 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -443,7 +443,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) return; if (master_priv->sarea) - drm_rmmap(dev, master_priv->sarea); + drm_rmmap_locked(dev, master_priv->sarea); drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 48f72ab0..b69fadbb 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -2535,7 +2535,7 @@ void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) master_priv->sarea_priv = NULL; if (master_priv->sarea) - drm_rmmap(dev, master_priv->sarea); + drm_rmmap_locked(dev, master_priv->sarea); drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); From 717dd804d0d1d9984345a998b28ee47079c70639 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:54:32 +1000 Subject: [PATCH 16/49] drm: fixup master code to use krefs --- linux-core/drmP.h | 13 ++++--- linux-core/drm_drv.c | 10 ++--- linux-core/drm_fops.c | 31 ++++++++++------ linux-core/drm_stub.c | 85 ++++++++++++++++++++++++++----------------- 4 files changed, 82 insertions(+), 57 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 59d44ac2..848fa885 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -670,7 +670,9 @@ struct drm_gem_object { /* per-master structure */ struct drm_master { - + + struct kref refcount; /* refcount for this master */ + struct list_head head; /**< each minor contains a list of masters */ struct drm_minor *minor; /**< link back to minor we are a master for */ @@ -1345,12 +1347,13 @@ extern int drm_setmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern struct drm_master *drm_get_master(struct drm_minor *minor); -extern void drm_put_master(struct drm_master *master); +struct drm_master *drm_master_create(struct drm_minor *minor); +extern struct drm_master *drm_master_get(struct drm_master *master); +extern void drm_master_put(struct drm_master **master); extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, - struct drm_driver *driver); + struct drm_driver *driver); extern int drm_put_dev(struct drm_device *dev); -extern int drm_put_minor(struct drm_device *dev, struct drm_minor **p); +extern int drm_put_minor(struct drm_minor **minor_p); extern unsigned int drm_debug; /* 1 to enable debug output */ extern struct class *drm_class; diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index c3cc620a..751322db 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -191,11 +191,6 @@ int drm_lastclose(struct drm_device * dev) drm_drawable_free_all(dev); del_timer(&dev->timer); - if (dev->primary->master) { - drm_put_master(dev->primary->master); - dev->primary->master = NULL; - } - /* Clear AGP information */ if (drm_core_has_AGP(dev) && dev->agp) { struct drm_agp_mem *entry, *tempe; @@ -400,9 +395,10 @@ static void drm_cleanup(struct drm_device * dev) drm_ht_remove(&dev->map_hash); drm_memrange_takedown(&dev->offset_manager); - drm_put_minor(dev, &dev->primary); if (drm_core_check_feature(dev, DRIVER_MODESET)) - drm_put_minor(dev, &dev->control); + drm_put_minor(&dev->control); + + drm_put_minor(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index 8eb20b47..f45d5e46 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -260,28 +260,34 @@ static int drm_open_helper(struct inode *inode, struct file *filp, /* if there is no current master make this fd it */ mutex_lock(&dev->struct_mutex); if (!priv->minor->master) { - priv->minor->master = drm_get_master(priv->minor); + /* create a new master */ + priv->minor->master = drm_master_create(priv->minor); if (!priv->minor->master) { ret = -ENOMEM; goto out_free; } priv->is_master = 1; - priv->master = priv->minor->master; + /* take another reference for the copy in the local file priv */ + priv->master = drm_master_get(priv->minor->master); priv->authenticated = 1; + mutex_unlock(&dev->struct_mutex); if (dev->driver->master_create) { ret = dev->driver->master_create(dev, priv->master); if (ret) { - drm_put_master(priv->minor->master); - priv->minor->master = priv->master = NULL; + mutex_lock(&dev->struct_mutex); + /* drop both references if this fails */ + drm_master_put(&priv->minor->master); + drm_master_put(&priv->master); mutex_unlock(&dev->struct_mutex); goto out_free; } } } else { - priv->master = priv->minor->master; + /* get a reference to the master */ + priv->master = drm_master_get(priv->minor->master); mutex_unlock(&dev->struct_mutex); } @@ -453,6 +459,8 @@ int drm_release(struct inode *inode, struct file *filp) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_fb_release(filp); + mutex_lock(&dev->struct_mutex); + if (file_priv->is_master) { struct drm_file *temp; list_for_each_entry(temp, &dev->filelist, lhead) { @@ -461,18 +469,17 @@ int drm_release(struct inode *inode, struct file *filp) temp->authenticated = 0; } - if (file_priv->minor->master == file_priv->master) - file_priv->minor->master = NULL; - drm_put_master(file_priv->master); + if (file_priv->minor->master == file_priv->master) { + /* drop the reference held my the minor */ + drm_master_put(&file_priv->minor->master); + } } - file_priv->master = NULL; + /* drop the reference held my the file priv */ + drm_master_put(&file_priv->master); file_priv->is_master = 0; - mutex_lock(&dev->struct_mutex); - list_del(&file_priv->lhead); - mutex_unlock(&dev->struct_mutex); if (dev->driver->postclose) diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index 97533d72..4654dca1 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -88,30 +88,7 @@ again: return new_id; } -int drm_setmaster_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - if (file_priv->minor->master && file_priv->minor->master != file_priv->master) - return -EINVAL; - - if (!file_priv->master) - return -EINVAL; - - if (!file_priv->minor->master && file_priv->minor->master != file_priv->master) - file_priv->minor->master = file_priv->master; - return 0; -} - -int drm_dropmaster_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - if (!file_priv->master) - return -EINVAL; - file_priv->minor->master = NULL; - return 0; -} - -struct drm_master *drm_get_master(struct drm_minor *minor) +struct drm_master *drm_master_create(struct drm_minor *minor) { struct drm_master *master; @@ -119,7 +96,7 @@ struct drm_master *drm_get_master(struct drm_minor *minor) if (!master) return NULL; -// INIT_LIST_HEAD(&master->filelist); + kref_init(&master->refcount); spin_lock_init(&master->lock.spinlock); init_waitqueue_head(&master->lock.lock_queue); drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); @@ -131,8 +108,15 @@ struct drm_master *drm_get_master(struct drm_minor *minor) return master; } -void drm_put_master(struct drm_master *master) +struct drm_master *drm_master_get(struct drm_master *master) { + kref_get(&master->refcount); + return master; +} + +static void drm_master_destroy(struct kref *kref) +{ + struct drm_master *master = container_of(kref, struct drm_master, refcount); struct drm_magic_entry *pt, *next; struct drm_device *dev = master->minor->dev; @@ -166,21 +150,56 @@ void drm_put_master(struct drm_master *master) drm_free(master, sizeof(*master), DRM_MEM_DRIVER); } +void drm_master_put(struct drm_master **master) +{ + kref_put(&(*master)->refcount, drm_master_destroy); + *master = NULL; +} + +int drm_setmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + if (file_priv->minor->master && file_priv->minor->master != file_priv->master) + return -EINVAL; + + if (!file_priv->master) + return -EINVAL; + + if (!file_priv->minor->master && file_priv->minor->master != file_priv->master) { + mutex_lock(&dev->struct_mutex); + file_priv->minor->master = drm_master_get(file_priv->master); + mutex_unlock(&dev->struct_mutex); + } + + return 0; +} + +int drm_dropmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + if (!file_priv->master) + return -EINVAL; + mutex_lock(&dev->struct_mutex); + drm_master_put(&file_priv->minor->master); + mutex_unlock(&dev->struct_mutex); + return 0; +} + static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) { int retcode; + INIT_LIST_HEAD(&dev->filelist); INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->maplist); - INIT_LIST_HEAD(&dev->filelist); spin_lock_init(&dev->count_lock); spin_lock_init(&dev->drw_lock); spin_lock_init(&dev->tasklet_lock); -// spin_lock_init(&dev->lock.spinlock); + init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); @@ -402,10 +421,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, return 0; err_g5: - drm_put_minor(dev, &dev->primary); + drm_put_minor(&dev->primary); err_g4: if (drm_core_check_feature(dev, DRIVER_MODESET)) - drm_put_minor(dev, &dev->control); + drm_put_minor(&dev->control); err_g3: if (!drm_fb_loaded) pci_disable_device(pdev); @@ -456,14 +475,14 @@ int drm_put_dev(struct drm_device * dev) * last minor released. * */ -int drm_put_minor(struct drm_device *dev, struct drm_minor **minor_p) +int drm_put_minor(struct drm_minor **minor_p) { struct drm_minor *minor = *minor_p; DRM_DEBUG("release secondary minor %d\n", minor->index); if (minor->type == DRM_MINOR_LEGACY) { - if (dev->driver->proc_cleanup) - dev->driver->proc_cleanup(minor); + if (minor->dev->driver->proc_cleanup) + minor->dev->driver->proc_cleanup(minor); drm_proc_cleanup(minor, drm_proc_root); } drm_sysfs_device_remove(minor); From dff84851516a71639d734e134c584f6ed4d3ee07 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:55:12 +1000 Subject: [PATCH 17/49] drm: remove unused types --- shared-core/drm.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/shared-core/drm.h b/shared-core/drm.h index 76d2c4c5..ed390885 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1096,11 +1096,6 @@ typedef struct drm_agp_binding drm_agp_binding_t; typedef struct drm_agp_info drm_agp_info_t; typedef struct drm_scatter_gather drm_scatter_gather_t; typedef struct drm_set_version drm_set_version_t; - -typedef struct drm_fence_arg drm_fence_arg_t; -typedef struct drm_mm_type_arg drm_mm_type_arg_t; -typedef struct drm_mm_init_arg drm_mm_init_arg_t; -typedef enum drm_bo_type drm_bo_type_t; #endif #endif From 29649ddedee6b07b922c99233b8afc7c3a1db66f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:56:08 +1000 Subject: [PATCH 18/49] radeon: don't use ring if cp not going --- linux-core/radeon_buffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-core/radeon_buffer.c b/linux-core/radeon_buffer.c index e9ba11d4..a4ac38c1 100644 --- a/linux-core/radeon_buffer.c +++ b/linux-core/radeon_buffer.c @@ -55,10 +55,14 @@ int radeon_invalidate_caches(struct drm_device * dev, uint64_t flags) drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; + if (!dev_priv->cp_running) + return 0; + BEGIN_RING(4); RADEON_FLUSH_CACHE(); RADEON_FLUSH_ZCACHE(); ADVANCE_RING(); + COMMIT_RING(); return 0; } From aa8e15f8b51e555e78cb93e279bad5843eea5391 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:59:17 +1000 Subject: [PATCH 19/49] radeon: add userspace mm enable switch --- shared-core/radeon_cp.c | 10 ++++++---- shared-core/radeon_drm.h | 1 + shared-core/radeon_drv.h | 2 ++ shared-core/radeon_state.c | 3 +++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index b69fadbb..430f5493 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1364,8 +1364,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev) if (dev_priv->gart_info.bus_addr) { /* Turn off PCI GART */ radeon_set_pcigart(dev_priv, 0); - if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) - DRM_ERROR("failed to cleanup PCI GART!\n"); + drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info); } if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) @@ -1373,6 +1372,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev) if (dev_priv->pcigart_offset_set == 1) { drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); dev_priv->gart_info.addr = NULL; + dev_priv->pcigart_offset_set = 0; } } } @@ -1563,8 +1563,10 @@ void radeon_do_release(struct drm_device * dev) radeon_mem_takedown(&(dev_priv->gart_heap)); radeon_mem_takedown(&(dev_priv->fb_heap)); - - radeon_gem_mm_fini(dev); + if (dev_priv->user_mm_enable) { + radeon_gem_mm_fini(dev); + dev_priv->user_mm_enable = false; + } /* deallocate kernel resources */ radeon_do_cleanup_cp(dev); diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 8ee1baa7..8bb5d87c 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -768,6 +768,7 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ #define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ +#define RADEON_SETPARAM_MM_INIT 7 /* Initialise the mm */ /* 1.14: Clients can allocate/free a surface */ typedef struct drm_radeon_surface_alloc { diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index e55a9697..0363dfd4 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -314,6 +314,8 @@ typedef struct drm_radeon_private { int new_memmap; + bool user_mm_enable; + int gart_size; u32 gart_vm_start; unsigned long gart_buffers_offset; diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 00160fbf..ca10db4b 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3182,6 +3182,9 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil case RADEON_SETPARAM_VBLANK_CRTC: return radeon_vblank_crtc_set(dev, sp->value); break; + case RADEON_SETPARAM_MM_INIT: + dev_priv->user_mm_enable = true; + return radeon_gem_mm_init(dev); default: DRM_DEBUG("Invalid parameter %d\n", sp->param); return -EINVAL; From fd75c02ddd380c102ca089f015f14dfe964910b1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Aug 2008 14:59:49 +1000 Subject: [PATCH 20/49] drm: finish bo after lastclose --- linux-core/drm_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 751322db..c503d484 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -170,8 +170,6 @@ int drm_lastclose(struct drm_device * dev) DRM_DEBUG("\n"); - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - drm_bo_driver_finish(dev); /* * We can't do much about this function failing. @@ -181,6 +179,8 @@ int drm_lastclose(struct drm_device * dev) dev->driver->lastclose(dev); DRM_DEBUG("driver lastclose completed\n"); + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + drm_bo_driver_finish(dev); /* if (dev->irq_enabled) drm_irq_uninstall(dev); */ From 4748fbcbd7b0337448ce88c2cdbbc500ff959e42 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 5 Aug 2008 11:36:20 +1000 Subject: [PATCH 21/49] radeon: fix blit due to registers wrong --- linux-core/radeon_reg.h | 23 +++++++++++++---------- shared-core/r300_reg.h | 14 +------------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index 784b3b50..0f2d239c 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -2095,16 +2095,19 @@ # define RADEON_STENCIL_ENABLE (1 << 7) # define RADEON_Z_ENABLE (1 << 8) # define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9) -# define RADEON_COLOR_FORMAT_ARGB1555 (3 << 10) -# define RADEON_COLOR_FORMAT_RGB565 (4 << 10) -# define RADEON_COLOR_FORMAT_ARGB8888 (6 << 10) -# define RADEON_COLOR_FORMAT_RGB332 (7 << 10) -# define RADEON_COLOR_FORMAT_Y8 (8 << 10) -# define RADEON_COLOR_FORMAT_RGB8 (9 << 10) -# define RADEON_COLOR_FORMAT_YUV422_VYUY (11 << 10) -# define RADEON_COLOR_FORMAT_YUV422_YVYU (12 << 10) -# define RADEON_COLOR_FORMAT_aYUV444 (14 << 10) -# define RADEON_COLOR_FORMAT_ARGB4444 (15 << 10) +# define RADEON_RB3D_COLOR_FORMAT_SHIFT 10 + +# define RADEON_COLOR_FORMAT_ARGB1555 3 +# define RADEON_COLOR_FORMAT_RGB565 4 +# define RADEON_COLOR_FORMAT_ARGB8888 6 +# define RADEON_COLOR_FORMAT_RGB332 7 +# define RADEON_COLOR_FORMAT_Y8 8 +# define RADEON_COLOR_FORMAT_RGB8 9 +# define RADEON_COLOR_FORMAT_YUV422_VYUY 11 +# define RADEON_COLOR_FORMAT_YUV422_YVYU 12 +# define RADEON_COLOR_FORMAT_aYUV444 14 +# define RADEON_COLOR_FORMAT_ARGB4444 15 + # define RADEON_CLRCMP_FLIP_ENABLE (1 << 14) #define RADEON_RB3D_COLOROFFSET 0x1c40 # define RADEON_COLOROFFSET_MASK 0xfffffff0 diff --git a/shared-core/r300_reg.h b/shared-core/r300_reg.h index 0be01fc7..65c5606a 100644 --- a/shared-core/r300_reg.h +++ b/shared-core/r300_reg.h @@ -129,15 +129,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* END: Wild guesses */ #define R300_SE_VTE_CNTL 0x20b0 -# define R300_VPORT_X_SCALE_ENA 0x00000001 -# define R300_VPORT_X_OFFSET_ENA 0x00000002 -# define R300_VPORT_Y_SCALE_ENA 0x00000004 -# define R300_VPORT_Y_OFFSET_ENA 0x00000008 -# define R300_VPORT_Z_SCALE_ENA 0x00000010 -# define R300_VPORT_Z_OFFSET_ENA 0x00000020 -# define R300_VTX_XY_FMT 0x00000100 -# define R300_VTX_Z_FMT 0x00000200 -# define R300_VTX_W0_FMT 0x00000400 # define R300_VTX_W0_NORMALIZE 0x00000800 # define R300_VTX_ST_DENORMALIZED 0x00001000 @@ -493,7 +484,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */ # define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24 -#define R300_GB_SELECT 0x401C + # define R300_GB_FOG_SELECT_C0A 0 # define R300_GB_FOG_SELECT_C1A 1 # define R300_GB_FOG_SELECT_C2A 2 @@ -934,7 +925,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* 32 bit chroma key */ #define R300_TX_CHROMA_KEY_0 0x4580 /* ff00ff00 == { 0, 1.0, 0, 1.0 } */ -#define R300_TX_BORDER_COLOR_0 0x45C0 /* END: Texture specification */ @@ -1319,7 +1309,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* gap */ -#define R300_RB3D_COLOROFFSET0 0x4E28 # define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */ #define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */ #define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */ @@ -1331,7 +1320,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Bit 17: 4x2 tiles * Bit 18: Extremely weird tile like, but some pixels duplicated? */ -#define R300_RB3D_COLORPITCH0 0x4E38 # define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */ # define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */ # define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */ From 513d4c3ff1937159e0d32047376415df09031ce6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 6 Aug 2008 10:21:20 +1000 Subject: [PATCH 22/49] radeon: fix setting new memmap in right place --- shared-core/radeon_cp.c | 2 +- shared-core/radeon_drv.h | 2 +- shared-core/radeon_state.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 430f5493..4c03f739 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -2301,7 +2301,7 @@ int radeon_modeset_cp_init(struct drm_device *dev) dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; - dev_priv->new_memmap = 1; + dev_priv->new_memmap = true; r300_init_reg_flags(dev); diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 0363dfd4..94975e4d 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -312,7 +312,7 @@ typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; - int new_memmap; + bool new_memmap; bool user_mm_enable; diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index ca10db4b..e168ea02 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3184,6 +3184,7 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil break; case RADEON_SETPARAM_MM_INIT: dev_priv->user_mm_enable = true; + dev_priv->new_memmap = true; return radeon_gem_mm_init(dev); default: DRM_DEBUG("Invalid parameter %d\n", sp->param); From 04b5584c62fa3311e717692e261870276cbd6350 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 6 Aug 2008 15:56:08 +1000 Subject: [PATCH 23/49] pcigart: fixup memset + remove wbinvd --- linux-core/ati_pcigart.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index 48c7988f..9b954291 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -90,7 +90,7 @@ int drm_ati_alloc_pcigart_table(struct drm_device *dev, if (gart_info->table_handle == NULL) return -ENOMEM; - memset(gart_info->table_handle, 0, gart_info->table_size); + memset(gart_info->table_handle->vaddr, 0, gart_info->table_size); return 0; } EXPORT_SYMBOL(drm_ati_alloc_pcigart_table); @@ -205,11 +205,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga ret = 1; -#if defined(__i386__) || defined(__x86_64__) - wbinvd(); -#else mb(); -#endif done: gart_info->addr = address; @@ -265,11 +261,7 @@ static int ati_pcigart_bind_ttm(struct drm_ttm_backend *backend, gart_insert_page_into_table(info, page_base, pci_gart + j); } -#if defined(__i386__) || defined(__x86_64__) - wbinvd(); -#else mb(); -#endif atipci_be->gart_flush_fn(atipci_be->dev); From a6c075fca6faf83ccbfa38fb27dc4f743b6cdd61 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 6 Aug 2008 15:57:38 +1000 Subject: [PATCH 24/49] drm: don't teardown things in modeset paths --- linux-core/drm_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index c503d484..2a6bebd7 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -182,8 +182,8 @@ int drm_lastclose(struct drm_device * dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) drm_bo_driver_finish(dev); -/* if (dev->irq_enabled) - drm_irq_uninstall(dev); */ + if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET)) + drm_irq_uninstall(dev); /* Free drawable information memory */ mutex_lock(&dev->struct_mutex); @@ -192,7 +192,7 @@ int drm_lastclose(struct drm_device * dev) del_timer(&dev->timer); /* Clear AGP information */ - if (drm_core_has_AGP(dev) && dev->agp) { + if (drm_core_has_AGP(dev) && dev->agp && !drm_core_check_feature(dev, DRIVER_MODESET)) { struct drm_agp_mem *entry, *tempe; /* Remove AGP resources, but leave dev->agp From 64359586730268fc83ccc0db0487e217a894335b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 6 Aug 2008 15:58:09 +1000 Subject: [PATCH 25/49] radeon: just evict to TT not cached --- linux-core/radeon_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/radeon_buffer.c b/linux-core/radeon_buffer.c index a4ac38c1..5fdd9c35 100644 --- a/linux-core/radeon_buffer.c +++ b/linux-core/radeon_buffer.c @@ -265,6 +265,6 @@ uint64_t radeon_evict_flags(struct drm_buffer_object *bo) case DRM_BO_MEM_TT: return DRM_BO_FLAG_MEM_LOCAL; default: - return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED; + return DRM_BO_FLAG_MEM_TT; } } From 8c042a0b0531117f2663ae6932d299cb47941607 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 6 Aug 2008 15:59:31 +1000 Subject: [PATCH 26/49] radeon: fixup PCI GART table with GEM enabled --- linux-core/radeon_gem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 1aa3afbf..1ee48514 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -485,6 +485,7 @@ static int radeon_gart_init(struct drm_device *dev) /* setup a 32MB GART */ dev_priv->gart_size = dev_priv->mm.gart_size; + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; #if __OS_HAS_AGP /* setup VRAM vs GART here */ @@ -547,8 +548,8 @@ static int radeon_gart_init(struct drm_device *dev) dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; else dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; - dev_priv->gart_info.addr = NULL; - dev_priv->gart_info.bus_addr = 0; + dev_priv->gart_info.addr = dev_priv->gart_info.table_handle->vaddr; + dev_priv->gart_info.bus_addr = dev_priv->gart_info.table_handle->busaddr; } /* gart values setup - start the GART */ @@ -843,7 +844,7 @@ static int radeon_gem_ib_init(struct drm_device *dev) if (!dev_priv->ib_objs) goto free_all; - for (i = 0; i < RADEON_NUM_IB; i++) { + for (i = 0; i < RADEON_NUM_IB; i++) { dev_priv->ib_objs[i] = drm_calloc(1, sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); if (!dev_priv->ib_objs[i]) goto free_all; From c2184e450e4c5613c1f1a004d183ad478358013e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 8 Aug 2008 16:04:45 +1000 Subject: [PATCH 27/49] radeon: add initial support for legacy crtc/encoders. not all there yet --- linux-core/Makefile.kernel | 2 +- linux-core/radeon_combios.c | 39 ++ linux-core/radeon_display.c | 54 +- linux-core/radeon_encoders.c | 73 +-- linux-core/radeon_legacy_crtc.c | 748 ++++++++++++++++++++++++++++ linux-core/radeon_legacy_encoders.c | 391 +++++++++++++++ linux-core/radeon_mode.h | 194 +++++++- shared-core/radeon_cp.c | 8 +- shared-core/radeon_drv.h | 110 ++-- 9 files changed, 1455 insertions(+), 164 deletions(-) create mode 100644 linux-core/radeon_legacy_crtc.c create mode 100644 linux-core/radeon_legacy_encoders.c diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index b15a12ab..576de5b2 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -41,7 +41,7 @@ nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nv50_fbcon.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o radeon_gem.o \ radeon_buffer.o radeon_fence.o atom.o radeon_display.o radeon_atombios.o radeon_i2c.o radeon_connectors.o radeon_cs.o \ - atombios_crtc.o radeon_encoders.o radeon_fb.o radeon_combios.o + atombios_crtc.o radeon_encoders.o radeon_fb.o radeon_combios.o radeon_legacy_crtc.o radeon_legacy_encoders.o sis-objs := sis_drv.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o savage-objs := savage_drv.o savage_bci.o savage_state.o diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c index e2b768ca..8a1dd8b3 100644 --- a/linux-core/radeon_combios.c +++ b/linux-core/radeon_combios.c @@ -175,6 +175,45 @@ bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder) return true; } +bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint16_t tmp; + int i, n; + uint8_t ver; + + tmp = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x34); + if (!tmp) { + DRM_INFO("No TMDS info found in BIOS\n"); + return false; + } + + ver = radeon_bios8(dev_priv, tmp); + DRM_INFO("DFP table revision: %d\n", ver); + if (ver == 3) { + n = radeon_bios8(dev_priv, tmp + 5) + 1; + if (n > 4) n = 4; + for (i = 0; i < n; i++) { + encoder->tmds_pll[i].value = radeon_bios32(dev_priv, tmp+i*10+0x08); + encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmp+i*10+0x10); + } + return true; + } else if (ver == 4) { + int stride = 0; + n = radeon_bios8(dev_priv, tmp + 5) + 1; + if (n > 4) n = 4; + for (i = 0; i < n; i++) { + encoder->tmds_pll[i].value = radeon_bios32(dev_priv, tmp+stride+0x08); + encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmp+stride+0x10); + if (i == 0) stride += 10; + else stride += 6; + } + return true; + } + return false; +} + static void radeon_apply_legacy_quirks(struct drm_device *dev, int bios_index) { struct drm_radeon_private *dev_priv = dev->dev_private; diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index 7a7b5856..1e5233d2 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -116,39 +116,8 @@ void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, radeon_crtc->lut_b[regno] = blue >> 8; } -void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) -{ -} - -static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void radeon_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y) -{ - -} - -void radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y) -{ -} - -static void radeon_crtc_prepare(struct drm_crtc *crtc) -{ -} - -static void radeon_crtc_commit(struct drm_crtc *crtc) -{ -} - static void avivo_lock_cursor(struct drm_crtc *crtc, bool lock) { struct drm_radeon_private *dev_priv = crtc->dev->dev_private; @@ -263,15 +232,6 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc) kfree(radeon_crtc); } -static const struct drm_crtc_helper_funcs radeon_helper_funcs = { - .dpms = radeon_crtc_dpms, - .mode_fixup = radeon_crtc_mode_fixup, - .mode_set = radeon_crtc_mode_set, - .mode_set_base = radeon_crtc_set_base, - .prepare = radeon_crtc_prepare, - .commit = radeon_crtc_commit, -}; - static const struct drm_crtc_funcs radeon_crtc_funcs = { .cursor_set = radeon_crtc_cursor_set, .cursor_move = radeon_crtc_cursor_move, @@ -309,7 +269,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) if (dev_priv->is_atom_bios && dev_priv->chip_family > CHIP_RS690) radeon_atombios_init_crtc(dev, radeon_crtc); else - drm_crtc_helper_add(&radeon_crtc->base, &radeon_helper_funcs); + radeon_legacy_init_crtc(dev, radeon_crtc); } bool radeon_legacy_setup_enc_conn(struct drm_device *dev) @@ -360,8 +320,14 @@ bool radeon_setup_enc_conn(struct drm_device *dev) if ((mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I) || (mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_A) || (mode_info->bios_connector[i].connector_type == CONNECTOR_VGA)) { - if (radeon_is_avivo(dev_priv)) + if (radeon_is_avivo(dev_priv)) { encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 0); + } else { + if (mode_info->bios_connector[i].dac_type == DAC_PRIMARY) + encoder = radeon_encoder_legacy_primary_dac_add(dev, i, 0); +// else if (mode_info->bios_connector[i].dac_type == DAC_TVDAC) +// encoder radeon_encoder_legacy_secondary_dac_add(dev, i, 0); + } if (encoder) drm_mode_connector_attach_encoder(connector, encoder); } @@ -371,6 +337,10 @@ bool radeon_setup_enc_conn(struct drm_device *dev) (mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_D)) { if (radeon_is_avivo(dev_priv)) encoder = radeon_encoder_atom_tmds_add(dev, i, mode_info->bios_connector[i].dac_type); + else { + if (mode_info->bios_connector[i].tmds_type == TMDS_INT) + encoder = radeon_encoder_legacy_tmds_int_add(dev, i); + } if (encoder) drm_mode_connector_attach_encoder(connector, encoder); } diff --git a/linux-core/radeon_encoders.c b/linux-core/radeon_encoders.c index 1b75bd6a..9a2d63ea 100644 --- a/linux-core/radeon_encoders.c +++ b/linux-core/radeon_encoders.c @@ -30,9 +30,9 @@ extern int atom_debug; -static void radeon_rmx_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +void radeon_rmx_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); if (mode->hdisplay < radeon_encoder->panel_xres || @@ -319,7 +319,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_lvtma_helper_funcs = { .commit = radeon_lvtma_commit, }; -static void radeon_enc_destroy(struct drm_encoder *encoder) +void radeon_enc_destroy(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); drm_encoder_cleanup(encoder); @@ -895,68 +895,3 @@ struct drm_encoder *radeon_encoder_atom_tmds_add(struct drm_device *dev, int bio return encoder; } -static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; -} - -static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder) -{ - radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF); -} - -static void radeon_legacy_lvds_commit(struct drm_encoder *encoder) -{ - radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON); -} - -static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - - -} - -static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { - .dpms = radeon_legacy_lvds_dpms, - .mode_fixup = radeon_lvtma_mode_fixup, - .prepare = radeon_legacy_lvds_prepare, - .mode_set = radeon_legacy_lvds_mode_set, - .commit = radeon_legacy_lvds_commit, -}; - - -static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = { - .destroy = radeon_enc_destroy, -}; - -struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_mode_info *mode_info = &dev_priv->mode_info; - struct radeon_encoder *radeon_encoder; - struct drm_encoder *encoder; - radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); - if (!radeon_encoder) { - return NULL; - } - - encoder = &radeon_encoder->base; - - encoder->possible_crtcs = 0x3; - encoder->possible_clones = 0; - drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, - DRM_MODE_ENCODER_LVDS); - - drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); - - /* TODO get the LVDS info from the BIOS for panel size etc. */ - /* get the lvds info from the bios */ - radeon_combios_get_lvds_info(radeon_encoder); - - /* LVDS gets default RMX full scaling */ - radeon_encoder->rmx_type = RMX_FULL; - - return encoder; -} diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c new file mode 100644 index 00000000..eb005a07 --- /dev/null +++ b/linux-core/radeon_legacy_crtc.c @@ -0,0 +1,748 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ +#include "drmP.h" +#include "radeon_drm.h" +#include "radeon_drv.h" + +#include "drm_crtc_helper.h" + +void radeon_restore_common_regs(struct drm_device *dev, struct radeon_legacy_state *state) +{ + /* don't need this yet */ +} + +void radeon_restore_crtc_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + RADEON_WRITE(RADEON_CRTC_GEN_CNTL, state->crtc_gen_cntl | + RADEON_CRTC_DISP_REQ_EN_B); + + RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, state->crtc_ext_cntl, + RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_DISPLAY_DIS); + + RADEON_WRITE(RADEON_CRTC_H_TOTAL_DISP, state->crtc_h_total_disp); + RADEON_WRITE(RADEON_CRTC_H_SYNC_STRT_WID, state->crtc_h_sync_strt_wid); + RADEON_WRITE(RADEON_CRTC_V_TOTAL_DISP, state->crtc_v_total_disp); + RADEON_WRITE(RADEON_CRTC_V_SYNC_STRT_WID, state->crtc_v_sync_strt_wid); + + if (radeon_is_r300(dev_priv)) + RADEON_WRITE(R300_CRTC_TILE_X0_Y0, state->crtc_tile_x0_y0); + + RADEON_WRITE(RADEON_CRTC_OFFSET_CNTL, state->crtc_offset_cntl); + RADEON_WRITE(RADEON_CRTC_OFFSET, state->crtc_offset); + + RADEON_WRITE(RADEON_CRTC_PITCH, state->crtc_pitch); + RADEON_WRITE(RADEON_DISP_MERGE_CNTL, state->disp_merge_cntl); + + /* if dell server */ + if (0) + { + RADEON_WRITE(RADEON_TV_DAC_CNTL, state->tv_dac_cntl); + RADEON_WRITE(RADEON_DISP_HW_DEBUG, state->disp_hw_debug); + RADEON_WRITE(RADEON_DAC_CNTL2, state->dac2_cntl); + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, state->crtc2_gen_cntl); + } + + RADEON_WRITE(RADEON_CRTC_GEN_CNTL, state->crtc_gen_cntl); +} + +void radeon_restore_crtc2_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + /* We prevent the CRTC from hitting th + e memory controller until + * fully programmed + */ + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, + state->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_DISP_REQ_EN_B); + + RADEON_WRITE(RADEON_CRTC2_H_TOTAL_DISP, state->crtc2_h_total_disp); + RADEON_WRITE(RADEON_CRTC2_H_SYNC_STRT_WID, state->crtc2_h_sync_strt_wid); + RADEON_WRITE(RADEON_CRTC2_V_TOTAL_DISP, state->crtc2_v_total_disp); + RADEON_WRITE(RADEON_CRTC2_V_SYNC_STRT_WID, state->crtc2_v_sync_strt_wid); + + RADEON_WRITE(RADEON_FP_H2_SYNC_STRT_WID, state->fp_h2_sync_strt_wid); + RADEON_WRITE(RADEON_FP_V2_SYNC_STRT_WID, state->fp_v2_sync_strt_wid); + + if (radeon_is_r300(dev_priv)) + RADEON_WRITE(R300_CRTC2_TILE_X0_Y0, state->crtc2_tile_x0_y0); + RADEON_WRITE(RADEON_CRTC2_OFFSET_CNTL, state->crtc2_offset_cntl); + RADEON_WRITE(RADEON_CRTC2_OFFSET, state->crtc2_offset); + + RADEON_WRITE(RADEON_CRTC2_PITCH, state->crtc2_pitch); + RADEON_WRITE(RADEON_DISP2_MERGE_CNTL, state->disp2_merge_cntl); + + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, state->crtc2_gen_cntl); +} + +static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + int i = 0; + + /* FIXME: Certain revisions of R300 can't recover here. Not sure of + the cause yet, but this workaround will mask the problem for now. + Other chips usually will pass at the very first test, so the + workaround shouldn't have any effect on them. */ + for (i = 0; + (i < 10000 && + RADEON_READ_PLL(dev_priv, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); + i++); +} + +static void radeon_pll_write_update(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + while (RADEON_READ_PLL(dev_priv, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, + RADEON_PPLL_ATOMIC_UPDATE_W, + ~(RADEON_PPLL_ATOMIC_UPDATE_W)); +} + +static void radeon_pll2_wait_for_read_update_complete(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + int i = 0; + + + /* FIXME: Certain revisions of R300 can't recover here. Not sure of + the cause yet, but this workaround will mask the problem for now. + Other chips usually will pass at the very first test, so the + workaround shouldn't have any effect on them. */ + for (i = 0; + (i < 10000 && + RADEON_READ_PLL(dev_priv, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); + i++); +} + +static void radeon_pll2_write_update(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + while (RADEON_READ_PLL(dev_priv, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_REF_DIV, + RADEON_P2PLL_ATOMIC_UPDATE_W, + ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); +} + +static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div, + uint16_t fb_div) +{ + unsigned int vcoFreq; + + if (!ref_div) + return 1; + + vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div; + + /* + * This is horribly crude: the VCO frequency range is divided into + * 3 parts, each part having a fixed PLL gain value. + */ + if (vcoFreq >= 30000) + /* + * [300..max] MHz : 7 + */ + return 7; + else if (vcoFreq >= 18000) + /* + * [180..300) MHz : 4 + */ + return 4; + else + /* + * [0..180) MHz : 1 + */ + return 1; +} + +void radeon_restore_pll_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + uint8_t pll_gain; + + pll_gain = radeon_compute_pll_gain(dev_priv->mode_info.pll.reference_freq, + state->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + state->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK); + + if (dev_priv->flags & RADEON_IS_MOBILITY) { + /* A temporal workaround for the occational blanking on certain laptop panels. + This appears to related to the PLL divider registers (fail to lock?). + It occurs even when all dividers are the same with their old settings. + In this case we really don't need to fiddle with PLL registers. + By doing this we can avoid the blanking problem with some panels. + */ + if ((state->ppll_ref_div == (RADEON_READ_PLL(dev_priv, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && + (state->ppll_div_3 == (RADEON_READ_PLL(dev_priv, RADEON_PPLL_DIV_3) & + (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { + RADEON_WRITE_P(RADEON_CLOCK_CNTL_INDEX, + RADEON_PLL_DIV_SEL, + ~(RADEON_PLL_DIV_SEL)); + radeon_pll_errata_after_index(dev_priv); + return; + } + } + + RADEON_WRITE_PLL_P(dev_priv, RADEON_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_CPUCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); + + RADEON_WRITE_PLL_P(dev_priv, + RADEON_PPLL_CNTL, + RADEON_PPLL_RESET + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT), + ~(RADEON_PPLL_RESET + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | RADEON_PPLL_PVG_MASK)); + + RADEON_WRITE_P(RADEON_CLOCK_CNTL_INDEX, + RADEON_PLL_DIV_SEL, + ~(RADEON_PLL_DIV_SEL)); + radeon_pll_errata_after_index(dev_priv); + + if (radeon_is_r300(dev_priv) || + (dev_priv->chip_family == CHIP_RS300) || + (dev_priv->chip_family == CHIP_RS400) || + (dev_priv->chip_family == CHIP_RS480)) { + if (state->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { + /* When restoring console mode, use saved PPLL_REF_DIV + * setting. + */ + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, + state->ppll_ref_div, + 0); + } else { + /* R300 uses ref_div_acc field as real ref divider */ + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, + (state->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), + ~R300_PPLL_REF_DIV_ACC_MASK); + } + } else { + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, + state->ppll_ref_div, + ~RADEON_PPLL_REF_DIV_MASK); + } + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_DIV_3, + state->ppll_div_3, + ~RADEON_PPLL_FB3_DIV_MASK); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_DIV_3, + state->ppll_div_3, + ~RADEON_PPLL_POST3_DIV_MASK); + + radeon_pll_write_update(dev); + radeon_pll_wait_for_read_update_complete(dev); + + RADEON_WRITE_PLL(dev_priv, RADEON_HTOTAL_CNTL, state->htotal_cntl); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_CNTL, + 0, + ~(RADEON_PPLL_RESET + | RADEON_PPLL_SLEEP + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); + + DRM_DEBUG("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + state->ppll_ref_div, + state->ppll_div_3, + (unsigned)state->htotal_cntl, + RADEON_READ_PLL(dev_priv, RADEON_PPLL_CNTL)); + DRM_DEBUG("Wrote: rd=%d, fd=%d, pd=%d\n", + state->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + state->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, + (state->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); + + mdelay(50); /* Let the clock to lock */ + + RADEON_WRITE_PLL_P(dev_priv, RADEON_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_PPLLCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); + + /*RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, state->vclk_ecp_cntl);*/ + +} + +void radeon_restore_pll2_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + uint8_t pll_gain; + + pll_gain = radeon_compute_pll_gain(dev_priv->mode_info.pll.reference_freq, + state->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + state->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK); + + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + RADEON_WRITE_PLL_P(dev_priv, + RADEON_P2PLL_CNTL, + RADEON_P2PLL_RESET + | RADEON_P2PLL_ATOMIC_UPDATE_EN + | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT), + ~(RADEON_P2PLL_RESET + | RADEON_P2PLL_ATOMIC_UPDATE_EN + | RADEON_P2PLL_PVG_MASK)); + + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_REF_DIV, + state->p2pll_ref_div, + ~RADEON_P2PLL_REF_DIV_MASK); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_DIV_0, + state->p2pll_div_0, + ~RADEON_P2PLL_FB0_DIV_MASK); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_DIV_0, + state->p2pll_div_0, + ~RADEON_P2PLL_POST0_DIV_MASK); + + radeon_pll2_write_update(dev); + radeon_pll2_wait_for_read_update_complete(dev); + + RADEON_WRITE_PLL(dev_priv, RADEON_HTOTAL2_CNTL, state->htotal_cntl2); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_CNTL, + 0, + ~(RADEON_P2PLL_RESET + | RADEON_P2PLL_SLEEP + | RADEON_P2PLL_ATOMIC_UPDATE_EN)); + + DRM_DEBUG("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + (unsigned)state->p2pll_ref_div, + (unsigned)state->p2pll_div_0, + (unsigned)state->htotal_cntl2, + RADEON_READ_PLL(dev_priv, RADEON_P2PLL_CNTL)); + DRM_DEBUG("Wrote2: rd=%u, fd=%u, pd=%u\n", + (unsigned)state->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + (unsigned)state->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, + (unsigned)((state->p2pll_div_0 & + RADEON_P2PLL_POST0_DIV_MASK) >>16)); + + mdelay(50); /* Let the clock to lock */ + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, state->pixclks_cntl); + + +} + + +void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + + uint32_t mask; + + mask = radeon_crtc->crtc_id ? + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS); + + switch(mode) { + case DRM_MODE_DPMS_ON: + if (radeon_crtc->crtc_id) { + RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, 0, ~mask); + } else { + RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); + } + break; + case DRM_MODE_DPMS_STANDBY: + if (radeon_crtc->crtc_id) { + RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask); + } else { + RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask); + } + break; + case DRM_MODE_DPMS_SUSPEND: + if (radeon_crtc->crtc_id) { + RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask); + } else { + RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask); + } + break; + case DRM_MODE_DPMS_OFF: + if (radeon_crtc->crtc_id) { + RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask); + } else { + RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B); + RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); + } + break; + } + + if (mode != DRM_MODE_DPMS_OFF) { + radeon_crtc_load_lut(crtc); + } +} + +static bool radeon_init_crtc_base(struct drm_crtc *crtc, struct radeon_legacy_state *state, int x, int y) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_framebuffer *radeon_fb; + struct drm_radeon_gem_object *obj_priv; + uint32_t base; + + radeon_fb = to_radeon_framebuffer(crtc->fb); + + obj_priv = radeon_fb->obj->driver_private; + + state->crtc_offset = obj_priv->bo->offset + dev_priv->fb_location; + + state->crtc_offset_cntl = 0; + + /* TODO tiling */ + if (0) { + if (radeon_is_r300(dev_priv)) { + state->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + } else { + state->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; + } + } else { + if (radeon_is_r300(dev_priv)) { + state->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + } else { + state->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + } + + base = obj_priv->bo->offset; + + /* TODO more tiling */ + if (0) { + if (radeon_is_r300(dev_priv)) { + state->crtc_tile_x0_y0 = x | (y << 16); + base &= ~0x7ff; + } else { + int byteshift = crtc->fb->bits_per_pixel >> 4; + int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; + base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + state->crtc_offset_cntl |= (y % 16); + } + } else { + int offset = y * crtc->fb->pitch + x; + switch (crtc->fb->bits_per_pixel) { + } + base += offset; + } + + base &= ~7; + + /* update sarea TODO */ + + state->crtc_offset = base; + return true; +} + +static bool radeon_init_crtc_registers(struct drm_crtc *crtc, struct radeon_legacy_state *state, + struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + switch (crtc->fb->depth) { + + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + return false; + } + + state->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + | RADEON_CRTC_EN + | (format << 8) + | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_CSYNC) + ? RADEON_CRTC_CSYNC_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); + + state->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); + + state->disp_merge_cntl = RADEON_READ(RADEON_DISP_MERGE_CNTL); + state->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + + state->crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) + << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) hsync_wid = 1; + hsync_start = mode->crtc_hsync_start - 8; + + state->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + state->crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) vsync_wid = 1; + + state->crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + state->crtc_pitch = (((crtc->fb->pitch * crtc->fb->bits_per_pixel) + + ((crtc->fb->bits_per_pixel * 8) -1)) / + (crtc->fb->bits_per_pixel * 8)); + state->crtc_pitch |= state->crtc_pitch << 16; + + /* TODO -> Dell Server */ + if (0) { +// state->dac2_cntl = info->StatedReg->dac2_cntl; +// state->tv_dac_cntl = info->StatedReg->tv_dac_cntl; +// state->crtc2_gen_cntl = info->StatedReg->crtc2_gen_cntl; +// state->disp_hw_debug = info->StatedReg->disp_hw_debug; + +// state->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; +// state->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + + /* For CRT on DAC2, don't turn it on if BIOS didn't + enable it, even it's detected. + */ + state->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + state->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); + state->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); + } + + return true; +} + +static void radeon_init_pll_registers(struct drm_crtc *crtc, struct radeon_legacy_state *state, + struct drm_display_mode *mode, int flags) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t feedback_div = 0; + uint32_t reference_div = 0; + uint32_t post_divider = 0; + uint32_t freq = 0; + struct radeon_pll *pll = &dev_priv->mode_info.pll; + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 16, 5 }, /* VCLK_SRC/16 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + +#if 0 // TODO + if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { + state->ppll_ref_div = info->RefDivider; + state->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); + state->htotal_cntl = 0; + return; + } +#endif + + DRM_DEBUG("\n"); + radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags); + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + if (post_div->divider == post_divider) + break; + } + + if (!post_div->divider) { + state->pll_output_freq = freq; + post_div = &post_divs[0]; + } + + state->dot_clock_freq = freq; + state->feedback_div = feedback_div; + state->reference_div = reference_div; + state->post_div = post_divider; + + DRM_DEBUG("dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)state->dot_clock_freq, + (unsigned)state->pll_output_freq, + state->feedback_div, + state->reference_div, + state->post_div); + + state->ppll_ref_div = state->reference_div; + +#if defined(__powerpc__) && (0) /* TODO */ + /* apparently programming this otherwise causes a hang??? */ + if (info->MacModel == RADEON_MAC_IBOOK) + state->ppll_div_3 = 0x000600ad; + else +#endif + state->ppll_div_3 = (state->feedback_div | (post_div->bitvalue << 16)); + + state->htotal_cntl = mode->htotal & 0x7; + + state->vclk_ecp_cntl = (RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL) & + ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; + +} + +static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void radeon_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder; + int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; + int i; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + if (encoder->crtc == crtc) { + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) + pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) + pll_flags |= RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV; + } + } + + switch(radeon_crtc->crtc_id) { + case 0: + radeon_init_crtc_registers(crtc, &dev_priv->mode_info.legacy_state, adjusted_mode); + radeon_init_crtc_base(crtc, &dev_priv->mode_info.legacy_state, crtc->x, crtc->y); +// dot_clock = adjusted_mode->clock / 1000; + + // if (dot_clock) + radeon_init_pll_registers(crtc, &dev_priv->mode_info.legacy_state, adjusted_mode, + pll_flags); + break; + case 1: + break; + + } + + /* TODO TV */ + + switch (radeon_crtc->crtc_id) { + case 0: + radeon_restore_crtc_registers(dev, &dev_priv->mode_info.legacy_state); + radeon_restore_pll_registers(dev, &dev_priv->mode_info.legacy_state); + break; + case 1: + radeon_restore_crtc2_registers(dev, &dev_priv->mode_info.legacy_state); + radeon_restore_pll2_registers(dev, &dev_priv->mode_info.legacy_state); + break; + } + +} + +void radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y) +{ +} + +static void radeon_crtc_prepare(struct drm_crtc *crtc) +{ +} + +static void radeon_crtc_commit(struct drm_crtc *crtc) +{ +} + +static const struct drm_crtc_helper_funcs legacy_helper_funcs = { + .dpms = radeon_crtc_dpms, + .mode_fixup = radeon_crtc_mode_fixup, + .mode_set = radeon_crtc_mode_set, + .mode_set_base = radeon_crtc_set_base, + .prepare = radeon_crtc_prepare, + .commit = radeon_crtc_commit, +}; + + +void radeon_legacy_init_crtc(struct drm_device *dev, + struct radeon_crtc *radeon_crtc) +{ + drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs); +} diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c new file mode 100644 index 00000000..8846653d --- /dev/null +++ b/linux-core/radeon_legacy_encoders.c @@ -0,0 +1,391 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ +#include "drmP.h" +#include "drm_crtc_helper.h" +#include "radeon_drm.h" +#include "radeon_drv.h" + + +void radeon_restore_dac_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + if (radeon_is_r300(dev_priv)) + RADEON_WRITE_P(RADEON_GPIOPAD_A, state->gpiopad_a, ~1); + + RADEON_WRITE_P(RADEON_DAC_CNTL, + state->dac_cntl, + RADEON_DAC_RANGE_CNTL | + RADEON_DAC_BLANKING); + + RADEON_WRITE(RADEON_DAC_CNTL2, state->dac2_cntl); + + if ((dev_priv->chip_family != CHIP_R100) && + (dev_priv->chip_family != CHIP_R200)) + RADEON_WRITE (RADEON_TV_DAC_CNTL, state->tv_dac_cntl); + + RADEON_WRITE(RADEON_DISP_OUTPUT_CNTL, state->disp_output_cntl); + + if ((dev_priv->chip_family == CHIP_R200) || + radeon_is_r300(dev_priv)) { + RADEON_WRITE(RADEON_DISP_TV_OUT_CNTL, state->disp_tv_out_cntl); + } else { + RADEON_WRITE(RADEON_DISP_HW_DEBUG, state->disp_hw_debug); + } + + RADEON_WRITE(RADEON_DAC_MACRO_CNTL, state->dac_macro_cntl); + + /* R200 DAC connected via DVO */ + if (dev_priv->chip_family == CHIP_R200) + RADEON_WRITE(RADEON_FP2_GEN_CNTL, state->fp2_gen_cntl); +} + + +/* Write TMDS registers */ +void radeon_restore_fp_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + RADEON_WRITE(RADEON_TMDS_PLL_CNTL, state->tmds_pll_cntl); + RADEON_WRITE(RADEON_TMDS_TRANSMITTER_CNTL,state->tmds_transmitter_cntl); + RADEON_WRITE(RADEON_FP_GEN_CNTL, state->fp_gen_cntl); + + if ((dev_priv->chip_family == CHIP_RS400) || + (dev_priv->chip_family == CHIP_RS480)) { + RADEON_WRITE(RS400_FP_2ND_GEN_CNTL, state->fp_2nd_gen_cntl); + /*RADEON_WRITE(RS400_TMDS2_CNTL, state->tmds2_cntl);*/ + RADEON_WRITE(RS400_TMDS2_TRANSMITTER_CNTL, state->tmds2_transmitter_cntl); + } + + /* old AIW Radeon has some BIOS initialization problem + * with display buffer underflow, only occurs to DFP + */ + if (dev_priv->flags & RADEON_SINGLE_CRTC) + RADEON_WRITE(RADEON_GRPH_BUFFER_CNTL, + RADEON_READ(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); + +} + +/* Write FP2 registers */ +void radeon_restore_fp2_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + RADEON_WRITE(RADEON_FP2_GEN_CNTL, state->fp2_gen_cntl); + + if ((dev_priv->chip_family == CHIP_RS400) || + (dev_priv->chip_family == CHIP_RS480)) + RADEON_WRITE(RS400_FP2_2_GEN_CNTL, state->fp2_2_gen_cntl); +} + +/* Write RMX registers */ +void radeon_state_rmx_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + RADEON_WRITE(RADEON_FP_HORZ_STRETCH, state->fp_horz_stretch); + RADEON_WRITE(RADEON_FP_VERT_STRETCH, state->fp_vert_stretch); + RADEON_WRITE(RADEON_CRTC_MORE_CNTL, state->crtc_more_cntl); + RADEON_WRITE(RADEON_FP_HORZ_VERT_ACTIVE, state->fp_horz_vert_active); + RADEON_WRITE(RADEON_FP_H_SYNC_STRT_WID, state->fp_h_sync_strt_wid); + RADEON_WRITE(RADEON_FP_V_SYNC_STRT_WID, state->fp_v_sync_strt_wid); + RADEON_WRITE(RADEON_FP_CRTC_H_TOTAL_DISP, state->fp_crtc_h_total_disp); + RADEON_WRITE(RADEON_FP_CRTC_V_TOTAL_DISP, state->fp_crtc_v_total_disp); + +} + +/* Write LVDS registers */ +void radeon_restore_lvds_registers(struct drm_device *dev, struct radeon_legacy_state *state) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + if (dev_priv->flags & RADEON_IS_MOBILITY) { + RADEON_WRITE(RADEON_LVDS_GEN_CNTL, state->lvds_gen_cntl); + /*RADEON_WRITE(RADEON_LVDS_PLL_CNTL, state->lvds_pll_cntl);*/ + + if (dev_priv->chip_family == CHIP_RV410) { + RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, 0); + } + } + +} + +static void radeon_init_fp_registers(struct drm_encoder *encoder, struct drm_display_mode *mode, + bool is_primary) +{ + + +} + +static void radeon_init_dac_registers(struct drm_encoder *encoder, struct radeon_legacy_state *state, + struct drm_display_mode *mode, bool is_primary) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + + if (is_primary) { + if (dev_priv->chip_family == CHIP_R200 || radeon_is_r300(dev_priv)) { + state->disp_output_cntl = RADEON_READ(RADEON_DISP_OUTPUT_CNTL & + ~RADEON_DISP_DAC_SOURCE_MASK); + } else { + state->dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2) & ~(RADEON_DAC2_DAC_CLK_SEL); + } + } else { + if (dev_priv->chip_family == CHIP_R200 || radeon_is_r300(dev_priv)) { + state->disp_output_cntl = RADEON_READ(RADEON_DISP_OUTPUT_CNTL & + ~RADEON_DISP_DAC_SOURCE_MASK); + state->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + } else { + state->dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL; + } + } + + state->dac_cntl = (RADEON_DAC_MASK_ALL | + RADEON_DAC_VGA_ADR_EN | + /* TODO 6-bits */ + RADEON_DAC_8BIT_EN); + state->dac_macro_cntl = RADEON_READ(RADEON_DAC_MACRO_CNTL); +} + +static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; +} + +static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder) +{ + radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_lvds_commit(struct drm_encoder *encoder) +{ + radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + + +} + +static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + radeon_encoder->flags &= ~RADEON_USE_RMX; + + if (radeon_encoder->rmx_type != RMX_OFF) + radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); + + return true; +} + +static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { + .dpms = radeon_legacy_lvds_dpms, + .mode_fixup = radeon_legacy_lvds_mode_fixup, + .prepare = radeon_legacy_lvds_prepare, + .mode_set = radeon_legacy_lvds_mode_set, + .commit = radeon_legacy_lvds_commit, +}; + + +static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + + +struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_mode_info *mode_info = &dev_priv->mode_info; + struct radeon_encoder *radeon_encoder; + struct drm_encoder *encoder; + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); + if (!radeon_encoder) { + return NULL; + } + + encoder = &radeon_encoder->base; + + encoder->possible_crtcs = 0x3; + encoder->possible_clones = 0; + drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, + DRM_MODE_ENCODER_LVDS); + + drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); + + /* TODO get the LVDS info from the BIOS for panel size etc. */ + /* get the lvds info from the bios */ + radeon_combios_get_lvds_info(radeon_encoder); + + /* LVDS gets default RMX full scaling */ + radeon_encoder->rmx_type = RMX_FULL; + + return encoder; +} + +static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode) +{ + + +} + +static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder) +{ + radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder) +{ + radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + radeon_init_dac_registers(encoder, &dev_priv->mode_info.legacy_state, adjusted_mode, + (radeon_crtc->crtc_id == 1)); + + radeon_restore_dac_registers(dev, &dev_priv->mode_info.legacy_state); +} + +static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = { + .dpms = radeon_legacy_primary_dac_dpms, + .mode_fixup = radeon_legacy_primary_dac_mode_fixup, + .prepare = radeon_legacy_primary_dac_prepare, + .mode_set = radeon_legacy_primary_dac_mode_set, + .commit = radeon_legacy_primary_dac_commit, +}; + + +static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + +struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int has_tv) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_mode_info *mode_info = &dev_priv->mode_info; + struct radeon_encoder *radeon_encoder; + struct drm_encoder *encoder; + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); + if (!radeon_encoder) { + return NULL; + } + + encoder = &radeon_encoder->base; + + encoder->possible_crtcs = 0x3; + encoder->possible_clones = 0; + drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, + DRM_MODE_ENCODER_DAC); + + drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs); + + return encoder; +} + + +static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + +} + +static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode) +{ + /* dfp1 */ + +} + +static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder) +{ + radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder) +{ + radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + + +} + +static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = { + .dpms = radeon_legacy_tmds_int_dpms, + .mode_fixup = radeon_legacy_tmds_int_mode_fixup, + .prepare = radeon_legacy_tmds_int_prepare, + .mode_set = radeon_legacy_tmds_int_mode_set, + .commit = radeon_legacy_tmds_int_commit, +}; + + +static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + +struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_mode_info *mode_info = &dev_priv->mode_info; + struct radeon_encoder *radeon_encoder; + struct drm_encoder *encoder; + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); + if (!radeon_encoder) { + return NULL; + } + + encoder = &radeon_encoder->base; + + encoder->possible_crtcs = 0x3; + encoder->possible_clones = 0; + drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, + DRM_MODE_ENCODER_TMDS); + + drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs); + + radeon_combios_get_tmds_info(radeon_encoder); + return encoder; +} diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h index f75e8272..91c6f48d 100644 --- a/linux-core/radeon_mode.h +++ b/linux-core/radeon_mode.h @@ -115,6 +115,11 @@ struct radeon_bios_connector { int igp_lane_info; }; +struct radeon_tmds_pll { + uint32_t freq; + uint32_t value; +}; + #define RADEON_MAX_BIOS_CONNECTOR 16 #define RADEON_PLL_USE_BIOS_DIVS (1 << 0) @@ -124,27 +129,177 @@ struct radeon_bios_connector { #define RADEON_PLL_PREFER_LOW_REF_DIV (1 << 4) struct radeon_pll { - uint16_t reference_freq; - uint16_t reference_div; - uint32_t pll_in_min; - uint32_t pll_in_max; - uint32_t pll_out_min; - uint32_t pll_out_max; - uint16_t xclk; + uint16_t reference_freq; + uint16_t reference_div; + uint32_t pll_in_min; + uint32_t pll_in_max; + uint32_t pll_out_min; + uint32_t pll_out_max; + uint16_t xclk; + + uint32_t min_ref_div; + uint32_t max_ref_div; + uint32_t min_post_div; + uint32_t max_post_div; + uint32_t min_feedback_div; + uint32_t max_feedback_div; + uint32_t best_vco; +}; + +#define MAX_H_CODE_TIMING_LEN 32 +#define MAX_V_CODE_TIMING_LEN 32 + +struct radeon_legacy_state { + + uint32_t bus_cntl; + + /* DAC */ + uint32_t dac_cntl; + uint32_t dac2_cntl; + uint32_t dac_macro_cntl; + + /* CRTC 1 */ + uint32_t crtc_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t crtc_h_total_disp; + uint32_t crtc_h_sync_strt_wid; + uint32_t crtc_v_total_disp; + uint32_t crtc_v_sync_strt_wid; + uint32_t crtc_offset; + uint32_t crtc_offset_cntl; + uint32_t crtc_pitch; + uint32_t disp_merge_cntl; + uint32_t grph_buffer_cntl; + uint32_t crtc_more_cntl; + uint32_t crtc_tile_x0_y0; + + /* CRTC 2 */ + uint32_t crtc2_gen_cntl; + uint32_t crtc2_h_total_disp; + uint32_t crtc2_h_sync_strt_wid; + uint32_t crtc2_v_total_disp; + uint32_t crtc2_v_sync_strt_wid; + uint32_t crtc2_offset; + uint32_t crtc2_offset_cntl; + uint32_t crtc2_pitch; + uint32_t crtc2_tile_x0_y0; + + uint32_t disp_output_cntl; + uint32_t disp_tv_out_cntl; + uint32_t disp_hw_debug; + uint32_t disp2_merge_cntl; + uint32_t grph2_buffer_cntl; + + /* FP regs */ + uint32_t fp_crtc_h_total_disp; + uint32_t fp_crtc_v_total_disp; + uint32_t fp_gen_cntl; + uint32_t fp2_gen_cntl; + uint32_t fp_h_sync_strt_wid; + uint32_t fp_h2_sync_strt_wid; + uint32_t fp_horz_stretch; + uint32_t fp_horz_vert_active; + uint32_t fp_panel_cntl; + uint32_t fp_v_sync_strt_wid; + uint32_t fp_v2_sync_strt_wid; + uint32_t fp_vert_stretch; + uint32_t lvds_gen_cntl; + uint32_t lvds_pll_cntl; + uint32_t tmds_pll_cntl; + uint32_t tmds_transmitter_cntl; + + /* Computed values for PLL */ + uint32_t dot_clock_freq; + uint32_t pll_output_freq; + int feedback_div; + int reference_div; + int post_div; + + /* PLL registers */ + uint32_t ppll_ref_div; + uint32_t ppll_div_3; + uint32_t htotal_cntl; + uint32_t vclk_ecp_cntl; + + /* Computed values for PLL2 */ + uint32_t dot_clock_freq_2; + uint32_t pll_output_freq_2; + int feedback_div_2; + int reference_div_2; + int post_div_2; + + /* PLL2 registers */ + uint32_t p2pll_ref_div; + uint32_t p2pll_div_0; + uint32_t htotal_cntl2; + uint32_t pixclks_cntl; + + bool palette_valid; + uint32_t palette[256]; + uint32_t palette2[256]; + + uint32_t disp2_req_cntl1; + uint32_t disp2_req_cntl2; + uint32_t dmif_mem_cntl1; + uint32_t disp1_req_cntl1; + + uint32_t fp_2nd_gen_cntl; + uint32_t fp2_2_gen_cntl; + uint32_t tmds2_cntl; + uint32_t tmds2_transmitter_cntl; + + /* TV out registers */ + uint32_t tv_master_cntl; + uint32_t tv_htotal; + uint32_t tv_hsize; + uint32_t tv_hdisp; + uint32_t tv_hstart; + uint32_t tv_vtotal; + uint32_t tv_vdisp; + uint32_t tv_timing_cntl; + uint32_t tv_vscaler_cntl1; + uint32_t tv_vscaler_cntl2; + uint32_t tv_sync_size; + uint32_t tv_vrestart; + uint32_t tv_hrestart; + uint32_t tv_frestart; + uint32_t tv_ftotal; + uint32_t tv_clock_sel_cntl; + uint32_t tv_clkout_cntl; + uint32_t tv_data_delay_a; + uint32_t tv_data_delay_b; + uint32_t tv_dac_cntl; + uint32_t tv_pll_cntl; + uint32_t tv_pll_cntl1; + uint32_t tv_pll_fine_cntl; + uint32_t tv_modulator_cntl1; + uint32_t tv_modulator_cntl2; + uint32_t tv_frame_lock_cntl; + uint32_t tv_pre_dac_mux_cntl; + uint32_t tv_rgb_cntl; + uint32_t tv_y_saw_tooth_cntl; + uint32_t tv_y_rise_cntl; + uint32_t tv_y_fall_cntl; + uint32_t tv_uv_adr; + uint32_t tv_upsamp_and_gain_cntl; + uint32_t tv_gain_limit_settings; + uint32_t tv_linear_gain_settings; + uint32_t tv_crc_cntl; + uint32_t tv_sync_cntl; + uint32_t gpiopad_a; + uint32_t pll_test_cntl; + + uint16_t h_code_timing[MAX_H_CODE_TIMING_LEN]; + uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN]; + - uint32_t min_ref_div; - uint32_t max_ref_div; - uint32_t min_post_div; - uint32_t max_post_div; - uint32_t min_feedback_div; - uint32_t max_feedback_div; - uint32_t best_vco; }; struct radeon_mode_info { struct atom_context *atom_context; struct radeon_bios_connector bios_connector[RADEON_MAX_BIOS_CONNECTOR]; struct radeon_pll pll; + struct radeon_legacy_state legacy_state; }; struct radeon_crtc { @@ -185,6 +340,7 @@ struct radeon_encoder { uint32_t vblank; uint32_t panel_pwr_delay; uint32_t dotclock; + struct radeon_tmds_pll tmds_pll[4]; }; struct radeon_connector { @@ -221,6 +377,8 @@ struct drm_encoder *radeon_encoder_lvtma_add(struct drm_device *dev, int bios_in struct drm_encoder *radeon_encoder_atom_dac_add(struct drm_device *dev, int bios_index, int dac_id, int with_tv); struct drm_encoder *radeon_encoder_atom_tmds_add(struct drm_device *dev, int bios_index, int tmds_type); struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); +struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv); +struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index); extern void radeon_crtc_load_lut(struct drm_crtc *crtc); extern void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y); @@ -233,6 +391,7 @@ extern bool radeon_atom_get_clock_info(struct drm_device *dev); extern bool radeon_combios_get_clock_info(struct drm_device *dev); extern void radeon_get_lvds_info(struct radeon_encoder *encoder); extern bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder); +extern bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder); extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno); struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev, @@ -245,6 +404,8 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev); void radeon_atombios_init_crtc(struct drm_device *dev, struct radeon_crtc *radeon_crtc); +void radeon_legacy_init_crtc(struct drm_device *dev, + struct radeon_crtc *radeon_crtc); void avivo_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state); void radeon_atom_static_pwrmgt_setup(struct drm_device *dev, int enable); @@ -252,4 +413,9 @@ void radeon_atom_dyn_clk_setup(struct drm_device *dev, int enable); void radeon_get_clock_info(struct drm_device *dev); extern bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device *dev); +void radeon_rmx_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); +void radeon_enc_destroy(struct drm_encoder *encoder); + #endif diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 4c03f739..b751740c 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -2282,6 +2282,7 @@ static void radeon_set_dynamic_clock(struct drm_device *dev, int mode) int radeon_modeset_cp_init(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t tmp; /* allocate a ring and ring rptr bits from GART space */ /* these are allocated in GEM files */ @@ -2311,6 +2312,11 @@ int radeon_modeset_cp_init(struct drm_device *dev) radeon_cp_init_ring_buffer(dev, dev_priv); + /* need to enable BUS mastering in Buscntl */ + tmp = RADEON_READ(RADEON_BUS_CNTL); + tmp &= ~RADEON_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); + radeon_do_engine_reset(dev); radeon_test_writeback(dev_priv); @@ -2381,8 +2387,8 @@ int radeon_modeset_preinit(struct drm_device *dev) if (dev_priv->is_atom_bios) { dev_priv->mode_info.atom_context = atom_parse(&card, dev_priv->bios); - radeon_get_clock_info(dev); } + radeon_get_clock_info(dev); return 0; } diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 94975e4d..51a5b00c 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -1277,41 +1277,59 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, extern int RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr); extern void RADEON_WRITE_PLL(struct drm_radeon_private *dev_priv, int addr, uint32_t data); -#define RADEON_WRITE_PCIE( addr, val ) \ -do { \ - RADEON_WRITE8( RADEON_PCIE_INDEX, \ - ((addr) & 0xff)); \ - RADEON_WRITE( RADEON_PCIE_DATA, (val) ); \ +#define RADEON_WRITE_P(reg, val, mask) \ +do { \ + uint32_t tmp = RADEON_READ(reg); \ + tmp &= ~(mask); \ + tmp |= ((val) & ~(mask)); \ + RADEON_WRITE(reg, tmp); \ +} while(0) + +#define RADEON_WRITE_PLL_P(dev_priv, addr, val, mask) \ +do { \ + uint32_t tmp_ = RADEON_READ_PLL(dev_priv, addr); \ + tmp_ &= (mask); \ + tmp_ |= ((val) & ~(mask)); \ + RADEON_WRITE_PLL(dev_priv, addr, tmp_); \ } while (0) -#define R500_WRITE_MCIND( addr, val ) \ + + +#define RADEON_WRITE_PCIE(addr, val) \ +do { \ + RADEON_WRITE8(RADEON_PCIE_INDEX, \ + ((addr) & 0xff)); \ + RADEON_WRITE(RADEON_PCIE_DATA, (val)); \ +} while (0) + +#define R500_WRITE_MCIND(addr, val) \ do { \ RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff)); \ RADEON_WRITE(R520_MC_IND_DATA, (val)); \ RADEON_WRITE(R520_MC_IND_INDEX, 0); \ } while (0) -#define RS480_WRITE_MCIND( addr, val ) \ +#define RS480_WRITE_MCIND(addr, val) \ do { \ - RADEON_WRITE( RS480_NB_MC_INDEX, \ + RADEON_WRITE(RS480_NB_MC_INDEX, \ ((addr) & 0xff) | RS480_NB_MC_IND_WR_EN); \ - RADEON_WRITE( RS480_NB_MC_DATA, (val) ); \ - RADEON_WRITE( RS480_NB_MC_INDEX, 0xff ); \ + RADEON_WRITE(RS480_NB_MC_DATA, (val)); \ + RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); \ } while (0) -#define RS690_WRITE_MCIND( addr, val ) \ +#define RS690_WRITE_MCIND(addr, val) \ do { \ RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK)); \ RADEON_WRITE(RS690_MC_DATA, val); \ RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); \ } while (0) -#define IGP_WRITE_MCIND( addr, val ) \ +#define IGP_WRITE_MCIND(addr, val) \ do { \ - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) \ - RS690_WRITE_MCIND( addr, val ); \ - else \ - RS480_WRITE_MCIND( addr, val ); \ + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) \ + RS690_WRITE_MCIND(addr, val); \ + else \ + RS480_WRITE_MCIND(addr, val); \ } while (0) #define CP_PACKET0( reg, n ) \ @@ -1355,42 +1373,42 @@ do { \ #define RADEON_FLUSH_CACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB3D_DC_FLUSH ); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH); \ } else { \ - OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB3D_DC_FLUSH ); \ - } \ + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH); \ + } \ } while (0) #define RADEON_PURGE_CACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB3D_DC_FLUSH_ALL ); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ } else { \ - OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB3D_DC_FLUSH_ALL ); \ - } \ + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ + } \ } while (0) #define RADEON_FLUSH_ZCACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB3D_ZC_FLUSH ); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_ZC_FLUSH); \ } else { \ - OUT_RING( CP_PACKET0( R300_ZB_ZCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( R300_ZC_FLUSH ); \ - } \ + OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_ZC_FLUSH); \ + } \ } while (0) #define RADEON_PURGE_ZCACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL); \ } else { \ - OUT_RING( CP_PACKET0( R300_RB3D_ZCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( R300_ZC_FLUSH_ALL ); \ - } \ + OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_ZC_FLUSH_ALL); \ + } \ } while (0) /* ================================================================ @@ -1411,7 +1429,7 @@ do { \ #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ do { \ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; \ - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \ + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \ if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \ int __ret = radeon_do_cp_idle( dev_priv ); \ if ( __ret ) return __ret; \ @@ -1587,6 +1605,23 @@ static inline int radeon_update_breadcrumb(struct drm_device *dev) #define radeon_is_dce3(dev_priv) ((dev_priv->chip_family >= CHIP_RV620)) +#define radeon_is_rv100(dev_priv) ((dev_priv->chip_family == CHIP_RV100) || \ + (dev_priv->chip_family == CHIP_RV200) || \ + (dev_priv->chip_family == CHIP_RS100) || \ + (dev_priv->chip_family == CHIP_RS200) || \ + (dev_priv->chip_family == CHIP_RV250) || \ + (dev_priv->chip_family == CHIP_RV280) || \ + (dev_priv->chip_family == CHIP_RS300)) + +#define radeon_is_r300(dev_priv) ((dev_priv->chip_family == CHIP_R300) || \ + (dev_priv->chip_family == CHIP_RV350) || \ + (dev_priv->chip_family == CHIP_R350) || \ + (dev_priv->chip_family == CHIP_RV380) || \ + (dev_priv->chip_family == CHIP_R420) || \ + (dev_priv->chip_family == CHIP_RV410) || \ + (dev_priv->chip_family == CHIP_RS400) || \ + (dev_priv->chip_family == CHIP_RS480)) + #define radeon_bios8(dev_priv, v) (dev_priv->bios[v]) #define radeon_bios16(dev_priv, v) (dev_priv->bios[v] | (dev_priv->bios[(v) + 1] << 8)) #define radeon_bios32(dev_priv, v) ((dev_priv->bios[v]) | \ @@ -1594,6 +1629,7 @@ static inline int radeon_update_breadcrumb(struct drm_device *dev) (dev_priv->bios[(v) + 2] << 16) | \ (dev_priv->bios[(v) + 3] << 24)) +extern void radeon_pll_errata_after_index(struct drm_radeon_private *dev_priv); extern int radeon_emit_irq(struct drm_device * dev); extern void radeon_gem_free_object(struct drm_gem_object *obj); From 957c71ff52e93bb2c1bc01b99d29d763d0ef3899 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:10:11 +1000 Subject: [PATCH 28/49] radeon: FEDORA: add old DMA buffers on top of GEM This really shouldn't go upstream, it just lets me run the old 3D driver on GEM setup system --- linux-core/drm_bufs.c | 4 + linux-core/drm_dma.c | 2 + linux-core/drm_drv.c | 2 +- linux-core/drm_fops.c | 7 +- linux-core/drm_memory.c | 1 + linux-core/radeon_gem.c | 248 +++++++++++++++++++++++++++++++++++++++ shared-core/radeon_drv.h | 3 + 7 files changed, 263 insertions(+), 4 deletions(-) diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index e9052570..c966badc 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -1528,6 +1528,7 @@ int drm_mapbufs(struct drm_device *dev, void *data, dev->buf_use++; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); + DRM_DEBUG("dma buf count %d, req count %d\n", request->count, dma->buf_count); if (request->count >= dma->buf_count) { if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) || (drm_core_check_feature(dev, DRIVER_SG) @@ -1538,10 +1539,12 @@ int drm_mapbufs(struct drm_device *dev, void *data, unsigned long token = dev->agp_buffer_token; if (!map) { + DRM_DEBUG("No map\n"); retcode = -EINVAL; goto done; } down_write(¤t->mm->mmap_sem); + DRM_DEBUG("%x %d\n", token, map->size); virtual = do_mmap(file_priv->filp, 0, map->size, PROT_READ | PROT_WRITE, MAP_SHARED, @@ -1555,6 +1558,7 @@ int drm_mapbufs(struct drm_device *dev, void *data, up_write(¤t->mm->mmap_sem); } if (virtual > -1024UL) { + DRM_DEBUG("mmap failed\n"); /* Real error */ retcode = (signed long)virtual; goto done; diff --git a/linux-core/drm_dma.c b/linux-core/drm_dma.c index f7bff0ac..1e6aeefd 100644 --- a/linux-core/drm_dma.c +++ b/linux-core/drm_dma.c @@ -58,6 +58,7 @@ int drm_dma_setup(struct drm_device *dev) return 0; } +EXPORT_SYMBOL(drm_dma_setup); /** * Cleanup the DMA resources. @@ -120,6 +121,7 @@ void drm_dma_takedown(struct drm_device *dev) drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER); dev->dma = NULL; } +EXPORT_SYMBOL(drm_dma_takedown); /** * Free a buffer. diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 2a6bebd7..7c43fd00 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -250,7 +250,7 @@ int drm_lastclose(struct drm_device * dev) } dev->queue_count = 0; - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !drm_core_check_feature(dev, DRIVER_MODESET)) drm_dma_takedown(dev); dev->dev_mapping = NULL; diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index f45d5e46..7bc73d26 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -54,10 +54,11 @@ static int drm_setup(struct drm_device * dev) atomic_set(&dev->ioctl_count, 0); atomic_set(&dev->vma_count, 0); - dev->buf_use = 0; - atomic_set(&dev->buf_alloc, 0); - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) { + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !drm_core_check_feature(dev, DRIVER_MODESET)) { + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + i = drm_dma_setup(dev); if (i < 0) return i; diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c index 4b494f9c..a663e965 100644 --- a/linux-core/drm_memory.c +++ b/linux-core/drm_memory.c @@ -188,6 +188,7 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) } return pt; } +EXPORT_SYMBOL(drm_realloc); /** * Allocate pages. diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 1ee48514..250e6852 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -29,6 +29,8 @@ static int radeon_gem_ib_init(struct drm_device *dev); static int radeon_gem_ib_destroy(struct drm_device *dev); +static int radeon_gem_dma_bufs_init(struct drm_device *dev); +static void radeon_gem_dma_bufs_destroy(struct drm_device *dev); int radeon_gem_init_object(struct drm_gem_object *obj) { @@ -608,6 +610,7 @@ int radeon_alloc_gart_objects(struct drm_device *dev) /* init the indirect buffers */ radeon_gem_ib_init(dev); + radeon_gem_dma_bufs_init(dev); return 0; } @@ -650,6 +653,7 @@ void radeon_gem_mm_fini(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; + radeon_gem_dma_bufs_destroy(dev); radeon_gem_ib_destroy(dev); mutex_lock(&dev->struct_mutex); @@ -878,3 +882,247 @@ free_all: return -ENOMEM; } +#define RADEON_DMA_BUFFER_SIZE (64 * 1024) +#define RADEON_DMA_BUFFER_COUNT (16) + + +/** + * Cleanup after an error on one of the addbufs() functions. + * + * \param dev DRM device. + * \param entry buffer entry where the error occurred. + * + * Frees any pages and buffers associated with the given entry. + */ +static void drm_cleanup_buf_error(struct drm_device * dev, + struct drm_buf_entry * entry) +{ + int i; + + if (entry->seg_count) { + for (i = 0; i < entry->seg_count; i++) { + if (entry->seglist[i]) { + drm_pci_free(dev, entry->seglist[i]); + } + } + drm_free(entry->seglist, + entry->seg_count * + sizeof(*entry->seglist), DRM_MEM_SEGS); + + entry->seg_count = 0; + } + + if (entry->buf_count) { + for (i = 0; i < entry->buf_count; i++) { + if (entry->buflist[i].dev_private) { + drm_free(entry->buflist[i].dev_private, + entry->buflist[i].dev_priv_size, + DRM_MEM_BUFS); + } + } + drm_free(entry->buflist, + entry->buf_count * + sizeof(*entry->buflist), DRM_MEM_BUFS); + + entry->buf_count = 0; + } +} + +static int radeon_gem_addbufs(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_device_dma *dma = dev->dma; + struct drm_buf_entry *entry; + struct drm_buf *buf; + unsigned long offset; + unsigned long agp_offset; + int count; + int order; + int size; + int alignment; + int page_order; + int total; + int byte_count; + int i; + struct drm_buf **temp_buflist; + + if (!dma) + return -EINVAL; + + count = RADEON_DMA_BUFFER_COUNT; + order = drm_order(RADEON_DMA_BUFFER_SIZE); + size = 1 << order; + + alignment = PAGE_ALIGN(size); + page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; + total = PAGE_SIZE << page_order; + + byte_count = 0; + agp_offset = dev_priv->mm.dma_bufs.bo->offset; + + DRM_DEBUG("count: %d\n", count); + DRM_DEBUG("order: %d\n", order); + DRM_DEBUG("size: %d\n", size); + DRM_DEBUG("agp_offset: %lu\n", agp_offset); + DRM_DEBUG("alignment: %d\n", alignment); + DRM_DEBUG("page_order: %d\n", page_order); + DRM_DEBUG("total: %d\n", total); + + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) + return -EINVAL; + if (dev->queue_count) + return -EBUSY; /* Not while in use */ + + spin_lock(&dev->count_lock); + if (dev->buf_use) { + spin_unlock(&dev->count_lock); + return -EBUSY; + } + atomic_inc(&dev->buf_alloc); + spin_unlock(&dev->count_lock); + + mutex_lock(&dev->struct_mutex); + entry = &dma->bufs[order]; + if (entry->buf_count) { + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; /* May only call once for each order */ + } + + if (count < 0 || count > 4096) { + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -EINVAL; + } + + entry->buflist = drm_alloc(count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + if (!entry->buflist) { + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + memset(entry->buflist, 0, count * sizeof(*entry->buflist)); + + entry->buf_size = size; + entry->page_order = page_order; + + offset = 0; + + while (entry->buf_count < count) { + buf = &entry->buflist[entry->buf_count]; + buf->idx = dma->buf_count + entry->buf_count; + buf->total = alignment; + buf->order = order; + buf->used = 0; + + buf->offset = (dma->byte_count + offset); + buf->bus_address = dev_priv->gart_vm_start + agp_offset + offset; + buf->address = (void *)(agp_offset + offset); + buf->next = NULL; + buf->waiting = 0; + buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); + buf->file_priv = NULL; + + buf->dev_priv_size = dev->driver->dev_priv_size; + buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); + if (!buf->dev_private) { + /* Set count correctly so we free the proper amount. */ + entry->buf_count = count; + drm_cleanup_buf_error(dev, entry); + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + + memset(buf->dev_private, 0, buf->dev_priv_size); + + DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); + + offset += alignment; + entry->buf_count++; + byte_count += PAGE_SIZE << page_order; + } + + DRM_DEBUG("byte_count: %d\n", byte_count); + + temp_buflist = drm_realloc(dma->buflist, + dma->buf_count * sizeof(*dma->buflist), + (dma->buf_count + entry->buf_count) + * sizeof(*dma->buflist), DRM_MEM_BUFS); + if (!temp_buflist) { + /* Free the entry because it isn't valid */ + drm_cleanup_buf_error(dev, entry); + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + dma->buflist = temp_buflist; + + for (i = 0; i < entry->buf_count; i++) { + dma->buflist[i + dma->buf_count] = &entry->buflist[i]; + } + + dma->buf_count += entry->buf_count; + dma->seg_count += entry->seg_count; + dma->page_count += byte_count >> PAGE_SHIFT; + dma->byte_count += byte_count; + + DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); + DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); + + mutex_unlock(&dev->struct_mutex); + + dma->flags = _DRM_DMA_USE_SG; + atomic_dec(&dev->buf_alloc); + return 0; +} + +static int radeon_gem_dma_bufs_init(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + int size = RADEON_DMA_BUFFER_SIZE * RADEON_DMA_BUFFER_COUNT; + int ret; + + ret = drm_dma_setup(dev); + if (ret < 0) + return ret; + + ret = drm_buffer_object_create(dev, size, drm_bo_type_device, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_NO_EVICT | + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE, 0, + 0, 0, &dev_priv->mm.dma_bufs.bo); + if (ret) { + DRM_ERROR("Failed to create DMA bufs\n"); + return -ENOMEM; + } + + ret = drm_bo_kmap(dev_priv->mm.dma_bufs.bo, 0, size >> PAGE_SHIFT, + &dev_priv->mm.dma_bufs.kmap); + if (ret) { + DRM_ERROR("Failed to mmap DMA buffers\n"); + return -ENOMEM; + } + DRM_DEBUG("\n"); + radeon_gem_addbufs(dev); + + DRM_DEBUG("%x %d\n", dev_priv->mm.dma_bufs.bo->map_list.hash.key, size); + dev->agp_buffer_token = dev_priv->mm.dma_bufs.bo->map_list.hash.key << PAGE_SHIFT; + dev_priv->mm.fake_agp_map.handle = dev_priv->mm.dma_bufs.kmap.virtual; + dev_priv->mm.fake_agp_map.size = size; + + dev->agp_buffer_map = &dev_priv->mm.fake_agp_map; + + return 0; +} + +static void radeon_gem_dma_bufs_destroy(struct drm_device *dev) +{ + + struct drm_radeon_private *dev_priv = dev->dev_private; + drm_dma_takedown(dev); + + drm_bo_kunmap(&dev_priv->mm.dma_bufs.kmap); + drm_bo_usage_deref_unlocked(&dev_priv->mm.dma_bufs.bo); +} diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 51a5b00c..138db794 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -277,6 +277,9 @@ struct radeon_mm_info { struct radeon_mm_obj pcie_table; struct radeon_mm_obj ring; struct radeon_mm_obj ring_read; + + struct radeon_mm_obj dma_bufs; + struct drm_map fake_agp_map; }; #include "radeon_mode.h" From d59f41b8cf0634a433be7d11f6b473035060c5e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:11:15 +1000 Subject: [PATCH 29/49] radeon: add userspace call for mm support check --- shared-core/radeon_state.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index e168ea02..01ee71f6 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3121,6 +3121,9 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil /* BSD TODO */ value = 1; break; + case RADEON_PARAM_KERNEL_MM: + value = !dev_priv->mm_disabled; + break; default: DRM_DEBUG( "Invalid parameter %d\n", param->param ); return -EINVAL; From 18020e5e9647e218caf8f1566cdc053aac126f23 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:12:36 +1000 Subject: [PATCH 30/49] radeon: make buffer swap for older drivers work again on GEM --- linux-core/radeon_gem.c | 47 ++++++++++++++++++++++++++++++++++++++ shared-core/radeon_drv.h | 1 + shared-core/radeon_state.c | 3 +++ 3 files changed, 51 insertions(+) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 250e6852..058131e9 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1126,3 +1126,50 @@ static void radeon_gem_dma_bufs_destroy(struct drm_device *dev) drm_bo_kunmap(&dev_priv->mm.dma_bufs.kmap); drm_bo_usage_deref_unlocked(&dev_priv->mm.dma_bufs.bo); } + + +static struct drm_gem_object *gem_object_get(struct drm_device *dev, uint32_t name) +{ + struct drm_gem_object *obj; + + spin_lock(&dev->object_name_lock); + obj = idr_find(&dev->object_name_idr, name); + if (obj) + drm_gem_object_reference(obj); + spin_unlock(&dev->object_name_lock); + return obj; +} + +void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + + /* update front_pitch_offset and back_pitch_offset */ + DRM_ERROR("old front %x back %x\n", dev_priv->front_pitch_offset, dev_priv->back_pitch_offset); + obj = gem_object_get(dev, sarea_priv->front_handle); + if (obj) { + obj_priv = obj->driver_private; + + dev_priv->front_offset = obj_priv->bo->offset; + dev_priv->front_pitch_offset = (((sarea_priv->front_pitch / 64) << 22) | + ((obj_priv->bo->offset + + dev_priv->fb_location) >> 10)); + drm_gem_object_unreference(obj); + } + + obj = gem_object_get(dev, sarea_priv->back_handle); + if (obj) { + obj_priv = obj->driver_private; + dev_priv->back_offset = obj_priv->bo->offset; + dev_priv->back_pitch_offset = (((sarea_priv->back_pitch / 64) << 22) | + ((obj_priv->bo->offset + + dev_priv->fb_location) >> 10)); + drm_gem_object_unreference(obj); + } + dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; + +} diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 138db794..aa5b4ba8 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -1664,6 +1664,7 @@ extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *mas extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master); extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv); extern int radeon_cs_init(struct drm_device *dev); +void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master); #define MARK_SAFE 1 #define MARK_CHECK_OFFSET 2 diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 01ee71f6..1a828be8 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -2223,6 +2223,9 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; + if (dev_priv->mm.vram_offset) + radeon_gem_update_offsets(dev, file_priv->master); + radeon_cp_dispatch_swap(dev, file_priv->master); sarea_priv->ctx_owner = 0; From b0ee12e6bb55655c92184483a065780529c8aa63 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:14:14 +1000 Subject: [PATCH 31/49] radeon: use mm_enabled variable to denote memory manager running --- linux-core/radeon_gem.c | 5 ++++- shared-core/radeon_drv.h | 2 +- shared-core/radeon_state.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 058131e9..ebba3cfe 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -645,7 +645,7 @@ int radeon_gem_mm_init(struct drm_device *dev) if (ret) return -EINVAL; - + dev_priv->mm_enabled = true; return 0; } @@ -685,6 +685,9 @@ void radeon_gem_mm_fini(struct drm_device *dev) } mutex_unlock(&dev->struct_mutex); + + drm_bo_driver_finish(dev); + dev_priv->mm_enabled = false; } int radeon_gem_object_pin(struct drm_gem_object *obj, diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index aa5b4ba8..df08b8d3 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -399,7 +399,7 @@ typedef struct drm_radeon_private { int num_gb_pipes; - int mm_disabled; /* on OSes with no MM this will be 1*/ + bool mm_enabled; struct radeon_mm_info mm; drm_local_map_t *mmio; diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 1a828be8..4520a35d 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3125,7 +3125,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil value = 1; break; case RADEON_PARAM_KERNEL_MM: - value = !dev_priv->mm_disabled; + value = dev_priv->mm_enabled; break; default: DRM_DEBUG( "Invalid parameter %d\n", param->param ); From 58df2fa0ecc7e4dac83b4e7a72d70c3ea41c7ed2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:14:56 +1000 Subject: [PATCH 32/49] radeon: remove debugging --- linux-core/radeon_gem.c | 1 - shared-core/radeon_cs.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index ebba3cfe..4b9b1d38 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1152,7 +1152,6 @@ void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master struct drm_radeon_gem_object *obj_priv; /* update front_pitch_offset and back_pitch_offset */ - DRM_ERROR("old front %x back %x\n", dev_priv->front_pitch_offset, dev_priv->back_pitch_offset); obj = gem_object_get(dev, sarea_priv->front_handle); if (obj) { obj_priv = obj->driver_private; diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 33a8ccd4..d961189e 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -154,10 +154,7 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct break; } - - DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+1], val, offset); packets[offset_dw + 1] = val; - return 0; } @@ -185,7 +182,6 @@ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *f offset >>= 10; val |= offset; - DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+2], val, offset); packets[offset_dw + 2] = val; } default: @@ -215,7 +211,6 @@ static __inline__ int radeon_cs_check_offset(struct drm_device *dev, break; } - DRM_ERROR("Offset check %x %x\n", reg, offset); return 0; } From 0580785030714f10f624ad329354dc7c688c32ad Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:15:28 +1000 Subject: [PATCH 33/49] radeon: FEDORA: patch to make 3D driver work set gart buffers start --- linux-core/radeon_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 4b9b1d38..df4ed4ce 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1116,7 +1116,7 @@ static int radeon_gem_dma_bufs_init(struct drm_device *dev) dev_priv->mm.fake_agp_map.size = size; dev->agp_buffer_map = &dev_priv->mm.fake_agp_map; - + dev_priv->gart_buffers_offset = dev_priv->mm.dma_bufs.bo->offset + dev_priv->gart_vm_start; return 0; } From b167ccf10fffb3e0ae0be14fc3b168fcacc373d8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:17:43 +1000 Subject: [PATCH 34/49] radeon: fix kernel_mm properly --- shared-core/radeon_state.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 4520a35d..7262b2aa 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3120,10 +3120,6 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil case RADEON_PARAM_NUM_GB_PIPES: value = dev_priv->num_gb_pipes; break; - case RADEON_PARAM_KERNEL_MM: - /* BSD TODO */ - value = 1; - break; case RADEON_PARAM_KERNEL_MM: value = dev_priv->mm_enabled; break; From 7677c2dba5d06e888c742a607bc7f42d934043c6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 8 Aug 2008 19:36:46 -0400 Subject: [PATCH 35/49] on_each_cpu() compat fixup from krh --- linux-core/drm_compat.h | 8 ++++++++ linux-core/drm_ttm.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 19dc1f67..f1efc1fe 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -389,4 +389,12 @@ extern struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, unsigned long address, int *type); #endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) +#define drm_on_each_cpu(handler, data, wait) \ + on_each_cpu(handler, data, wait) +#else +#define drm_on_each_cpu(handler, data, wait) \ + on_each_cpu(handler, data, wait, 1) +#endif + #endif diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index b58a1ada..aa137dda 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -72,7 +72,7 @@ void drm_ttm_cache_flush(struct page *pages[], unsigned long num_pages) return; } #endif - if (on_each_cpu(drm_ttm_ipi_handler, NULL,1) != 0) + if (drm_on_each_cpu(drm_ttm_ipi_handler, NULL, 1) != 0) DRM_ERROR("Timed out waiting for drm cache flush.\n"); } EXPORT_SYMBOL(drm_ttm_cache_flush); From 5f427e9aaed76ec827b9523b4022205f5bd09a4a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Aug 2008 12:29:42 -0400 Subject: [PATCH 36/49] Brute force port of legacy crtc/encoder code - removed save/init/restore chain with set functions --- linux-core/radeon_atombios.c | 22 +- linux-core/radeon_display.c | 2 +- linux-core/radeon_encoders.c | 4 +- linux-core/radeon_legacy_crtc.c | 997 +++++++++++++++++----------- linux-core/radeon_legacy_encoders.c | 881 ++++++++++++++++++++---- linux-core/radeon_reg.h | 18 + shared-core/radeon_cp.c | 2 +- shared-core/radeon_drv.h | 2 +- 8 files changed, 1392 insertions(+), 536 deletions(-) diff --git a/linux-core/radeon_atombios.c b/linux-core/radeon_atombios.c index ee628732..cdb001c1 100644 --- a/linux-core/radeon_atombios.c +++ b/linux-core/radeon_atombios.c @@ -94,7 +94,7 @@ static void radeon_atom_apply_quirks(struct drm_device *dev, int index) mode_info->bios_connector[index].ddc_i2c.valid = false; } } -} +} bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device *dev) { @@ -146,7 +146,7 @@ bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device } mode_info->bios_connector[i].dac_type = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; - + if ((i == ATOM_DEVICE_TV1_INDEX) || (i == ATOM_DEVICE_TV2_INDEX) || (i == ATOM_DEVICE_TV1_INDEX)) @@ -161,7 +161,7 @@ bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device mode_info->bios_connector[i].ddc_i2c = radeon_lookup_gpio_for_ddc(dev, ci.sucI2cId.sbfAccess.bfI2C_LineMux); } else - mode_info->bios_connector[i].ddc_i2c = + mode_info->bios_connector[i].ddc_i2c = radeon_lookup_gpio_for_ddc(dev, ci.sucI2cId.sbfAccess.bfI2C_LineMux); if (i == ATOM_DEVICE_DFP1_INDEX) @@ -243,7 +243,7 @@ bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device } } - + DRM_DEBUG("BIOS Connector table\n"); for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { if (!mode_info->bios_connector[i].valid) @@ -265,7 +265,7 @@ union firmware_info { ATOM_FIRMWARE_INFO_V1_3 info_13; ATOM_FIRMWARE_INFO_V1_4 info_14; }; - + bool radeon_atom_get_clock_info(struct drm_device *dev) { struct drm_radeon_private *dev_priv = dev->dev_private; @@ -284,8 +284,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) pll->reference_div = 0; pll->pll_out_min = le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output); - pll->pll_out_max = le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); - + pll->pll_out_max = le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); + if (pll->pll_out_min == 0) { if (radeon_is_avivo(dev_priv)) pll->pll_out_min = 64800; @@ -298,7 +298,7 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) pll->xclk = le16_to_cpu(firmware_info->info.usMaxPixelClock); - return true; + return true; } union lvds_info { @@ -330,7 +330,7 @@ void radeon_get_lvds_info(struct radeon_encoder *encoder) encoder->vblank = le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time); encoder->hoverplus = le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset); encoder->hsync_width = le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); - encoder->panel_pwr_delay = le16_to_cpu(lvds_info->info.usOffDelayInMs); + encoder->panel_pwr_delay = le16_to_cpu(lvds_info->info.usOffDelayInMs); } void radeon_atom_dyn_clk_setup(struct drm_device *dev, int enable) @@ -342,7 +342,7 @@ void radeon_atom_dyn_clk_setup(struct drm_device *dev, int enable) int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating); args.ucEnable = enable; - + atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); } @@ -355,7 +355,7 @@ void radeon_atom_static_pwrmgt_setup(struct drm_device *dev, int enable) int index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt); args.ucEnable = enable; - + atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); } diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index 1e5233d2..97e9da55 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -336,7 +336,7 @@ bool radeon_setup_enc_conn(struct drm_device *dev) if ((mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I) || (mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_D)) { if (radeon_is_avivo(dev_priv)) - encoder = radeon_encoder_atom_tmds_add(dev, i, mode_info->bios_connector[i].dac_type); + encoder = radeon_encoder_atom_tmds_add(dev, i, mode_info->bios_connector[i].tmds_type); else { if (mode_info->bios_connector[i].tmds_type == TMDS_INT) encoder = radeon_encoder_legacy_tmds_int_add(dev, i); diff --git a/linux-core/radeon_encoders.c b/linux-core/radeon_encoders.c index 9a2d63ea..04c57092 100644 --- a/linux-core/radeon_encoders.c +++ b/linux-core/radeon_encoders.c @@ -279,7 +279,7 @@ static void radeon_lvtma_dpms(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_ON: atombios_display_device_control(encoder, index, ATOM_ENABLE); break; - case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: atombios_display_device_control(encoder, index, ATOM_DISABLE); @@ -792,7 +792,7 @@ static void radeon_atom_tmds_dpms(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_ON: atombios_display_device_control(encoder, index, ATOM_ENABLE); break; - case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: atombios_display_device_control(encoder, index, ATOM_DISABLE); diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index eb005a07..6446f8cb 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -34,74 +34,6 @@ void radeon_restore_common_regs(struct drm_device *dev, struct radeon_legacy_sta /* don't need this yet */ } -void radeon_restore_crtc_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - - RADEON_WRITE(RADEON_CRTC_GEN_CNTL, state->crtc_gen_cntl | - RADEON_CRTC_DISP_REQ_EN_B); - - RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, state->crtc_ext_cntl, - RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_DISPLAY_DIS); - - RADEON_WRITE(RADEON_CRTC_H_TOTAL_DISP, state->crtc_h_total_disp); - RADEON_WRITE(RADEON_CRTC_H_SYNC_STRT_WID, state->crtc_h_sync_strt_wid); - RADEON_WRITE(RADEON_CRTC_V_TOTAL_DISP, state->crtc_v_total_disp); - RADEON_WRITE(RADEON_CRTC_V_SYNC_STRT_WID, state->crtc_v_sync_strt_wid); - - if (radeon_is_r300(dev_priv)) - RADEON_WRITE(R300_CRTC_TILE_X0_Y0, state->crtc_tile_x0_y0); - - RADEON_WRITE(RADEON_CRTC_OFFSET_CNTL, state->crtc_offset_cntl); - RADEON_WRITE(RADEON_CRTC_OFFSET, state->crtc_offset); - - RADEON_WRITE(RADEON_CRTC_PITCH, state->crtc_pitch); - RADEON_WRITE(RADEON_DISP_MERGE_CNTL, state->disp_merge_cntl); - - /* if dell server */ - if (0) - { - RADEON_WRITE(RADEON_TV_DAC_CNTL, state->tv_dac_cntl); - RADEON_WRITE(RADEON_DISP_HW_DEBUG, state->disp_hw_debug); - RADEON_WRITE(RADEON_DAC_CNTL2, state->dac2_cntl); - RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, state->crtc2_gen_cntl); - } - - RADEON_WRITE(RADEON_CRTC_GEN_CNTL, state->crtc_gen_cntl); -} - -void radeon_restore_crtc2_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - - /* We prevent the CRTC from hitting th - e memory controller until - * fully programmed - */ - RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, - state->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_DISP_REQ_EN_B); - - RADEON_WRITE(RADEON_CRTC2_H_TOTAL_DISP, state->crtc2_h_total_disp); - RADEON_WRITE(RADEON_CRTC2_H_SYNC_STRT_WID, state->crtc2_h_sync_strt_wid); - RADEON_WRITE(RADEON_CRTC2_V_TOTAL_DISP, state->crtc2_v_total_disp); - RADEON_WRITE(RADEON_CRTC2_V_SYNC_STRT_WID, state->crtc2_v_sync_strt_wid); - - RADEON_WRITE(RADEON_FP_H2_SYNC_STRT_WID, state->fp_h2_sync_strt_wid); - RADEON_WRITE(RADEON_FP_V2_SYNC_STRT_WID, state->fp_v2_sync_strt_wid); - - if (radeon_is_r300(dev_priv)) - RADEON_WRITE(R300_CRTC2_TILE_X0_Y0, state->crtc2_tile_x0_y0); - RADEON_WRITE(RADEON_CRTC2_OFFSET_CNTL, state->crtc2_offset_cntl); - RADEON_WRITE(RADEON_CRTC2_OFFSET, state->crtc2_offset); - - RADEON_WRITE(RADEON_CRTC2_PITCH, state->crtc2_pitch); - RADEON_WRITE(RADEON_DISP2_MERGE_CNTL, state->disp2_merge_cntl); - - RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, state->crtc2_gen_cntl); -} - static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev) { struct drm_radeon_private *dev_priv = dev->dev_private; @@ -149,7 +81,7 @@ static void radeon_pll2_write_update(struct drm_device *dev) struct drm_radeon_private *dev_priv = dev->dev_private; while (RADEON_READ_PLL(dev_priv, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); - + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_REF_DIV, RADEON_P2PLL_ATOMIC_UPDATE_W, ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); @@ -186,186 +118,6 @@ static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div, return 1; } -void radeon_restore_pll_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - uint8_t pll_gain; - - pll_gain = radeon_compute_pll_gain(dev_priv->mode_info.pll.reference_freq, - state->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, - state->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK); - - if (dev_priv->flags & RADEON_IS_MOBILITY) { - /* A temporal workaround for the occational blanking on certain laptop panels. - This appears to related to the PLL divider registers (fail to lock?). - It occurs even when all dividers are the same with their old settings. - In this case we really don't need to fiddle with PLL registers. - By doing this we can avoid the blanking problem with some panels. - */ - if ((state->ppll_ref_div == (RADEON_READ_PLL(dev_priv, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && - (state->ppll_div_3 == (RADEON_READ_PLL(dev_priv, RADEON_PPLL_DIV_3) & - (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { - RADEON_WRITE_P(RADEON_CLOCK_CNTL_INDEX, - RADEON_PLL_DIV_SEL, - ~(RADEON_PLL_DIV_SEL)); - radeon_pll_errata_after_index(dev_priv); - return; - } - } - - RADEON_WRITE_PLL_P(dev_priv, RADEON_VCLK_ECP_CNTL, - RADEON_VCLK_SRC_SEL_CPUCLK, - ~(RADEON_VCLK_SRC_SEL_MASK)); - - RADEON_WRITE_PLL_P(dev_priv, - RADEON_PPLL_CNTL, - RADEON_PPLL_RESET - | RADEON_PPLL_ATOMIC_UPDATE_EN - | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN - | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT), - ~(RADEON_PPLL_RESET - | RADEON_PPLL_ATOMIC_UPDATE_EN - | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN - | RADEON_PPLL_PVG_MASK)); - - RADEON_WRITE_P(RADEON_CLOCK_CNTL_INDEX, - RADEON_PLL_DIV_SEL, - ~(RADEON_PLL_DIV_SEL)); - radeon_pll_errata_after_index(dev_priv); - - if (radeon_is_r300(dev_priv) || - (dev_priv->chip_family == CHIP_RS300) || - (dev_priv->chip_family == CHIP_RS400) || - (dev_priv->chip_family == CHIP_RS480)) { - if (state->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { - /* When restoring console mode, use saved PPLL_REF_DIV - * setting. - */ - RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, - state->ppll_ref_div, - 0); - } else { - /* R300 uses ref_div_acc field as real ref divider */ - RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, - (state->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), - ~R300_PPLL_REF_DIV_ACC_MASK); - } - } else { - RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, - state->ppll_ref_div, - ~RADEON_PPLL_REF_DIV_MASK); - } - - RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_DIV_3, - state->ppll_div_3, - ~RADEON_PPLL_FB3_DIV_MASK); - - RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_DIV_3, - state->ppll_div_3, - ~RADEON_PPLL_POST3_DIV_MASK); - - radeon_pll_write_update(dev); - radeon_pll_wait_for_read_update_complete(dev); - - RADEON_WRITE_PLL(dev_priv, RADEON_HTOTAL_CNTL, state->htotal_cntl); - - RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_CNTL, - 0, - ~(RADEON_PPLL_RESET - | RADEON_PPLL_SLEEP - | RADEON_PPLL_ATOMIC_UPDATE_EN - | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); - - DRM_DEBUG("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", - state->ppll_ref_div, - state->ppll_div_3, - (unsigned)state->htotal_cntl, - RADEON_READ_PLL(dev_priv, RADEON_PPLL_CNTL)); - DRM_DEBUG("Wrote: rd=%d, fd=%d, pd=%d\n", - state->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, - state->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, - (state->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); - - mdelay(50); /* Let the clock to lock */ - - RADEON_WRITE_PLL_P(dev_priv, RADEON_VCLK_ECP_CNTL, - RADEON_VCLK_SRC_SEL_PPLLCLK, - ~(RADEON_VCLK_SRC_SEL_MASK)); - - /*RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, state->vclk_ecp_cntl);*/ - -} - -void radeon_restore_pll2_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - uint8_t pll_gain; - - pll_gain = radeon_compute_pll_gain(dev_priv->mode_info.pll.reference_freq, - state->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, - state->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK); - - - RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, - RADEON_PIX2CLK_SRC_SEL_CPUCLK, - ~(RADEON_PIX2CLK_SRC_SEL_MASK)); - - RADEON_WRITE_PLL_P(dev_priv, - RADEON_P2PLL_CNTL, - RADEON_P2PLL_RESET - | RADEON_P2PLL_ATOMIC_UPDATE_EN - | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT), - ~(RADEON_P2PLL_RESET - | RADEON_P2PLL_ATOMIC_UPDATE_EN - | RADEON_P2PLL_PVG_MASK)); - - - RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_REF_DIV, - state->p2pll_ref_div, - ~RADEON_P2PLL_REF_DIV_MASK); - - RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_DIV_0, - state->p2pll_div_0, - ~RADEON_P2PLL_FB0_DIV_MASK); - - RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_DIV_0, - state->p2pll_div_0, - ~RADEON_P2PLL_POST0_DIV_MASK); - - radeon_pll2_write_update(dev); - radeon_pll2_wait_for_read_update_complete(dev); - - RADEON_WRITE_PLL(dev_priv, RADEON_HTOTAL2_CNTL, state->htotal_cntl2); - - RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_CNTL, - 0, - ~(RADEON_P2PLL_RESET - | RADEON_P2PLL_SLEEP - | RADEON_P2PLL_ATOMIC_UPDATE_EN)); - - DRM_DEBUG("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", - (unsigned)state->p2pll_ref_div, - (unsigned)state->p2pll_div_0, - (unsigned)state->htotal_cntl2, - RADEON_READ_PLL(dev_priv, RADEON_P2PLL_CNTL)); - DRM_DEBUG("Wrote2: rd=%u, fd=%u, pd=%u\n", - (unsigned)state->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, - (unsigned)state->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, - (unsigned)((state->p2pll_div_0 & - RADEON_P2PLL_POST0_DIV_MASK) >>16)); - - mdelay(50); /* Let the clock to lock */ - - RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, - RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, - ~(RADEON_PIX2CLK_SRC_SEL_MASK)); - - RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, state->pixclks_cntl); - - -} - - void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); @@ -374,7 +126,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) uint32_t mask; - mask = radeon_crtc->crtc_id ? + mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS); @@ -412,46 +164,45 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) } break; } - + if (mode != DRM_MODE_DPMS_OFF) { radeon_crtc_load_lut(crtc); } } -static bool radeon_init_crtc_base(struct drm_crtc *crtc, struct radeon_legacy_state *state, int x, int y) +static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_framebuffer *radeon_fb; struct drm_radeon_gem_object *obj_priv; uint32_t base; + uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; radeon_fb = to_radeon_framebuffer(crtc->fb); obj_priv = radeon_fb->obj->driver_private; - state->crtc_offset = obj_priv->bo->offset + dev_priv->fb_location; + crtc_offset = obj_priv->bo->offset; - state->crtc_offset_cntl = 0; + crtc_offset_cntl = 0; /* TODO tiling */ if (0) { - if (radeon_is_r300(dev_priv)) { - state->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - } else { - state->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; - } + if (radeon_is_r300(dev_priv)) + crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + crtc_offset_cntl |= RADEON_CRTC_TILE_EN; } else { - if (radeon_is_r300(dev_priv)) { - state->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - } else { - state->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; - } + if (radeon_is_r300(dev_priv)) + crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; } base = obj_priv->bo->offset; @@ -459,17 +210,29 @@ static bool radeon_init_crtc_base(struct drm_crtc *crtc, struct radeon_legacy_st /* TODO more tiling */ if (0) { if (radeon_is_r300(dev_priv)) { - state->crtc_tile_x0_y0 = x | (y << 16); - base &= ~0x7ff; - } else { - int byteshift = crtc->fb->bits_per_pixel >> 4; - int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; - base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); - state->crtc_offset_cntl |= (y % 16); - } + crtc_tile_x0_y0 = x | (y << 16); + base &= ~0x7ff; + } else { + int byteshift = crtc->fb->bits_per_pixel >> 4; + int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; + base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + crtc_offset_cntl |= (y % 16); + } } else { int offset = y * crtc->fb->pitch + x; switch (crtc->fb->bits_per_pixel) { + case 15: + case 16: + offset *= 2; + break; + case 24: + offset *= 3; + break; + case 32: + offset *= 4; + break; + default: + return false; } base += offset; } @@ -478,86 +241,114 @@ static bool radeon_init_crtc_base(struct drm_crtc *crtc, struct radeon_legacy_st /* update sarea TODO */ - state->crtc_offset = base; + crtc_offset = base; + + if (radeon_is_r300(dev_priv)) + RADEON_WRITE(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0); + + RADEON_WRITE(RADEON_CRTC_OFFSET_CNTL, crtc_offset_cntl); + RADEON_WRITE(RADEON_CRTC_OFFSET, crtc_offset); + return true; } -static bool radeon_init_crtc_registers(struct drm_crtc *crtc, struct radeon_legacy_state *state, - struct drm_display_mode *mode) +static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; int format; int hsync_start; int hsync_wid; int vsync_wid; + uint32_t crtc_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t crtc_h_total_disp; + uint32_t crtc_h_sync_strt_wid; + uint32_t crtc_v_total_disp; + uint32_t crtc_v_sync_strt_wid; + uint32_t crtc_pitch; + uint32_t disp_merge_cntl; switch (crtc->fb->depth) { - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ + case 15: /* 555 */ + format = 3; + break; + case 16: /* 565 */ + format = 4; + break; + case 24: /* RGB */ + format = 5; + break; + case 32: /* xRGB */ + format = 6; + break; default: return false; } - state->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN - | RADEON_CRTC_EN - | (format << 8) - | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) - ? RADEON_CRTC_DBL_SCAN_EN - : 0) - | ((mode->flags & DRM_MODE_FLAG_CSYNC) - ? RADEON_CRTC_CSYNC_EN - : 0) - | ((mode->flags & DRM_MODE_FLAG_INTERLACE) - ? RADEON_CRTC_INTERLACE_EN - : 0)); + crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + | RADEON_CRTC_EN + | (format << 8) + | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_CSYNC) + ? RADEON_CRTC_CSYNC_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); - state->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_DISPLAY_DIS); + crtc_ext_cntl = RADEON_READ(RADEON_CRTC_EXT_CNTL); + crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); - state->disp_merge_cntl = RADEON_READ(RADEON_DISP_MERGE_CNTL); - state->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + disp_merge_cntl = RADEON_READ(RADEON_DISP_MERGE_CNTL); + disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; - state->crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) - | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) - << 16)); + crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; - if (!hsync_wid) hsync_wid = 1; + if (!hsync_wid) + hsync_wid = 1; hsync_start = mode->crtc_hsync_start - 8; - state->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->flags & DRM_MODE_FLAG_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); + crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); /* This works for double scan mode. */ - state->crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) - | ((mode->crtc_vdisplay - 1) << 16)); + crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; - if (!vsync_wid) vsync_wid = 1; + if (!vsync_wid) + vsync_wid = 1; - state->crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->flags & DRM_MODE_FLAG_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0)); + crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); - state->crtc_pitch = (((crtc->fb->pitch * crtc->fb->bits_per_pixel) + - ((crtc->fb->bits_per_pixel * 8) -1)) / - (crtc->fb->bits_per_pixel * 8)); - state->crtc_pitch |= state->crtc_pitch << 16; + crtc_pitch = (((crtc->fb->pitch * crtc->fb->bits_per_pixel) + + ((crtc->fb->bits_per_pixel * 8) -1)) / + (crtc->fb->bits_per_pixel * 8)); + crtc_pitch |= crtc_pitch << 16; /* TODO -> Dell Server */ if (0) { + uint32_t disp_hw_debug = RADEON_READ(RADEON_DISP_HW_DEBUG); + uint32_t tv_dac_cntl = RADEON_READ(RADEON_TV_DAC_CNTL); + uint32_t dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2); + uint32_t crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); // state->dac2_cntl = info->StatedReg->dac2_cntl; // state->tv_dac_cntl = info->StatedReg->tv_dac_cntl; // state->crtc2_gen_cntl = info->StatedReg->crtc2_gen_cntl; @@ -569,25 +360,53 @@ static bool radeon_init_crtc_registers(struct drm_crtc *crtc, struct radeon_lega /* For CRT on DAC2, don't turn it on if BIOS didn't enable it, even it's detected. */ - state->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; - state->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); - state->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); + disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); + tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); + + RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl); + RADEON_WRITE(RADEON_DISP_HW_DEBUG, disp_hw_debug); + RADEON_WRITE(RADEON_DAC_CNTL2, dac2_cntl); + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); } + RADEON_WRITE(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl | + RADEON_CRTC_DISP_REQ_EN_B); + + RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, + RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_DISPLAY_DIS); + + RADEON_WRITE(RADEON_CRTC_H_TOTAL_DISP, crtc_h_total_disp); + RADEON_WRITE(RADEON_CRTC_H_SYNC_STRT_WID, crtc_h_sync_strt_wid); + RADEON_WRITE(RADEON_CRTC_V_TOTAL_DISP, crtc_v_total_disp); + RADEON_WRITE(RADEON_CRTC_V_SYNC_STRT_WID, crtc_v_sync_strt_wid); + + RADEON_WRITE(RADEON_CRTC_PITCH, crtc_pitch); + RADEON_WRITE(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); + + RADEON_WRITE(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); + return true; } -static void radeon_init_pll_registers(struct drm_crtc *crtc, struct radeon_legacy_state *state, - struct drm_display_mode *mode, int flags) +static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; uint32_t feedback_div = 0; uint32_t reference_div = 0; uint32_t post_divider = 0; uint32_t freq = 0; + uint8_t pll_gain; + /* PLL registers */ + uint32_t ppll_ref_div; + uint32_t ppll_div_3; + uint32_t htotal_cntl; + uint32_t vclk_ecp_cntl; + struct radeon_pll *pll = &dev_priv->mode_info.pll; + struct { int divider; int bitvalue; @@ -607,12 +426,12 @@ static void radeon_init_pll_registers(struct drm_crtc *crtc, struct radeon_legac { 12, 7 }, /* VCLK_SRC/12 */ { 0, 0 } }; - + #if 0 // TODO if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { - state->ppll_ref_div = info->RefDivider; - state->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); - state->htotal_cntl = 0; + ppll_ref_div = info->RefDivider; + ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); + htotal_cntl = 0; return; } #endif @@ -626,23 +445,16 @@ static void radeon_init_pll_registers(struct drm_crtc *crtc, struct radeon_legac } if (!post_div->divider) { - state->pll_output_freq = freq; post_div = &post_divs[0]; } - - state->dot_clock_freq = freq; - state->feedback_div = feedback_div; - state->reference_div = reference_div; - state->post_div = post_divider; - DRM_DEBUG("dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", - (unsigned)state->dot_clock_freq, - (unsigned)state->pll_output_freq, - state->feedback_div, - state->reference_div, - state->post_div); + DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)freq, + feedback_div, + reference_div, + post_divider); - state->ppll_ref_div = state->reference_div; + ppll_ref_div = reference_div; #if defined(__powerpc__) && (0) /* TODO */ /* apparently programming this otherwise causes a hang??? */ @@ -650,12 +462,451 @@ static void radeon_init_pll_registers(struct drm_crtc *crtc, struct radeon_legac state->ppll_div_3 = 0x000600ad; else #endif - state->ppll_div_3 = (state->feedback_div | (post_div->bitvalue << 16)); - - state->htotal_cntl = mode->htotal & 0x7; + ppll_div_3 = (feedback_div | (post_div->bitvalue << 16)); - state->vclk_ecp_cntl = (RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL) & - ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; + htotal_cntl = mode->htotal & 0x7; + + vclk_ecp_cntl = (RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL) & + ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; + + pll_gain = radeon_compute_pll_gain(dev_priv->mode_info.pll.reference_freq, + ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK); + + if (dev_priv->flags & RADEON_IS_MOBILITY) { + /* A temporal workaround for the occational blanking on certain laptop panels. + This appears to related to the PLL divider registers (fail to lock?). + It occurs even when all dividers are the same with their old settings. + In this case we really don't need to fiddle with PLL registers. + By doing this we can avoid the blanking problem with some panels. + */ + if ((ppll_ref_div == (RADEON_READ_PLL(dev_priv, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && + (ppll_div_3 == (RADEON_READ_PLL(dev_priv, RADEON_PPLL_DIV_3) & + (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { + RADEON_WRITE_P(RADEON_CLOCK_CNTL_INDEX, + RADEON_PLL_DIV_SEL, + ~(RADEON_PLL_DIV_SEL)); + radeon_pll_errata_after_index(dev_priv); + return; + } + } + + RADEON_WRITE_PLL_P(dev_priv, RADEON_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_CPUCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); + RADEON_WRITE_PLL_P(dev_priv, + RADEON_PPLL_CNTL, + RADEON_PPLL_RESET + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT), + ~(RADEON_PPLL_RESET + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | RADEON_PPLL_PVG_MASK)); + + RADEON_WRITE_P(RADEON_CLOCK_CNTL_INDEX, + RADEON_PLL_DIV_SEL, + ~(RADEON_PLL_DIV_SEL)); + radeon_pll_errata_after_index(dev_priv); + + if (radeon_is_r300(dev_priv) || + (dev_priv->chip_family == CHIP_RS300) || + (dev_priv->chip_family == CHIP_RS400) || + (dev_priv->chip_family == CHIP_RS480)) { + if (ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { + /* When restoring console mode, use saved PPLL_REF_DIV + * setting. + */ + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, + ppll_ref_div, + 0); + } else { + /* R300 uses ref_div_acc field as real ref divider */ + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, + (ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), + ~R300_PPLL_REF_DIV_ACC_MASK); + } + } else { + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_REF_DIV, + ppll_ref_div, + ~RADEON_PPLL_REF_DIV_MASK); + } + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_DIV_3, + ppll_div_3, + ~RADEON_PPLL_FB3_DIV_MASK); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_DIV_3, + ppll_div_3, + ~RADEON_PPLL_POST3_DIV_MASK); + + radeon_pll_write_update(dev); + radeon_pll_wait_for_read_update_complete(dev); + + RADEON_WRITE_PLL(dev_priv, RADEON_HTOTAL_CNTL, htotal_cntl); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PPLL_CNTL, + 0, + ~(RADEON_PPLL_RESET + | RADEON_PPLL_SLEEP + | RADEON_PPLL_ATOMIC_UPDATE_EN + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); + + DRM_DEBUG("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + ppll_ref_div, + ppll_div_3, + (unsigned)htotal_cntl, + RADEON_READ_PLL(dev_priv, RADEON_PPLL_CNTL)); + DRM_DEBUG("Wrote: rd=%d, fd=%d, pd=%d\n", + ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, + (ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); + + mdelay(50); /* Let the clock to lock */ + + RADEON_WRITE_PLL_P(dev_priv, RADEON_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_PPLLCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); + + /*RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, state->vclk_ecp_cntl);*/ + +} + +static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_framebuffer *radeon_fb; + struct drm_radeon_gem_object *obj_priv; + uint32_t crtc2_offset, crtc2_offset_cntl, crtc2_tile_x0_y0 = 0; + uint32_t base; + + radeon_fb = to_radeon_framebuffer(crtc->fb); + + obj_priv = radeon_fb->obj->driver_private; + + crtc2_offset = obj_priv->bo->offset; + + crtc2_offset_cntl = 0; + + /* TODO tiling */ + if (0) { + if (radeon_is_r300(dev_priv)) + crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; + } else { + if (radeon_is_r300(dev_priv)) + crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + base = obj_priv->bo->offset; + + /* TODO more tiling */ + if (0) { + if (radeon_is_r300(dev_priv)) { + crtc2_tile_x0_y0 = x | (y << 16); + base &= ~0x7ff; + } else { + int byteshift = crtc->fb->bits_per_pixel >> 4; + int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; + base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + crtc2_offset_cntl |= (y % 16); + } + } else { + int offset = y * crtc->fb->pitch + x; + switch (crtc->fb->bits_per_pixel) { + case 15: + case 16: + offset *= 2; + break; + case 24: + offset *= 3; + break; + case 32: + offset *= 4; + break; + default: + return false; + } + base += offset; + } + + base &= ~7; + + /* update sarea TODO */ + + crtc2_offset = base; + + if (radeon_is_r300(dev_priv)) + RADEON_WRITE(R300_CRTC2_TILE_X0_Y0, crtc2_tile_x0_y0); + RADEON_WRITE(RADEON_CRTC2_OFFSET_CNTL, crtc2_offset_cntl); + RADEON_WRITE(RADEON_CRTC2_OFFSET, crtc2_offset); + + return true; +} + +static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + uint32_t crtc2_gen_cntl; + uint32_t crtc2_h_total_disp; + uint32_t crtc2_h_sync_strt_wid; + uint32_t crtc2_v_total_disp; + uint32_t crtc2_v_sync_strt_wid; + uint32_t crtc2_pitch; + uint32_t disp2_merge_cntl; + uint32_t fp_h2_sync_strt_wid; + uint32_t fp_v2_sync_strt_wid; + + switch (crtc->fb->depth) { + + case 15: /* 555 */ + format = 3; + break; + case 16: /* 565 */ + format = 4; + break; + case 24: /* RGB */ + format = 5; + break; + case 32: /* xRGB */ + format = 6; + break; + default: + return false; + } + + crtc2_h_total_disp = + ((((mode->crtc_htotal / 8) - 1) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + hsync_start = mode->crtc_hsync_start - 8; + + crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + crtc2_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + crtc2_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC2_V_SYNC_POL + : 0)); + + crtc2_pitch = (((crtc->fb->pitch * crtc->fb->bits_per_pixel) + + ((crtc->fb->bits_per_pixel * 8) -1)) / + (crtc->fb->bits_per_pixel * 8)); + crtc2_pitch |= crtc2_pitch << 16; + + /* check to see if TV DAC is enabled for another crtc and keep it enabled */ + if (RADEON_READ(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON) + crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; + else + crtc2_gen_cntl = 0; + + crtc2_gen_cntl |= (RADEON_CRTC2_EN + | (format << 8) + | RADEON_CRTC2_VSYNC_DIS + | RADEON_CRTC2_HSYNC_DIS + | RADEON_CRTC2_DISP_DIS + | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) + ? RADEON_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_CSYNC) + ? RADEON_CRTC2_CSYNC_EN + : 0) + | ((mode->flags & DRM_MODE_FLAG_INTERLACE) + ? RADEON_CRTC2_INTERLACE_EN + : 0)); + + disp2_merge_cntl = RADEON_READ(RADEON_DISP2_MERGE_CNTL); + disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; + + fp_h2_sync_strt_wid = crtc2_h_sync_strt_wid; + fp_v2_sync_strt_wid = crtc2_v_sync_strt_wid; + + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, + crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_DISP_REQ_EN_B); + + RADEON_WRITE(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + RADEON_WRITE(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + RADEON_WRITE(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + RADEON_WRITE(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + + RADEON_WRITE(RADEON_FP_H2_SYNC_STRT_WID, fp_h2_sync_strt_wid); + RADEON_WRITE(RADEON_FP_V2_SYNC_STRT_WID, fp_v2_sync_strt_wid); + + RADEON_WRITE(RADEON_CRTC2_PITCH, crtc2_pitch); + RADEON_WRITE(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl); + + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + + return true; + +} + +static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t feedback_div = 0; + uint32_t reference_div = 0; + uint32_t post_divider = 0; + uint32_t freq = 0; + uint8_t pll_gain; + /* PLL2 registers */ + uint32_t p2pll_ref_div; + uint32_t p2pll_div_0; + uint32_t htotal_cntl2; + uint32_t pixclks_cntl; + + struct radeon_pll *pll = &dev_priv->mode_info.pll; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + +#if 0 + if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { + p2pll_ref_div = info->RefDivider; + p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16); + htotal_cntl2 = 0; + return; + } +#endif + + radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags); + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + if (post_div->divider == post_divider) + break; + } + + if (!post_div->divider) { + post_div = &post_divs[0]; + } + + DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)freq, + feedback_div, + reference_div, + post_divider); + + p2pll_ref_div = reference_div; + + p2pll_div_0 = (feedback_div | (post_div->bitvalue << 16)); + + htotal_cntl2 = mode->htotal & 0x7; + + pixclks_cntl = ((RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL) & + ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); + + pll_gain = radeon_compute_pll_gain(dev_priv->mode_info.pll.reference_freq, + p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK); + + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + RADEON_WRITE_PLL_P(dev_priv, + RADEON_P2PLL_CNTL, + RADEON_P2PLL_RESET + | RADEON_P2PLL_ATOMIC_UPDATE_EN + | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT), + ~(RADEON_P2PLL_RESET + | RADEON_P2PLL_ATOMIC_UPDATE_EN + | RADEON_P2PLL_PVG_MASK)); + + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_REF_DIV, + p2pll_ref_div, + ~RADEON_P2PLL_REF_DIV_MASK); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_DIV_0, + p2pll_div_0, + ~RADEON_P2PLL_FB0_DIV_MASK); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_DIV_0, + p2pll_div_0, + ~RADEON_P2PLL_POST0_DIV_MASK); + + radeon_pll2_write_update(dev); + radeon_pll2_wait_for_read_update_complete(dev); + + RADEON_WRITE_PLL(dev_priv, RADEON_HTOTAL2_CNTL, htotal_cntl2); + + RADEON_WRITE_PLL_P(dev_priv, RADEON_P2PLL_CNTL, + 0, + ~(RADEON_P2PLL_RESET + | RADEON_P2PLL_SLEEP + | RADEON_P2PLL_ATOMIC_UPDATE_EN)); + + DRM_DEBUG("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + (unsigned)p2pll_ref_div, + (unsigned)p2pll_div_0, + (unsigned)htotal_cntl2, + RADEON_READ_PLL(dev_priv, RADEON_P2PLL_CNTL)); + DRM_DEBUG("Wrote2: rd=%u, fd=%u, pd=%u\n", + (unsigned)p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + (unsigned)p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, + (unsigned)((p2pll_div_0 & + RADEON_P2PLL_POST0_DIV_MASK) >>16)); + + mdelay(50); /* Let the clock to lock */ + + RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl); } @@ -671,7 +922,7 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode, int x, int y) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_encoder *encoder; @@ -689,46 +940,44 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, } } - switch(radeon_crtc->crtc_id) { - case 0: - radeon_init_crtc_registers(crtc, &dev_priv->mode_info.legacy_state, adjusted_mode); - radeon_init_crtc_base(crtc, &dev_priv->mode_info.legacy_state, crtc->x, crtc->y); -// dot_clock = adjusted_mode->clock / 1000; - - // if (dot_clock) - radeon_init_pll_registers(crtc, &dev_priv->mode_info.legacy_state, adjusted_mode, - pll_flags); - break; - case 1: - break; - - } - /* TODO TV */ - switch (radeon_crtc->crtc_id) { + switch(radeon_crtc->crtc_id) { case 0: - radeon_restore_crtc_registers(dev, &dev_priv->mode_info.legacy_state); - radeon_restore_pll_registers(dev, &dev_priv->mode_info.legacy_state); + radeon_set_crtc1_timing(crtc, adjusted_mode); + radeon_set_pll1(crtc, adjusted_mode, pll_flags); break; case 1: - radeon_restore_crtc2_registers(dev, &dev_priv->mode_info.legacy_state); - radeon_restore_pll2_registers(dev, &dev_priv->mode_info.legacy_state); + radeon_set_crtc2_timing(crtc, adjusted_mode); + radeon_set_pll2(crtc, adjusted_mode, pll_flags); break; - } + } } void radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + switch(radeon_crtc->crtc_id) { + case 0: + radeon_set_crtc1_base(crtc, x, y); + break; + case 1: + radeon_set_crtc2_base(crtc, x, y); + break; + + } } static void radeon_crtc_prepare(struct drm_crtc *crtc) { + radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } static void radeon_crtc_commit(struct drm_crtc *crtc) { + radeon_crtc_dpms(crtc, DRM_MODE_DPMS_ON); } static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c index 8846653d..0ef7e113 100644 --- a/linux-core/radeon_legacy_encoders.c +++ b/linux-core/radeon_legacy_encoders.c @@ -29,148 +29,205 @@ #include "radeon_drv.h" -void radeon_restore_dac_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - - if (radeon_is_r300(dev_priv)) - RADEON_WRITE_P(RADEON_GPIOPAD_A, state->gpiopad_a, ~1); - - RADEON_WRITE_P(RADEON_DAC_CNTL, - state->dac_cntl, - RADEON_DAC_RANGE_CNTL | - RADEON_DAC_BLANKING); - - RADEON_WRITE(RADEON_DAC_CNTL2, state->dac2_cntl); - - if ((dev_priv->chip_family != CHIP_R100) && - (dev_priv->chip_family != CHIP_R200)) - RADEON_WRITE (RADEON_TV_DAC_CNTL, state->tv_dac_cntl); - - RADEON_WRITE(RADEON_DISP_OUTPUT_CNTL, state->disp_output_cntl); - - if ((dev_priv->chip_family == CHIP_R200) || - radeon_is_r300(dev_priv)) { - RADEON_WRITE(RADEON_DISP_TV_OUT_CNTL, state->disp_tv_out_cntl); - } else { - RADEON_WRITE(RADEON_DISP_HW_DEBUG, state->disp_hw_debug); - } - - RADEON_WRITE(RADEON_DAC_MACRO_CNTL, state->dac_macro_cntl); - - /* R200 DAC connected via DVO */ - if (dev_priv->chip_family == CHIP_R200) - RADEON_WRITE(RADEON_FP2_GEN_CNTL, state->fp2_gen_cntl); -} - - -/* Write TMDS registers */ -void radeon_restore_fp_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - - RADEON_WRITE(RADEON_TMDS_PLL_CNTL, state->tmds_pll_cntl); - RADEON_WRITE(RADEON_TMDS_TRANSMITTER_CNTL,state->tmds_transmitter_cntl); - RADEON_WRITE(RADEON_FP_GEN_CNTL, state->fp_gen_cntl); - - if ((dev_priv->chip_family == CHIP_RS400) || - (dev_priv->chip_family == CHIP_RS480)) { - RADEON_WRITE(RS400_FP_2ND_GEN_CNTL, state->fp_2nd_gen_cntl); - /*RADEON_WRITE(RS400_TMDS2_CNTL, state->tmds2_cntl);*/ - RADEON_WRITE(RS400_TMDS2_TRANSMITTER_CNTL, state->tmds2_transmitter_cntl); - } - - /* old AIW Radeon has some BIOS initialization problem - * with display buffer underflow, only occurs to DFP - */ - if (dev_priv->flags & RADEON_SINGLE_CRTC) - RADEON_WRITE(RADEON_GRPH_BUFFER_CNTL, - RADEON_READ(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); - -} - -/* Write FP2 registers */ -void radeon_restore_fp2_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - RADEON_WRITE(RADEON_FP2_GEN_CNTL, state->fp2_gen_cntl); - - if ((dev_priv->chip_family == CHIP_RS400) || - (dev_priv->chip_family == CHIP_RS480)) - RADEON_WRITE(RS400_FP2_2_GEN_CNTL, state->fp2_2_gen_cntl); -} - -/* Write RMX registers */ -void radeon_state_rmx_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - RADEON_WRITE(RADEON_FP_HORZ_STRETCH, state->fp_horz_stretch); - RADEON_WRITE(RADEON_FP_VERT_STRETCH, state->fp_vert_stretch); - RADEON_WRITE(RADEON_CRTC_MORE_CNTL, state->crtc_more_cntl); - RADEON_WRITE(RADEON_FP_HORZ_VERT_ACTIVE, state->fp_horz_vert_active); - RADEON_WRITE(RADEON_FP_H_SYNC_STRT_WID, state->fp_h_sync_strt_wid); - RADEON_WRITE(RADEON_FP_V_SYNC_STRT_WID, state->fp_v_sync_strt_wid); - RADEON_WRITE(RADEON_FP_CRTC_H_TOTAL_DISP, state->fp_crtc_h_total_disp); - RADEON_WRITE(RADEON_FP_CRTC_V_TOTAL_DISP, state->fp_crtc_v_total_disp); - -} - -/* Write LVDS registers */ -void radeon_restore_lvds_registers(struct drm_device *dev, struct radeon_legacy_state *state) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - - if (dev_priv->flags & RADEON_IS_MOBILITY) { - RADEON_WRITE(RADEON_LVDS_GEN_CNTL, state->lvds_gen_cntl); - /*RADEON_WRITE(RADEON_LVDS_PLL_CNTL, state->lvds_pll_cntl);*/ - - if (dev_priv->chip_family == CHIP_RV410) { - RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, 0); - } - } - -} - -static void radeon_init_fp_registers(struct drm_encoder *encoder, struct drm_display_mode *mode, - bool is_primary) -{ - - -} - -static void radeon_init_dac_registers(struct drm_encoder *encoder, struct radeon_legacy_state *state, - struct drm_display_mode *mode, bool is_primary) +static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + int xres = mode->hdisplay; + int yres = mode->vdisplay; + bool hscale = true, vscale = true; + int hsync_wid; + int vsync_wid; + int hsync_start; + uint32_t scale, inc; + uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active; + uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp; - if (is_primary) { - if (dev_priv->chip_family == CHIP_R200 || radeon_is_r300(dev_priv)) { - state->disp_output_cntl = RADEON_READ(RADEON_DISP_OUTPUT_CNTL & - ~RADEON_DISP_DAC_SOURCE_MASK); - } else { - state->dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2) & ~(RADEON_DAC2_DAC_CLK_SEL); - } - } else { - if (dev_priv->chip_family == CHIP_R200 || radeon_is_r300(dev_priv)) { - state->disp_output_cntl = RADEON_READ(RADEON_DISP_OUTPUT_CNTL & - ~RADEON_DISP_DAC_SOURCE_MASK); - state->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; - } else { - state->dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL; - } + + fp_vert_stretch = RADEON_READ(RADEON_FP_VERT_STRETCH) & + (RADEON_VERT_STRETCH_RESERVED | + RADEON_VERT_AUTO_RATIO_INC); + fp_horz_stretch = RADEON_READ(RADEON_FP_HORZ_STRETCH) & + (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); + + crtc_more_cntl = 0; + if ((dev_priv->chip_family == CHIP_RS100) || + (dev_priv->chip_family == CHIP_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. */ + crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; } - state->dac_cntl = (RADEON_DAC_MASK_ALL | - RADEON_DAC_VGA_ADR_EN | - /* TODO 6-bits */ - RADEON_DAC_8BIT_EN); - state->dac_macro_cntl = RADEON_READ(RADEON_DAC_MACRO_CNTL); + + fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + hsync_start = mode->crtc_hsync_start - 8; + + fp_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + fp_horz_vert_active = 0; + + if (radeon_encoder->panel_xres == 0 || + radeon_encoder->panel_yres == 0) { + hscale = false; + vscale = false; + } else { + if (xres > radeon_encoder->panel_xres) + xres = radeon_encoder->panel_xres; + if (yres > radeon_encoder->panel_yres) + yres = radeon_encoder->panel_yres; + + if (xres == radeon_encoder->panel_xres) + hscale = false; + if (yres == radeon_encoder->panel_yres) + vscale = false; + } + + if (radeon_encoder->flags & RADEON_USE_RMX) { + if (radeon_encoder->rmx_type != RMX_CENTER) { + if (!hscale) + fp_horz_stretch |= ((xres/8-1) << 16); + else { + inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; + scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) + / radeon_encoder->panel_xres + 1; + fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((radeon_encoder->panel_xres/8-1) << 16)); + } + + if (!vscale) + fp_vert_stretch |= ((yres-1) << 12); + else { + inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; + scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) + / radeon_encoder->panel_yres + 1; + fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((radeon_encoder->panel_yres-1) << 12)); + } + } else if (radeon_encoder->rmx_type == RMX_CENTER) { + int blank_width; + + fp_horz_stretch |= ((xres/8-1) << 16); + fp_vert_stretch |= ((yres-1) << 12); + + crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | + RADEON_CRTC_AUTO_VERT_CENTER_EN); + + blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; + if (blank_width > 110) + blank_width = 110; + + fp_crtc_h_total_disp = (((blank_width) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + + fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0))); + + fp_horz_vert_active = (((radeon_encoder->panel_yres) & 0xfff) | + (((radeon_encoder->panel_xres / 8) & 0x1ff) << 16)); + } + } else { + fp_horz_stretch |= ((xres/8-1) << 16); + fp_vert_stretch |= ((yres-1) << 12); + } + + RADEON_WRITE(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); + RADEON_WRITE(RADEON_FP_VERT_STRETCH, fp_vert_stretch); + RADEON_WRITE(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); + RADEON_WRITE(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); + RADEON_WRITE(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); + RADEON_WRITE(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); + RADEON_WRITE(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); + RADEON_WRITE(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); + } static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man; + + switch(mode) { + case DRM_MODE_DPMS_ON: + disp_pwr_man = RADEON_READ(RADEON_DISP_PWR_MAN); + disp_pwr_man |= RADEON_AUTO_PWRUP_EN; + RADEON_WRITE(RADEON_DISP_PWR_MAN, disp_pwr_man); + lvds_pll_cntl |= RADEON_LVDS_PLL_EN; + RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + udelay(1000); + lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL); + lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; + RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); + lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); + udelay(radeon_encoder->panel_pwr_delay * 1000); + RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + pixclks_cntl = RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL); + RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); + lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl); + break; + } } static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder) @@ -184,16 +241,53 @@ static void radeon_legacy_lvds_commit(struct drm_encoder *encoder) } static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t lvds_pll_cntl, lvds_gen_cntl; + if (radeon_crtc->crtc_id == 0) + radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); + lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL); + lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; + lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); + lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + lvds_gen_cntl &= ~(RADEON_LVDS_ON | + RADEON_LVDS_BLON | + RADEON_LVDS_EN | + RADEON_LVDS_RST_FM); + + if (radeon_is_r300(dev_priv)) + lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK); + + if (radeon_crtc->crtc_id == 0) { + if (radeon_is_r300(dev_priv)) { + if (radeon_encoder->flags & RADEON_USE_RMX) + lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; + } else + lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; + } else { + if (radeon_is_r300(dev_priv)) { + lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2; + } else + lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; + } + + RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + + if (dev_priv->chip_family == CHIP_RV410) + RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, 0); } static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -201,7 +295,7 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, if (radeon_encoder->rmx_type != RMX_OFF) radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); - + return true; } @@ -258,7 +352,34 @@ static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder, static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode) { + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t crtc_ext_cntl = RADEON_READ(RADEON_CRTC_EXT_CNTL); + uint32_t dac_cntl = RADEON_READ(RADEON_DAC_CNTL); + uint32_t dac_macro_cntl = RADEON_READ(RADEON_DAC_MACRO_CNTL); + switch(mode) { + case DRM_MODE_DPMS_ON: + crtc_ext_cntl |= RADEON_CRTC_CRT_ON; + dac_cntl &= ~RADEON_DAC_PDWN; + dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; + dac_cntl |= RADEON_DAC_PDWN; + dac_macro_cntl |= (RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + break; + } + + RADEON_WRITE(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + RADEON_WRITE(RADEON_DAC_CNTL, dac_cntl); + RADEON_WRITE(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); } @@ -273,16 +394,50 @@ static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder) } static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); - radeon_init_dac_registers(encoder, &dev_priv->mode_info.legacy_state, adjusted_mode, - (radeon_crtc->crtc_id == 1)); + uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl; - radeon_restore_dac_registers(dev, &dev_priv->mode_info.legacy_state); + if (radeon_crtc->crtc_id == 0) + radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); + + if (radeon_crtc->crtc_id == 0) { + if (dev_priv->chip_family == CHIP_R200 || radeon_is_r300(dev_priv)) { + disp_output_cntl = RADEON_READ(RADEON_DISP_OUTPUT_CNTL) & + ~(RADEON_DISP_DAC_SOURCE_MASK); + RADEON_WRITE(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + } else { + dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2) & ~(RADEON_DAC2_DAC_CLK_SEL); + RADEON_WRITE(RADEON_DAC_CNTL2, dac2_cntl); + } + } else { + if (dev_priv->chip_family == CHIP_R200 || radeon_is_r300(dev_priv)) { + disp_output_cntl = RADEON_READ(RADEON_DISP_OUTPUT_CNTL) & + ~(RADEON_DISP_DAC_SOURCE_MASK); + disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + RADEON_WRITE(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + } else { + dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL; + RADEON_WRITE(RADEON_DAC_CNTL2, dac2_cntl); + } + } + + dac_cntl = (RADEON_DAC_MASK_ALL | + RADEON_DAC_VGA_ADR_EN | + /* TODO 6-bits */ + RADEON_DAC_8BIT_EN); + + RADEON_WRITE_P(RADEON_DAC_CNTL, + dac_cntl, + RADEON_DAC_RANGE_CNTL | + RADEON_DAC_BLANKING); + + dac_macro_cntl = RADEON_READ(RADEON_DAC_MACRO_CNTL); + RADEON_WRITE(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); } static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = { @@ -318,6 +473,9 @@ struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs); + /* TODO get the primary dac vals from bios tables */ + //radeon_combios_get_lvds_info(radeon_encoder); + return encoder; } @@ -326,13 +484,27 @@ static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - + return true; } static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode) { - /* dfp1 */ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t fp_gen_cntl = RADEON_READ(RADEON_FP_GEN_CNTL); + switch(mode) { + case DRM_MODE_DPMS_ON: + fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + break; + } + + RADEON_WRITE(RADEON_FP_GEN_CNTL, fp_gen_cntl); } static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder) @@ -346,11 +518,87 @@ static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder) } static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { - + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl; + int i; + if (radeon_crtc->crtc_id == 0) + radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); + + tmp = tmds_pll_cntl = RADEON_READ(RADEON_TMDS_PLL_CNTL); + tmp &= 0xfffff; + if (dev_priv->chip_family == CHIP_RV280) { + /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ + tmp ^= (1 << 22); + tmds_pll_cntl ^= (1 << 22); + } + + for (i = 0; i < 4; i++) { + if (radeon_encoder->tmds_pll[i].freq == 0) + break; + if ((uint32_t)(mode->clock / 10) < radeon_encoder->tmds_pll[i].freq) { + tmp = radeon_encoder->tmds_pll[i].value ; + break; + } + } + + if (radeon_is_r300(dev_priv) || (dev_priv->chip_family == CHIP_RV280)) { + if (tmp & 0xfff00000) + tmds_pll_cntl = tmp; + else { + tmds_pll_cntl &= 0xfff00000; + tmds_pll_cntl |= tmp; + } + } else + tmds_pll_cntl = tmp; + + tmds_transmitter_cntl = RADEON_READ(RADEON_TMDS_TRANSMITTER_CNTL) & + ~(RADEON_TMDS_TRANSMITTER_PLLRST); + + if (dev_priv->chip_family == CHIP_R200 || + dev_priv->chip_family == CHIP_R100 || + radeon_is_r300(dev_priv)) + tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); + else /* RV chips got this bit reversed */ + tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN; + + fp_gen_cntl = (RADEON_READ(RADEON_FP_GEN_CNTL) | + (RADEON_FP_CRTC_DONT_SHADOW_VPAR | + RADEON_FP_CRTC_DONT_SHADOW_HEND)); + + fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + + if (1) // FIXME rgbBits == 8 + fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ + else + fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ + + if (radeon_crtc->crtc_id == 0) { + if (radeon_is_r300(dev_priv) || dev_priv->chip_family == CHIP_R200) { + fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + if (radeon_encoder->flags & RADEON_USE_RMX) + fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; + else + fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; + } else + fp_gen_cntl |= RADEON_FP_SEL_CRTC1; + } else { + if (radeon_is_r300(dev_priv) || dev_priv->chip_family == CHIP_R200) { + fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; + } else + fp_gen_cntl |= RADEON_FP_SEL_CRTC2; + } + + RADEON_WRITE(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl); + RADEON_WRITE(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl); + RADEON_WRITE(RADEON_FP_GEN_CNTL, fp_gen_cntl); } static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = { @@ -389,3 +637,344 @@ struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, i radeon_combios_get_tmds_info(radeon_encoder); return encoder; } + +static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL); + + switch(mode) { + case DRM_MODE_DPMS_ON: + fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; + fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + fp2_gen_cntl |= RADEON_FP2_BLANK_EN; + fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + break; + } + + RADEON_WRITE(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); +} + +static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder) +{ + radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder) +{ + radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL); + + if (radeon_crtc->crtc_id == 0) + radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); + + if (1) // FIXME rgbBits == 8 + fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + + fp2_gen_cntl &= ~(RADEON_FP2_ON | + RADEON_FP2_DVO_EN | + RADEON_FP2_DVO_RATE_SEL_SDR); + + /* XXX: these are oem specific */ + if (radeon_is_r300(dev_priv)) { + if ((dev->pdev->device == 0x4850) && + (dev->pdev->subsystem_vendor == 0x1028) && + (dev->pdev->subsystem_device == 0x2001)) /* Dell Inspiron 8600 */ + fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE; + else + fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE; + + /*if (mode->clock > 165000) + fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/ + } + + if (radeon_crtc->crtc_id == 0) { + if ((dev_priv->chip_family == CHIP_R200) || radeon_is_r300(dev_priv)) { + fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; + if (radeon_encoder->flags & RADEON_USE_RMX) + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + else + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; + } else + fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; + } else { + if ((dev_priv->chip_family == CHIP_R200) || radeon_is_r300(dev_priv)) { + fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else + fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; + } + + RADEON_WRITE(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); +} + +static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = { + .dpms = radeon_legacy_tmds_ext_dpms, + .mode_fixup = radeon_legacy_tmds_ext_mode_fixup, + .prepare = radeon_legacy_tmds_ext_prepare, + .mode_set = radeon_legacy_tmds_ext_mode_set, + .commit = radeon_legacy_tmds_ext_commit, +}; + + +static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + +struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_mode_info *mode_info = &dev_priv->mode_info; + struct radeon_encoder *radeon_encoder; + struct drm_encoder *encoder; + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); + if (!radeon_encoder) { + return NULL; + } + + encoder = &radeon_encoder->base; + + encoder->possible_crtcs = 0x3; + encoder->possible_clones = 0; + drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, + DRM_MODE_ENCODER_TMDS); + + drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs); + + //radeon_combios_get_tmds_info(radeon_encoder); + return encoder; +} + +static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t fp2_gen_cntl, crtc2_gen_cntl, tv_master_cntl, tv_dac_cntl; + + if (dev_priv->chip_family == CHIP_R200) + fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL); + else { + crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); + // FIXME TV + //tv_master_cntl = RADEON_READ(RADEON_TV_MASTER_CNTL); + tv_dac_cntl = RADEON_READ(RADEON_TV_DAC_CNTL); + } + + switch(mode) { + case DRM_MODE_DPMS_ON: + if (dev_priv->chip_family == CHIP_R200) + fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + else { + crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + //tv_master_cntl |= RADEON_TV_ON; + if (dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_RV410) + tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + else + tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + if (dev_priv->chip_family == CHIP_R200) + fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + else { + crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; + //tv_master_cntl &= ~RADEON_TV_ON; + if (dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_RV410) + tv_dac_cntl |= (R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + else + tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + break; + } + + if (dev_priv->chip_family == CHIP_R200) + RADEON_WRITE(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + else { + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + //RADEON_WRITE(RADEON_TV_MASTER_CNTL, tv_master_cntl); + RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl); + } + +} + +static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder) +{ + radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder) +{ + radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t tv_dac_cntl, gpiopad_a, dac2_cntl, disp_output_cntl, fp2_gen_cntl; + uint32_t disp_hw_debug; + + if (radeon_crtc->crtc_id == 0) + radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); + + if (dev_priv->chip_family != CHIP_R200) { + tv_dac_cntl = RADEON_READ(RADEON_TV_DAC_CNTL); + if (dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_RV410) { + tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + R420_TV_DAC_DACADJ_MASK | + R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_TVENABLE); + } else { + tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_GDACPD); + } + + // FIXME TV + tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_DAC_STD_PS2 /*| + radeon_encoder->ps2_tvdac_adj*/); // fixme, get from bios + + RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl); + } + + if (radeon_is_r300(dev_priv)) { + gpiopad_a = RADEON_READ(RADEON_GPIOPAD_A) | 1; + disp_output_cntl = RADEON_READ(RADEON_DISP_OUTPUT_CNTL); + } else if (dev_priv->chip_family == CHIP_R200) + fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL); + else + disp_hw_debug = RADEON_READ(RADEON_DISP_HW_DEBUG); + + dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL; + + if (radeon_crtc->crtc_id == 0) { + if (radeon_is_r300(dev_priv)) { + disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; + } else if (dev_priv->chip_family == CHIP_R200) { + fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + } else + disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + } else { + if (radeon_is_r300(dev_priv)) { + disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + } else if (dev_priv->chip_family == CHIP_R200) { + fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else + disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + } + + RADEON_WRITE(RADEON_DAC_CNTL2, dac2_cntl); + + if (radeon_is_r300(dev_priv)) { + RADEON_WRITE_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + RADEON_WRITE(RADEON_DISP_TV_OUT_CNTL, disp_output_cntl); + } else if (dev_priv->chip_family == CHIP_R200) + RADEON_WRITE(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + else + RADEON_WRITE(RADEON_DISP_HW_DEBUG, disp_hw_debug); + +} + +static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = { + .dpms = radeon_legacy_tv_dac_dpms, + .mode_fixup = radeon_legacy_tv_dac_mode_fixup, + .prepare = radeon_legacy_tv_dac_prepare, + .mode_set = radeon_legacy_tv_dac_mode_set, + .commit = radeon_legacy_tv_dac_commit, +}; + + +static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = { + .destroy = radeon_enc_destroy, +}; + +struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int has_tv) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_mode_info *mode_info = &dev_priv->mode_info; + struct radeon_encoder *radeon_encoder; + struct drm_encoder *encoder; + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); + if (!radeon_encoder) { + return NULL; + } + + encoder = &radeon_encoder->base; + + encoder->possible_crtcs = 0x3; + encoder->possible_clones = 0; + drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, + DRM_MODE_ENCODER_DAC); + + drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs); + + /* TODO get the tv dac vals from bios tables */ + //radeon_combios_get_lvds_info(radeon_encoder); + + return encoder; +} diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index 0f2d239c..887b2f84 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -556,6 +556,24 @@ # define RADEON_DAC_PDWN_R (1 << 16) # define RADEON_DAC_PDWN_G (1 << 17) # define RADEON_DAC_PDWN_B (1 << 18) +#define RADEON_DISP_PWR_MAN 0x0d08 +# define RADEON_DISP_PWR_MAN_D3_CRTC_EN (1 << 0) +# define RADEON_DISP_PWR_MAN_D3_CRTC2_EN (1 << 4) +# define RADEON_DISP_PWR_MAN_DPMS_ON (0 << 8) +# define RADEON_DISP_PWR_MAN_DPMS_STANDBY (1 << 8) +# define RADEON_DISP_PWR_MAN_DPMS_SUSPEND (2 << 8) +# define RADEON_DISP_PWR_MAN_DPMS_OFF (3 << 8) +# define RADEON_DISP_D3_RST (1 << 16) +# define RADEON_DISP_D3_REG_RST (1 << 17) +# define RADEON_DISP_D3_GRPH_RST (1 << 18) +# define RADEON_DISP_D3_SUBPIC_RST (1 << 19) +# define RADEON_DISP_D3_OV0_RST (1 << 20) +# define RADEON_DISP_D1D2_GRPH_RST (1 << 21) +# define RADEON_DISP_D1D2_SUBPIC_RST (1 << 22) +# define RADEON_DISP_D1D2_OV0_RST (1 << 23) +# define RADEON_DIG_TMDS_ENABLE_RST (1 << 24) +# define RADEON_TV_ENABLE_RST (1 << 25) +# define RADEON_AUTO_PWRUP_EN (1 << 26) #define RADEON_TV_DAC_CNTL 0x088c # define RADEON_TV_DAC_NBLANK (1 << 0) # define RADEON_TV_DAC_NHOLD (1 << 1) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index b751740c..53177bb0 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -185,7 +185,7 @@ void radeon_pll_errata_after_data(struct drm_radeon_private *dev_priv) } } -int RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr) +u32 RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr) { uint32_t data; diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index df08b8d3..fb266093 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -1277,7 +1277,7 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, #define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) #define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) -extern int RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr); +extern u32 RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr); extern void RADEON_WRITE_PLL(struct drm_radeon_private *dev_priv, int addr, uint32_t data); #define RADEON_WRITE_P(reg, val, mask) \ From b6f5b8ec7169320b79561c88ad04aefa795b3497 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Aug 2008 14:26:43 -0400 Subject: [PATCH 37/49] unify connector, i2c handling for atom and legacy --- linux-core/radeon_atombios.c | 4 +++ linux-core/radeon_combios.c | 41 ++++++++++------------ linux-core/radeon_connectors.c | 64 +++++++++++++++++----------------- linux-core/radeon_display.c | 27 ++++++++------ linux-core/radeon_mode.h | 8 +++-- 5 files changed, 77 insertions(+), 67 deletions(-) diff --git a/linux-core/radeon_atombios.c b/linux-core/radeon_atombios.c index cdb001c1..eb482d92 100644 --- a/linux-core/radeon_atombios.c +++ b/linux-core/radeon_atombios.c @@ -62,12 +62,16 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio_for_ddc(struct drm_de i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4; i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4; i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4; + i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4; + i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4; i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift); i2c.mask_data_mask = (1 << gpio.ucDataMaskShift); i2c.put_clk_mask = (1 << gpio.ucClkEnShift); i2c.put_data_mask = (1 << gpio.ucDataEnShift); i2c.get_clk_mask = (1 << gpio.ucClkY_Shift); i2c.get_data_mask = (1 << gpio.ucDataY_Shift); + i2c.a_clk_mask = (1 << gpio.ucClkA_Shift); + i2c.a_data_mask = (1 << gpio.ucDataA_Shift); i2c.valid = true; return i2c; diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c index 8a1dd8b3..3b01385c 100644 --- a/linux-core/radeon_combios.c +++ b/linux-core/radeon_combios.c @@ -57,8 +57,10 @@ struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line) { struct radeon_i2c_bus_rec i2c; - i2c.mask_clk_mask = RADEON_GPIO_EN_1 | RADEON_GPIO_Y_1; - i2c.mask_data_mask = RADEON_GPIO_EN_0 | RADEON_GPIO_Y_0; + i2c.mask_clk_mask = RADEON_GPIO_EN_1; + i2c.mask_data_mask = RADEON_GPIO_EN_0; + i2c.a_clk_mask = RADEON_GPIO_A_1; + i2c.a_data_mask = RADEON_GPIO_A_0; i2c.put_clk_mask = RADEON_GPIO_EN_1; i2c.put_data_mask = RADEON_GPIO_EN_0; i2c.get_clk_mask = RADEON_GPIO_Y_1; @@ -67,6 +69,8 @@ struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line) (ddc_line == RADEON_MDGPIO_EN_REG)) { i2c.mask_clk_reg = ddc_line; i2c.mask_data_reg = ddc_line; + i2c.a_clk_reg = ddc_line; + i2c.a_data_reg = ddc_line; i2c.put_clk_reg = ddc_line; i2c.put_data_reg = ddc_line; i2c.get_clk_reg = ddc_line + 4; @@ -74,17 +78,19 @@ struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line) } else { i2c.mask_clk_reg = ddc_line; i2c.mask_data_reg = ddc_line; + i2c.a_clk_reg = ddc_line; + i2c.a_data_reg = ddc_line; i2c.put_clk_reg = ddc_line; i2c.put_data_reg = ddc_line; i2c.get_clk_reg = ddc_line; i2c.get_data_reg = ddc_line; } - + if (ddc_line) i2c.valid = true; else i2c.valid = false; - + return i2c; } @@ -196,7 +202,7 @@ bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder) if (n > 4) n = 4; for (i = 0; i < n; i++) { encoder->tmds_pll[i].value = radeon_bios32(dev_priv, tmp+i*10+0x08); - encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmp+i*10+0x10); + encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmp+i*10+0x10); } return true; } else if (ver == 4) { @@ -219,7 +225,7 @@ static void radeon_apply_legacy_quirks(struct drm_device *dev, int bios_index) struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_mode_info *mode_info = &dev_priv->mode_info; - /* on XPRESS chips, CRT2_DDC and MONID_DCC both use the + /* on XPRESS chips, CRT2_DDC and MONID_DCC both use the * MONID gpio, but use different pins. * CRT2_DDC uses the standard pinout, MONID_DDC uses * something else. @@ -231,17 +237,6 @@ static void radeon_apply_legacy_quirks(struct drm_device *dev, int bios_index) mode_info->bios_connector[bios_index].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID); } - /* XPRESS desktop chips seem to have a proprietary connector listed for - * DVI-D, try and do the right thing here. - */ - if ((dev_priv->flags & RADEON_IS_MOBILITY) && - (mode_info->bios_connector[bios_index].connector_type == CONNECTOR_LVDS)) { - DRM_INFO("proprietary connector found. assuming DVI-D\n"); - mode_info->bios_connector[bios_index].dac_type = DAC_NONE; - mode_info->bios_connector[bios_index].tmds_type = TMDS_EXT; - mode_info->bios_connector[bios_index].connector_type = CONNECTOR_DVI_D; - } - /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ if (dev->pdev->device == 0x515e && @@ -272,16 +267,16 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) enum radeon_combios_ddc ddctype; enum radeon_combios_connector connector_type; int i; - + DRM_DEBUG("\n"); offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x50); if (offset) { for (i = 0; i < 4; i++) { entry = offset + 2 + i * 2; - + if (!radeon_bios16(dev_priv, entry)) break; - + mode_info->bios_connector[i].valid = true; tmp = radeon_bios16(dev_priv, entry); @@ -291,7 +286,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) switch(connector_type) { case CONNECTOR_PROPRIETARY_LEGACY: - mode_info->bios_connector[i].connector_type = CONNECTOR_LVDS; + mode_info->bios_connector[i].connector_type = CONNECTOR_DVI_D; break; case CONNECTOR_CRT_LEGACY: mode_info->bios_connector[i].connector_type = CONNECTOR_VGA; @@ -406,7 +401,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { if (!mode_info->bios_connector[i].valid) continue; - + DRM_DEBUG("Port %d: ddc_type 0x%x, dac_type %d, tmds_type %d, connector type %d, hpd_mask %d\n", i, mode_info->bios_connector[i].ddc_i2c.mask_clk_reg, mode_info->bios_connector[i].dac_type, @@ -417,4 +412,4 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) return true; } - + diff --git a/linux-core/radeon_connectors.c b/linux-core/radeon_connectors.c index 344b4f77..2cc0be06 100644 --- a/linux-core/radeon_connectors.c +++ b/linux-core/radeon_connectors.c @@ -36,9 +36,9 @@ static int radeon_lvds_get_modes(struct drm_connector *connector) int ret = 0; struct edid *edid; - avivo_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector, 1); edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - avivo_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector, 0); if (edid) { drm_mode_connector_update_edid_property(&radeon_connector->base, edid); ret = drm_add_edid_modes(&radeon_connector->base, edid); @@ -53,7 +53,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector) return ret; radeon_encoder_update_panel_size(lvds_encoder, connector); -#endif +#endif return ret; } @@ -111,33 +111,33 @@ struct drm_connector_funcs radeon_lvds_connector_funcs = { .destroy = radeon_connector_destroy, }; -static int radeon_atom_vga_get_modes(struct drm_connector *connector) +static int radeon_vga_get_modes(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); int ret; ret = radeon_ddc_get_modes(radeon_connector); - + return ret; } -static int radeon_atom_vga_mode_valid(struct drm_connector *connector, +static int radeon_vga_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { return MODE_OK; } -static enum drm_connector_status radeon_atom_vga_detect(struct drm_connector *connector) +static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) { struct edid *edid; struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder; struct drm_encoder_helper_funcs *encoder_funcs; - avivo_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector, 1); edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - avivo_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector, 0); if (edid) { kfree(edid); return connector_status_connected; @@ -152,20 +152,20 @@ static enum drm_connector_status radeon_atom_vga_detect(struct drm_connector *co return encoder_funcs->detect(encoder, connector); } -struct drm_connector_helper_funcs radeon_atom_vga_connector_helper_funcs = { - .get_modes = radeon_atom_vga_get_modes, - .mode_valid = radeon_atom_vga_mode_valid, +struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = { + .get_modes = radeon_vga_get_modes, + .mode_valid = radeon_vga_mode_valid, .best_encoder = radeon_best_single_encoder, }; -struct drm_connector_funcs radeon_atom_vga_connector_funcs = { - .detect = radeon_atom_vga_detect, +struct drm_connector_funcs radeon_vga_connector_funcs = { + .detect = radeon_vga_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = radeon_connector_destroy, }; -static enum drm_connector_status radeon_atom_dvi_detect(struct drm_connector *connector) +static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) { struct edid *edid; struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -175,9 +175,9 @@ static enum drm_connector_status radeon_atom_dvi_detect(struct drm_connector *co int i; enum drm_connector_status ret; - avivo_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector, 1); edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - avivo_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector, 0); if (edid) { /* if the monitor is digital - set the bits */ if (edid->digital) @@ -212,7 +212,7 @@ static enum drm_connector_status radeon_atom_dvi_detect(struct drm_connector *co } /* okay need to be smart in here about which encoder to pick */ -struct drm_encoder *radeon_atom_dvi_encoder(struct drm_connector *connector) +struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) { int enc_id = connector->encoder_ids[0]; struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -253,14 +253,14 @@ struct drm_encoder *radeon_atom_dvi_encoder(struct drm_connector *connector) return NULL; } -struct drm_connector_helper_funcs radeon_atom_dvi_connector_helper_funcs = { - .get_modes = radeon_atom_vga_get_modes, - .mode_valid = radeon_atom_vga_mode_valid, - .best_encoder = radeon_atom_dvi_encoder, +struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { + .get_modes = radeon_vga_get_modes, + .mode_valid = radeon_vga_mode_valid, + .best_encoder = radeon_dvi_encoder, }; -struct drm_connector_funcs radeon_atom_dvi_connector_funcs = { - .detect = radeon_atom_dvi_detect, +struct drm_connector_funcs radeon_dvi_connector_funcs = { + .detect = radeon_dvi_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = radeon_connector_destroy, }; @@ -272,12 +272,12 @@ static struct connector_funcs { struct drm_connector_helper_funcs *helper_funcs; int conn_type; char *i2c_id; -} connector_fns[] = { +} connector_fns[] = { { CONNECTOR_NONE, NULL, NULL, DRM_MODE_CONNECTOR_Unknown }, - { CONNECTOR_VGA, &radeon_atom_vga_connector_funcs, &radeon_atom_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA , "VGA"}, + { CONNECTOR_VGA, &radeon_vga_connector_funcs, &radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA , "VGA"}, { CONNECTOR_LVDS, &radeon_lvds_connector_funcs, &radeon_lvds_connector_helper_funcs, DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { CONNECTOR_DVI_A, &radeon_atom_vga_connector_funcs, &radeon_atom_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_DVIA, "DVI" }, - { CONNECTOR_DVI_I, &radeon_atom_dvi_connector_funcs, &radeon_atom_dvi_connector_helper_funcs, DRM_MODE_CONNECTOR_DVII, "DVI" }, + { CONNECTOR_DVI_A, &radeon_vga_connector_funcs, &radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_DVIA, "DVI" }, + { CONNECTOR_DVI_I, &radeon_dvi_connector_funcs, &radeon_dvi_connector_helper_funcs, DRM_MODE_CONNECTOR_DVII, "DVI" }, #if 0 { CONNECTOR_DVI_D, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, @@ -294,14 +294,14 @@ static struct connector_funcs { { CONNECTOR_DIN, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, { CONNECTOR_DISPLAY_PORT, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, #endif -}; - +}; + struct drm_connector *radeon_connector_add(struct drm_device *dev, int bios_index) { struct radeon_connector *radeon_connector; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_mode_info *mode_info = &dev_priv->mode_info; - struct drm_connector *connector; + struct drm_connector *connector; int table_idx; for (table_idx = 0; table_idx < ARRAY_SIZE(connector_fns); table_idx++) { @@ -323,7 +323,7 @@ struct drm_connector *radeon_connector_add(struct drm_device *dev, int bios_inde connector_fns[table_idx].conn_type); drm_connector_helper_add(&radeon_connector->base, connector_fns[table_idx].helper_funcs); - + if (mode_info->bios_connector[bios_index].ddc_i2c.valid) { radeon_connector->ddc_bus = radeon_i2c_create(dev, &mode_info->bios_connector[bios_index].ddc_i2c, connector_fns[table_idx].i2c_id); diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index 97e9da55..5272d198 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -361,25 +361,35 @@ bool radeon_setup_enc_conn(struct drm_device *dev) -void avivo_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state) +void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state) { struct drm_radeon_private *dev_priv = radeon_connector->base.dev->dev_private; uint32_t temp; struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec; + if (lock_state) { + temp = RADEON_READ(rec->a_clk_reg); + temp &= ~(rec->a_clk_mask); + RADEON_WRITE(rec->a_clk_reg, temp); + + temp = RADEON_READ(rec->a_data_reg); + temp &= ~(rec->a_data_mask); + RADEON_WRITE(rec->a_data_reg, temp); + } + temp = RADEON_READ(rec->mask_clk_reg); if (lock_state) - temp |= rec->put_clk_mask; + temp |= rec->mask_clk_mask; else - temp &= ~rec->put_clk_mask; + temp &= ~rec->mask_clk_mask; RADEON_WRITE(rec->mask_clk_reg, temp); temp = RADEON_READ(rec->mask_clk_reg); temp = RADEON_READ(rec->mask_data_reg); if (lock_state) - temp |= rec->put_data_mask; + temp |= rec->mask_data_mask; else - temp &= ~rec->put_data_mask; + temp &= ~rec->mask_data_mask; RADEON_WRITE(rec->mask_data_reg, temp); temp = RADEON_READ(rec->mask_data_reg); } @@ -392,12 +402,9 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) if (!radeon_connector->ddc_bus) return -1; - - if (radeon_is_avivo(dev_priv)) - avivo_i2c_do_lock(radeon_connector, 1); + radeon_i2c_do_lock(radeon_connector, 1); edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); - if (radeon_is_avivo(dev_priv)) - avivo_i2c_do_lock(radeon_connector, 0); + radeon_i2c_do_lock(radeon_connector, 0); if (edid) { drm_mode_connector_update_edid_property(&radeon_connector->base, edid); ret = drm_add_edid_modes(&radeon_connector->base, edid); diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h index 91c6f48d..b92490fc 100644 --- a/linux-core/radeon_mode.h +++ b/linux-core/radeon_mode.h @@ -91,6 +91,8 @@ struct radeon_i2c_bus_rec { bool valid; uint32_t mask_clk_reg; uint32_t mask_data_reg; + uint32_t a_clk_reg; + uint32_t a_data_reg; uint32_t put_clk_reg; uint32_t put_data_reg; uint32_t get_clk_reg; @@ -101,6 +103,8 @@ struct radeon_i2c_bus_rec { uint32_t put_data_mask; uint32_t get_clk_mask; uint32_t get_data_mask; + uint32_t a_clk_mask; + uint32_t a_data_mask; }; struct radeon_bios_connector { @@ -121,7 +125,7 @@ struct radeon_tmds_pll { }; #define RADEON_MAX_BIOS_CONNECTOR 16 - + #define RADEON_PLL_USE_BIOS_DIVS (1 << 0) #define RADEON_PLL_NO_ODD_POST_DIV (1 << 1) #define RADEON_PLL_USE_REF_DIV (1 << 2) @@ -406,7 +410,7 @@ void radeon_atombios_init_crtc(struct drm_device *dev, struct radeon_crtc *radeon_crtc); void radeon_legacy_init_crtc(struct drm_device *dev, struct radeon_crtc *radeon_crtc); -void avivo_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state); +void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state); void radeon_atom_static_pwrmgt_setup(struct drm_device *dev, int enable); void radeon_atom_dyn_clk_setup(struct drm_device *dev, int enable); From 019745c41758173eacb910dde512de0beb6a69eb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Aug 2008 14:41:13 -0400 Subject: [PATCH 38/49] Add legacy dac detect stubs --- linux-core/radeon_legacy_encoders.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c index 0ef7e113..46cf791e 100644 --- a/linux-core/radeon_legacy_encoders.c +++ b/linux-core/radeon_legacy_encoders.c @@ -440,12 +440,23 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, RADEON_WRITE(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); } +static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + return connector_status_disconnected; + +} + static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = { .dpms = radeon_legacy_primary_dac_dpms, .mode_fixup = radeon_legacy_primary_dac_mode_fixup, .prepare = radeon_legacy_primary_dac_prepare, .mode_set = radeon_legacy_primary_dac_mode_set, .commit = radeon_legacy_primary_dac_commit, + .detect = radeon_legacy_primary_dac_detect, }; @@ -940,12 +951,23 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, } +static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + return connector_status_disconnected; + +} + static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = { .dpms = radeon_legacy_tv_dac_dpms, .mode_fixup = radeon_legacy_tv_dac_mode_fixup, .prepare = radeon_legacy_tv_dac_prepare, .mode_set = radeon_legacy_tv_dac_mode_set, .commit = radeon_legacy_tv_dac_commit, + .detect = radeon_legacy_tv_dac_detect, }; From d4f9eaa55a0f9c1c9b3f8d92d734eff4a6ae859e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Aug 2008 16:15:21 -0400 Subject: [PATCH 39/49] various cleanups - white space - move i2c_lock to radeon_i2c.c - enable tv dac on legacy --- linux-core/radeon_display.c | 69 +++++++++++-------------------------- linux-core/radeon_i2c.c | 36 +++++++++++++++++-- linux-core/radeon_mode.h | 2 ++ 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index 5272d198..aa48e478 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -48,11 +48,11 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) DRM_DEBUG("%d\n", radeon_crtc->crtc_id); RADEON_WRITE(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0); - + RADEON_WRITE(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); RADEON_WRITE(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0); RADEON_WRITE(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0); - + RADEON_WRITE(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff); RADEON_WRITE(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff); RADEON_WRITE(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff); @@ -62,7 +62,6 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) RADEON_WRITE(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f); for (i = 0; i < 256; i++) { - RADEON_WRITE8(AVIVO_DC_LUT_RW_INDEX, i); RADEON_WRITE(AVIVO_DC_LUT_30_COLOR, (radeon_crtc->lut_r[i] << 22) | @@ -84,7 +83,6 @@ void radeon_crtc_load_lut(struct drm_crtc *crtc) if (!crtc->enabled) return; - if (radeon_is_avivo(dev_priv)) { avivo_crtc_load_lut(crtc); return; @@ -158,7 +156,7 @@ static int radeon_crtc_cursor_set(struct drm_crtc *crtc, } obj_priv = obj->driver_private; - + RADEON_WRITE(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0); if (radeon_is_avivo(dev_priv)) { RADEON_WRITE(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, @@ -172,7 +170,7 @@ static int radeon_crtc_cursor_set(struct drm_crtc *crtc, mutex_lock(&crtc->dev->struct_mutex); drm_gem_object_unreference(obj); mutex_unlock(&crtc->dev->struct_mutex); - + return 0; } @@ -202,7 +200,7 @@ static int radeon_crtc_cursor_move(struct drm_crtc *crtc, RADEON_WRITE(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); avivo_lock_cursor(crtc, false); } - + return 0; } @@ -325,8 +323,8 @@ bool radeon_setup_enc_conn(struct drm_device *dev) } else { if (mode_info->bios_connector[i].dac_type == DAC_PRIMARY) encoder = radeon_encoder_legacy_primary_dac_add(dev, i, 0); -// else if (mode_info->bios_connector[i].dac_type == DAC_TVDAC) -// encoder radeon_encoder_legacy_secondary_dac_add(dev, i, 0); + else if (mode_info->bios_connector[i].dac_type == DAC_TVDAC) + encoder = radeon_encoder_legacy_tv_dac_add(dev, i, 0); } if (encoder) drm_mode_connector_attach_encoder(connector, encoder); @@ -340,6 +338,8 @@ bool radeon_setup_enc_conn(struct drm_device *dev) else { if (mode_info->bios_connector[i].tmds_type == TMDS_INT) encoder = radeon_encoder_legacy_tmds_int_add(dev, i); + else if (mode_info->bios_connector[i].dac_type == TMDS_EXT) + encoder = radeon_encoder_legacy_tmds_ext_add(dev, i); } if (encoder) drm_mode_connector_attach_encoder(connector, encoder); @@ -349,6 +349,10 @@ bool radeon_setup_enc_conn(struct drm_device *dev) if (mode_info->bios_connector[i].connector_type == CONNECTOR_DIN) { if (radeon_is_avivo(dev_priv)) encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 1); + else { + if (mode_info->bios_connector[i].dac_type == DAC_TVDAC) + encoder = radeon_encoder_legacy_tv_dac_add(dev, i, 0); + } if (encoder) drm_mode_connector_attach_encoder(connector, encoder); } @@ -359,41 +363,6 @@ bool radeon_setup_enc_conn(struct drm_device *dev) return true; } - - -void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state) -{ - struct drm_radeon_private *dev_priv = radeon_connector->base.dev->dev_private; - uint32_t temp; - struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec; - - if (lock_state) { - temp = RADEON_READ(rec->a_clk_reg); - temp &= ~(rec->a_clk_mask); - RADEON_WRITE(rec->a_clk_reg, temp); - - temp = RADEON_READ(rec->a_data_reg); - temp &= ~(rec->a_data_mask); - RADEON_WRITE(rec->a_data_reg, temp); - } - - temp = RADEON_READ(rec->mask_clk_reg); - if (lock_state) - temp |= rec->mask_clk_mask; - else - temp &= ~rec->mask_clk_mask; - RADEON_WRITE(rec->mask_clk_reg, temp); - temp = RADEON_READ(rec->mask_clk_reg); - - temp = RADEON_READ(rec->mask_data_reg); - if (lock_state) - temp |= rec->mask_data_mask; - else - temp &= ~rec->mask_data_mask; - RADEON_WRITE(rec->mask_data_reg, temp); - temp = RADEON_READ(rec->mask_data_reg); -} - int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) { struct drm_radeon_private *dev_priv = radeon_connector->base.dev->dev_private; @@ -422,7 +391,9 @@ int radeon_ddc_dump(struct drm_connector *connector) if (!radeon_connector->ddc_bus) return -1; + radeon_i2c_do_lock(radeon_connector, 1); edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); + radeon_i2c_do_lock(radeon_connector, 0); if (edid) { kfree(edid); } @@ -433,7 +404,7 @@ static inline uint32_t radeon_div(uint64_t n, uint32_t d) { uint64_t x, y, result; uint64_t mod; - + n += d / 2; mod = do_div(n, d); @@ -519,7 +490,7 @@ void radeon_compute_pll(struct radeon_pll *pll, current_freq = radeon_div((uint64_t)pll->reference_freq * 10000 * feedback_div, ref_div * post_div); - + error = abs(current_freq - freq); vco_diff = abs(vco - best_vco); @@ -550,7 +521,7 @@ void radeon_compute_pll(struct radeon_pll *pll, best_vco_diff = vco_diff; } } - + if (current_freq < freq) min_feed_div = feedback_div+1; else @@ -558,7 +529,7 @@ void radeon_compute_pll(struct radeon_pll *pll, } } } - + *dot_clock_p = best_freq / 10000; *fb_div_p = best_feedback_div; *ref_div_p = best_ref_div; @@ -680,7 +651,7 @@ int radeon_modeset_init(struct drm_device *dev) if (!ret) return ret; - + drm_helper_initial_config(dev, false); return 0; diff --git a/linux-core/radeon_i2c.c b/linux-core/radeon_i2c.c index eccec650..00fc7c0e 100644 --- a/linux-core/radeon_i2c.c +++ b/linux-core/radeon_i2c.c @@ -27,6 +27,38 @@ #include "radeon_drm.h" #include "radeon_drv.h" +void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state) +{ + struct drm_radeon_private *dev_priv = radeon_connector->base.dev->dev_private; + uint32_t temp; + struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec; + + if (lock_state) { + temp = RADEON_READ(rec->a_clk_reg); + temp &= ~(rec->a_clk_mask); + RADEON_WRITE(rec->a_clk_reg, temp); + + temp = RADEON_READ(rec->a_data_reg); + temp &= ~(rec->a_data_mask); + RADEON_WRITE(rec->a_data_reg, temp); + } + + temp = RADEON_READ(rec->mask_clk_reg); + if (lock_state) + temp |= rec->mask_clk_mask; + else + temp &= ~rec->mask_clk_mask; + RADEON_WRITE(rec->mask_clk_reg, temp); + temp = RADEON_READ(rec->mask_clk_reg); + + temp = RADEON_READ(rec->mask_data_reg); + if (lock_state) + temp |= rec->mask_data_mask; + else + temp &= ~rec->mask_data_mask; + RADEON_WRITE(rec->mask_data_reg, temp); + temp = RADEON_READ(rec->mask_data_reg); +} static int get_clock(void *i2c_priv) { @@ -88,7 +120,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, i2c = drm_calloc(1, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER); if (i2c == NULL) return NULL; - + i2c->adapter.owner = THIS_MODULE; i2c->adapter.id = I2C_HW_B_RADEON; i2c->adapter.algo_data = &i2c->algo; @@ -113,7 +145,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, out_free: drm_free(i2c, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER); return NULL; - + } void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h index b92490fc..3e0ffc66 100644 --- a/linux-core/radeon_mode.h +++ b/linux-core/radeon_mode.h @@ -382,7 +382,9 @@ struct drm_encoder *radeon_encoder_atom_dac_add(struct drm_device *dev, int bios struct drm_encoder *radeon_encoder_atom_tmds_add(struct drm_device *dev, int bios_index, int tmds_type); struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv); +struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int with_tv); struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index); +struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index); extern void radeon_crtc_load_lut(struct drm_crtc *crtc); extern void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y); From e20c670a5a7896a7ad6c004c744993e3be3879dc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Aug 2008 16:29:19 -0400 Subject: [PATCH 40/49] LUT updates - Add gamma set for legacy chips - Add 16 bpp gamma set --- linux-core/radeon_display.c | 65 +++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index aa48e478..95258efa 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -72,33 +72,43 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) RADEON_WRITE(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id); } +static void legacy_crtc_load_lut(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + int i; + uint32_t dac2_cntl; + + dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2); + if (radeon_crtc->crtc_id == 0) + dac2_cntl &= (uint32_t)~RADEON_DAC2_PALETTE_ACC_CTL; + else + dac2_cntl |= RADEON_DAC2_PALETTE_ACC_CTL; + RADEON_WRITE(RADEON_DAC_CNTL2, dac2_cntl); + + for (i = 0; i < 256; i++) { + RADEON_WRITE8(RADEON_PALETTE_INDEX, i); + RADEON_WRITE(RADEON_PALETTE_DATA, + (radeon_crtc->lut_r[i] << 16) | + (radeon_crtc->lut_g[i] << 8) | + (radeon_crtc->lut_b[i] << 0)); + } +} void radeon_crtc_load_lut(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; - u32 temp; - int i; + if (!crtc->enabled) return; - if (radeon_is_avivo(dev_priv)) { + if (radeon_is_avivo(dev_priv)) avivo_crtc_load_lut(crtc); - return; - } - - temp = RADEON_READ(RADEON_DAC_CNTL2); - if (radeon_crtc->crtc_id == 0) - temp &= (uint32_t)~RADEON_DAC2_PALETTE_ACC_CTL; else - temp |= RADEON_DAC2_PALETTE_ACC_CTL; - RADEON_WRITE(RADEON_DAC_CNTL2, temp); - - for (i = 0; i < 256; i++) { -// OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]); - } - + legacy_crtc_load_lut(crtc); } /** Sets the color ramps on behalf of RandR */ @@ -208,15 +218,28 @@ static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - int i; + int i, j; if (size != 256) return; - for (i = 0; i < 256; i++) { - radeon_crtc->lut_r[i] = red[i] >> 8; - radeon_crtc->lut_g[i] = green[i] >> 8; - radeon_crtc->lut_b[i] = blue[i] >> 8; + if (crtc->fb->depth == 16) { + for (i = 0; i < 64; i++) { + if (i <= 31) { + for (j = 0; j < 8; j++) { + radeon_crtc->lut_r[i * 8 + j] = red[i] >> 8; + radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 8; + } + } + for (j = 0; j < 4; j++) + radeon_crtc->lut_g[i * 4 + j] = green[i] >> 8; + } + } else { + for (i = 0; i < 256; i++) { + radeon_crtc->lut_r[i] = red[i] >> 8; + radeon_crtc->lut_g[i] = green[i] >> 8; + radeon_crtc->lut_b[i] = blue[i] >> 8; + } } radeon_crtc_load_lut(crtc); From f2351ab38c8157bdbc839ad628b1dde6693f51bd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Aug 2008 17:02:18 -0400 Subject: [PATCH 41/49] atom: implement crtc lock --- linux-core/atombios_crtc.c | 76 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/linux-core/atombios_crtc.c b/linux-core/atombios_crtc.c index 1f372045..0a86f36b 100644 --- a/linux-core/atombios_crtc.c +++ b/linux-core/atombios_crtc.c @@ -31,6 +31,22 @@ #include "atom.h" #include "atom-bits.h" +static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + int index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); + ENABLE_CRTC_PS_ALLOCATION args; + + memset(&args, 0, sizeof(args)); + + args.ucCRTC = radeon_crtc->crtc_id; + args.ucEnable = lock; + + atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); +} + static void atombios_enable_crtc(struct drm_crtc *crtc, int state) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); @@ -127,7 +143,7 @@ void atombios_crtc_set_timing(struct drm_crtc *crtc, SET_CRTC_TIMING_PARAMETERS_ conv_param.ucOverscanRight = crtc_param->ucOverscanRight; conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft; conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom; - conv_param.ucOverscanTop = crtc_param->ucOverscanTop; + conv_param.ucOverscanTop = crtc_param->ucOverscanTop; conv_param.ucReserved = crtc_param->ucReserved; printk("executing set crtc timing\n"); @@ -150,29 +166,21 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode, memset(&spc_param, 0, sizeof(SET_PIXEL_CLOCK_PS_ALLOCATION)); + pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + + radeon_compute_pll(&dev_priv->mode_info.pll, mode->clock, + &sclock, &fb_div, &ref_div, &post_div, pll_flags); + if (radeon_is_avivo(dev_priv)) { - uint32_t temp; - - pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; - - radeon_compute_pll(&dev_priv->mode_info.pll, mode->clock, - &temp, &fb_div, &ref_div, &post_div, pll_flags); - sclock = temp; + uint32_t ss_cntl; if (radeon_crtc->crtc_id == 0) { - temp = RADEON_READ(AVIVO_P1PLL_INT_SS_CNTL); - RADEON_WRITE(AVIVO_P1PLL_INT_SS_CNTL, temp & ~1); + ss_cntl = RADEON_READ(AVIVO_P1PLL_INT_SS_CNTL); + RADEON_WRITE(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1); } else { - temp = RADEON_READ(AVIVO_P2PLL_INT_SS_CNTL); - RADEON_WRITE(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1); + ss_cntl = RADEON_READ(AVIVO_P2PLL_INT_SS_CNTL); + RADEON_WRITE(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1); } - } else { -#if 0 // TODO r400 - sclock = save->dot_clock_freq; - fb_div = save->feedback_div; - post_div = save->post_div; - ref_div = save->ppll_ref_div; -#endif } /* */ @@ -201,7 +209,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode, spc3_ptr->ucPostDiv = post_div; spc3_ptr->ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2); - + /* TODO insert output encoder object stuff herre for r600 */ break; default: @@ -220,7 +228,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode, void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_framebuffer *radeon_fb; @@ -251,19 +259,17 @@ void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y) DRM_ERROR("Unsupported screen depth %d\n", crtc->fb->bits_per_pixel); return; } - + /* TODO tiling */ if (radeon_crtc->crtc_id == 0) RADEON_WRITE(AVIVO_D1VGA_CONTROL, 0); else RADEON_WRITE(AVIVO_D2VGA_CONTROL, 0); - - RADEON_WRITE(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, AVIVO_D1GRPH_UPDATE_LOCK); - + RADEON_WRITE(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, fb_location); RADEON_WRITE(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, fb_location); RADEON_WRITE(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); - + RADEON_WRITE(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); RADEON_WRITE(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); RADEON_WRITE(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, x); @@ -274,20 +280,13 @@ void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y) fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); RADEON_WRITE(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); RADEON_WRITE(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); - - /* unlock the grph regs */ - RADEON_WRITE(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, 0); - - /* lock the mode regs */ - RADEON_WRITE(AVIVO_D1SCL_UPDATE + radeon_crtc->crtc_offset, AVIVO_D1SCL_UPDATE_LOCK); - + RADEON_WRITE(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, crtc->mode.vdisplay); RADEON_WRITE(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y); RADEON_WRITE(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); - /* unlock the mode regs */ - RADEON_WRITE(AVIVO_D1SCL_UPDATE + radeon_crtc->crtc_offset, 0); + } void atombios_crtc_mode_set(struct drm_crtc *crtc, @@ -324,7 +323,7 @@ void atombios_crtc_mode_set(struct drm_crtc *crtc, if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY; - + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY; @@ -337,9 +336,8 @@ void atombios_crtc_mode_set(struct drm_crtc *crtc, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; - if (radeon_is_avivo(dev_priv)) { + if (radeon_is_avivo(dev_priv)) atombios_crtc_set_base(crtc, x, y); - } atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags); @@ -357,11 +355,13 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, static void atombios_crtc_prepare(struct drm_crtc *crtc) { atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + atombios_lock_crtc(crtc, 1); } static void atombios_crtc_commit(struct drm_crtc *crtc) { atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + atombios_lock_crtc(crtc, 0); } static const struct drm_crtc_helper_funcs atombios_helper_funcs = { From 5af426a2b29f5426ba5714cb6501aa5b270089b4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Aug 2008 18:37:16 -0400 Subject: [PATCH 42/49] Restructure cursor handling and add support for legacy cursors --- linux-core/Makefile.kernel | 3 +- linux-core/radeon_cursor.c | 243 ++++++++++++++++++++++++++++++++++++ linux-core/radeon_display.c | 93 -------------- linux-core/radeon_mode.h | 9 ++ linux-core/radeon_reg.h | 13 +- 5 files changed, 262 insertions(+), 99 deletions(-) create mode 100644 linux-core/radeon_cursor.c diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 576de5b2..036461db 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -41,7 +41,8 @@ nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nv50_fbcon.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o radeon_gem.o \ radeon_buffer.o radeon_fence.o atom.o radeon_display.o radeon_atombios.o radeon_i2c.o radeon_connectors.o radeon_cs.o \ - atombios_crtc.o radeon_encoders.o radeon_fb.o radeon_combios.o radeon_legacy_crtc.o radeon_legacy_encoders.o + atombios_crtc.o radeon_encoders.o radeon_fb.o radeon_combios.o radeon_legacy_crtc.o radeon_legacy_encoders.o \ + radeon_cursor.o sis-objs := sis_drv.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o savage-objs := savage_drv.o savage_bci.o savage_state.o diff --git a/linux-core/radeon_cursor.c b/linux-core/radeon_cursor.c new file mode 100644 index 00000000..e71b325d --- /dev/null +++ b/linux-core/radeon_cursor.c @@ -0,0 +1,243 @@ +/* + * Copyright 2007-8 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + */ +#include "drmP.h" +#include "radeon_drm.h" +#include "radeon_drv.h" + +#define CURSOR_WIDTH 64 +#define CURSOR_HEIGHT 64 + +static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock) +{ + struct drm_radeon_private *dev_priv = crtc->dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + uint32_t cur_lock; + + if (radeon_is_avivo(dev_priv)) { + cur_lock = RADEON_READ(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); + if (lock) + cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK; + else + cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK; + RADEON_WRITE(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock); + } else { + switch(radeon_crtc->crtc_id) { + case 0: + cur_lock = RADEON_READ(RADEON_CUR_OFFSET); + if (lock) + cur_lock |= RADEON_CUR_LOCK; + else + cur_lock &= ~RADEON_CUR_LOCK; + RADEON_WRITE(RADEON_CUR_OFFSET, cur_lock); + break; + case 1: + cur_lock = RADEON_READ(RADEON_CUR2_OFFSET); + if (lock) + cur_lock |= RADEON_CUR2_LOCK; + else + cur_lock &= ~RADEON_CUR2_LOCK; + RADEON_WRITE(RADEON_CUR2_OFFSET, cur_lock); + break; + default: + break; + } + } +} + +static void radeon_hide_cursor(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_radeon_private *dev_priv = crtc->dev->dev_private; + + if (radeon_is_avivo(dev_priv)) { + RADEON_WRITE(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); + RADEON_WRITE_P(RADEON_MM_DATA, 0, ~AVIVO_D1CURSOR_EN); + } else { + switch(radeon_crtc->crtc_id) { + case 0: + RADEON_WRITE(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); + break; + case 1: + RADEON_WRITE(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); + break; + default: + return; + } + RADEON_WRITE_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN); + } +} + +static void radeon_show_cursor(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_radeon_private *dev_priv = crtc->dev->dev_private; + + if (radeon_is_avivo(dev_priv)) { + RADEON_WRITE(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); + RADEON_WRITE(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | + (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); + } else { + switch(radeon_crtc->crtc_id) { + case 0: + RADEON_WRITE(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); + break; + case 1: + RADEON_WRITE(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); + break; + default: + return; + } + + RADEON_WRITE_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN | + (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)), + ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); + } +} + +static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, + uint32_t width, uint32_t height) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_radeon_private *dev_priv = crtc->dev->dev_private; + struct drm_radeon_gem_object *obj_priv; + + obj_priv = obj->driver_private; + + if (radeon_is_avivo(dev_priv)) { + RADEON_WRITE(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + dev_priv->fb_location + obj_priv->bo->offset); + RADEON_WRITE(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, + (width - 1) << 16 | (height - 1)); + } else { + switch(radeon_crtc->crtc_id) { + case 0: + /* offset is from DISP_BASE_ADDRESS */ + RADEON_WRITE(RADEON_CUR_OFFSET, obj_priv->bo->offset); + break; + case 1: + /* offset is from DISP2_BASE_ADDRESS */ + RADEON_WRITE(RADEON_CUR2_OFFSET, obj_priv->bo->offset); + break; + default: + break; + } + } +} + +int radeon_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_gem_object *obj; + + if (!handle) { + /* turn off cursor */ + radeon_hide_cursor(crtc); + return 0; + } + + obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); + if (!obj) { + DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); + return -EINVAL; + } + + if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { + DRM_ERROR("bad cursor width or height %d x %d\n", width, height); + return -EINVAL; + } + + radeon_lock_cursor(crtc, true); + // XXX only 27 bit offset for legacy cursor + radeon_set_cursor(crtc, obj, width, height); + radeon_show_cursor(crtc); + radeon_lock_cursor(crtc, false); + + mutex_lock(&crtc->dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&crtc->dev->struct_mutex); + + return 0; +} + +int radeon_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_radeon_private *dev_priv = crtc->dev->dev_private; + int xorigin = 0, yorigin = 0; + + if (x < 0) + xorigin = -x + 1; + if (y < 0) + yorigin = -x + 1; + if (xorigin >= CURSOR_WIDTH) + xorigin = CURSOR_WIDTH - 1; + if (yorigin >= CURSOR_WIDTH) + yorigin = CURSOR_WIDTH - 1; + + radeon_lock_cursor(crtc, true); + if (radeon_is_avivo(dev_priv)) { + RADEON_WRITE(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, + ((xorigin ? 0: x) << 16) | + (yorigin ? 0 : y)); + RADEON_WRITE(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); + } else { + if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) + y /= 2; + else if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) + y *= 2; + + switch(radeon_crtc->crtc_id) { + case 0: + RADEON_WRITE(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK + | (xorigin << 16) + | yorigin)); + RADEON_WRITE(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK + | ((xorigin ? 0 : x) << 16) + | (yorigin ? 0 : y))); + break; + case 1: + RADEON_WRITE(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK + | (xorigin << 16) + | yorigin)); + RADEON_WRITE(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK + | ((xorigin ? 0 : x) << 16) + | (yorigin ? 0 : y))); + break; + default: + break; + } + + } + radeon_lock_cursor(crtc, false); + + return 0; +} + diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index 95258efa..39eb91eb 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -32,9 +32,6 @@ #include "drm_crtc_helper.h" -#define CURSOR_WIDTH 64 -#define CURSOR_HEIGHT 64 - int radeon_ddc_dump(struct drm_connector *connector); @@ -124,96 +121,6 @@ void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, radeon_crtc->lut_b[regno] = blue >> 8; } - - -static void avivo_lock_cursor(struct drm_crtc *crtc, bool lock) -{ - struct drm_radeon_private *dev_priv = crtc->dev->dev_private; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - - uint32_t tmp; - - tmp = RADEON_READ(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); - if (lock) - tmp |= AVIVO_D1CURSOR_UPDATE_LOCK; - else - tmp &= ~AVIVO_D1CURSOR_UPDATE_LOCK; - - RADEON_WRITE(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, tmp); -} - -static int radeon_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, - uint32_t height) -{ - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_radeon_private *dev_priv = crtc->dev->dev_private; - struct drm_gem_object *obj; - struct drm_radeon_gem_object *obj_priv; - - if (!handle) { - RADEON_WRITE(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0); - return 0; - /* turn off cursor */ - } - - obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); - if (!obj) { - DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); - return -EINVAL; - } - - obj_priv = obj->driver_private; - - RADEON_WRITE(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0); - if (radeon_is_avivo(dev_priv)) { - RADEON_WRITE(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, - dev_priv->fb_location + obj_priv->bo->offset); - RADEON_WRITE(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, - (CURSOR_WIDTH - 1) << 16 | (CURSOR_HEIGHT - 1)); - RADEON_WRITE(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, - AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); - } - - mutex_lock(&crtc->dev->struct_mutex); - drm_gem_object_unreference(obj); - mutex_unlock(&crtc->dev->struct_mutex); - - return 0; -} - -static int radeon_crtc_cursor_move(struct drm_crtc *crtc, - int x, int y) -{ - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_radeon_private *dev_priv = crtc->dev->dev_private; - int xorigin = 0, yorigin = 0; - - if (x < 0) xorigin = -x+1; - if (y < 0) yorigin = -x+1; - if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; - if (yorigin >= CURSOR_WIDTH) yorigin = CURSOR_WIDTH - 1; - - if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) - y /= 2; - else if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) - y *= 2; - - if (radeon_is_avivo(dev_priv)) { - avivo_lock_cursor(crtc, true); - - RADEON_WRITE(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, - ((xorigin ? 0: x) << 16) | - (yorigin ? 0 : y)); - RADEON_WRITE(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); - avivo_lock_cursor(crtc, false); - } - - return 0; -} - static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size) { diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h index 3e0ffc66..6a2e275c 100644 --- a/linux-core/radeon_mode.h +++ b/linux-core/radeon_mode.h @@ -393,6 +393,15 @@ extern void atombios_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode, int x, int y); extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); + +extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height); +extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y); + extern bool radeon_atom_get_clock_info(struct drm_device *dev); extern bool radeon_combios_get_clock_info(struct drm_device *dev); extern void radeon_get_lvds_info(struct radeon_encoder *encoder); diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index 887b2f84..ad91e04c 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -374,6 +374,9 @@ # define RADEON_CRTC_ICON_EN (1 << 15) # define RADEON_CRTC_CUR_EN (1 << 16) # define RADEON_CRTC_CUR_MODE_MASK (7 << 20) +# define RADEON_CRTC_CUR_MODE_SHIFT 20 +# define RADEON_CRTC_CUR_MODE_MONO 0 +# define RADEON_CRTC_CUR_MODE_24BPP 2 # define RADEON_CRTC_EXT_DISP_EN (1 << 24) # define RADEON_CRTC_EN (1 << 25) # define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) @@ -3591,14 +3594,14 @@ #define AVIVO_D1GRPH_X_END 0x6134 #define AVIVO_D1GRPH_Y_END 0x6138 #define AVIVO_D1GRPH_UPDATE 0x6144 -# define AVIVO_D1GRPH_UPDATE_LOCK (1<<16) +# define AVIVO_D1GRPH_UPDATE_LOCK (1 << 16) #define AVIVO_D1GRPH_FLIP_CONTROL 0x6148 #define AVIVO_D1CUR_CONTROL 0x6400 -# define AVIVO_D1CURSOR_EN (1<<0) -# define AVIVO_D1CURSOR_MODE_SHIFT 8 -# define AVIVO_D1CURSOR_MODE_MASK (0x3<<8) -# define AVIVO_D1CURSOR_MODE_24BPP (0x2) +# define AVIVO_D1CURSOR_EN (1 << 0) +# define AVIVO_D1CURSOR_MODE_SHIFT 8 +# define AVIVO_D1CURSOR_MODE_MASK (3 << 8) +# define AVIVO_D1CURSOR_MODE_24BPP 2 #define AVIVO_D1CUR_SURFACE_ADDRESS 0x6408 #define AVIVO_D1CUR_SIZE 0x6410 #define AVIVO_D1CUR_POSITION 0x6414 From ae89ced7ded55c164c620ebbd799fdb44ed9c09f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Aug 2008 02:11:44 -0400 Subject: [PATCH 43/49] Convert COM BIOS to table offset lookup function --- linux-core/radeon_combios.c | 635 +++++++++++++++++++++++++++++------- 1 file changed, 515 insertions(+), 120 deletions(-) diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c index 3b01385c..c293cd71 100644 --- a/linux-core/radeon_combios.c +++ b/linux-core/radeon_combios.c @@ -30,6 +30,57 @@ /* old legacy ATI BIOS routines */ +/* COMBIOS table offsets */ +enum radeon_combios_table_offset +{ + /* absolute offset tables */ + COMBIOS_ASIC_INIT_1_TABLE, + COMBIOS_BIOS_SUPPORT_TABLE, + COMBIOS_DAC_PROGRAMMING_TABLE, + COMBIOS_MAX_COLOR_DEPTH_TABLE, + COMBIOS_CRTC_INFO_TABLE, + COMBIOS_PLL_INFO_TABLE, + COMBIOS_TV_INFO_TABLE, + COMBIOS_DFP_INFO_TABLE, + COMBIOS_HW_CONFIG_INFO_TABLE, + COMBIOS_MULTIMEDIA_INFO_TABLE, + COMBIOS_TV_STD_PATCH_TABLE, + COMBIOS_LCD_INFO_TABLE, + COMBIOS_MOBILE_INFO_TABLE, + COMBIOS_PLL_INIT_TABLE, + COMBIOS_MEM_CONFIG_TABLE, + COMBIOS_SAVE_MASK_TABLE, + COMBIOS_HARDCODED_EDID_TABLE, + COMBIOS_ASIC_INIT_2_TABLE, + COMBIOS_CONNECTOR_INFO_TABLE, + COMBIOS_DYN_CLK_1_TABLE, + COMBIOS_RESERVED_MEM_TABLE, + COMBIOS_EXT_TDMS_INFO_TABLE, + COMBIOS_MEM_CLK_INFO_TABLE, + COMBIOS_EXT_DAC_INFO_TABLE, + COMBIOS_MISC_INFO_TABLE, + COMBIOS_CRT_INFO_TABLE, + COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE, + COMBIOS_COMPONENT_VIDEO_INFO_TABLE, + COMBIOS_FAN_SPEED_INFO_TABLE, + COMBIOS_OVERDRIVE_INFO_TABLE, + COMBIOS_OEM_INFO_TABLE, + COMBIOS_DYN_CLK_2_TABLE, + COMBIOS_POWER_CONNECTOR_INFO_TABLE, + COMBIOS_I2C_INFO_TABLE, + /* relative offset tables */ + COMBIOS_ASIC_INIT_3_TABLE, /* offset from misc info */ + COMBIOS_ASIC_INIT_4_TABLE, /* offset from misc info */ + COMBIOS_ASIC_INIT_5_TABLE, /* offset from misc info */ + COMBIOS_RAM_RESET_TABLE, /* offset from mem config */ + COMBIOS_POWERPLAY_TABLE, /* offset from mobile info */ + COMBIOS_GPIO_INFO_TABLE, /* offset from mobile info */ + COMBIOS_LCD_DDC_INFO_TABLE, /* offset from mobile info */ + COMBIOS_TMDS_POWER_TABLE, /* offset from mobile info */ + COMBIOS_TMDS_POWER_ON_TABLE, /* offset from tmds power */ + COMBIOS_TMDS_POWER_OFF_TABLE, /* offset from tmds power */ +}; + enum radeon_combios_ddc { DDC_NONE_DETECTED, @@ -53,6 +104,283 @@ enum radeon_combios_connector CONNECTOR_UNSUPPORTED_LEGACY }; +static uint16_t combios_get_table_offset(struct drm_device *dev, enum radeon_combios_table_offset table) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + int rev; + uint16_t offset = 0, check_offset; + + switch (table) { + /* absolute offset tables */ + case COMBIOS_ASIC_INIT_1_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0xc); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_BIOS_SUPPORT_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x14); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DAC_PROGRAMMING_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x2a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MAX_COLOR_DEPTH_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x2c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_CRTC_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x2e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_PLL_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x30); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_TV_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x32); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DFP_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x34); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_HW_CONFIG_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x36); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MULTIMEDIA_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x38); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_TV_STD_PATCH_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x3e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_LCD_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x40); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MOBILE_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x42); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_PLL_INIT_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x46); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MEM_CONFIG_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x48); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_SAVE_MASK_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x4a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_HARDCODED_EDID_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x4c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_ASIC_INIT_2_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x4e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_CONNECTOR_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x50); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DYN_CLK_1_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x52); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_RESERVED_MEM_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x54); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_EXT_TDMS_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x58); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MEM_CLK_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x5a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_EXT_DAC_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x5c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_MISC_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x5e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_CRT_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x60); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x62); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_COMPONENT_VIDEO_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x64); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_FAN_SPEED_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x66); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_OVERDRIVE_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x68); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_OEM_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x6a); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_DYN_CLK_2_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x6c); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_POWER_CONNECTOR_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x6e); + if (check_offset) + offset = check_offset; + break; + case COMBIOS_I2C_INFO_TABLE: + check_offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x70); + if (check_offset) + offset = check_offset; + break; + /* relative offset tables */ + case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = radeon_bios8(dev_priv, check_offset); + if (rev > 0) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x3); + if (check_offset) + offset = check_offset; + } + } + break; + case COMBIOS_ASIC_INIT_4_TABLE: /* offset from misc info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = radeon_bios8(dev_priv, check_offset); + if (rev > 0) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x5); + if (check_offset) + offset = check_offset; + } + } + break; + case COMBIOS_ASIC_INIT_5_TABLE: /* offset from misc info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = radeon_bios8(dev_priv, check_offset); + if (rev == 2) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x9); + if (check_offset) + offset = check_offset; + } + } + break; + case COMBIOS_RAM_RESET_TABLE: /* offset from mem config */ + check_offset = combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE); + if (check_offset) { + while (radeon_bios8(dev_priv, check_offset++)); + check_offset += 2; + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_POWERPLAY_TABLE: /* offset from mobile info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x11); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_GPIO_INFO_TABLE: /* offset from mobile info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x13); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_LCD_DDC_INFO_TABLE: /* offset from mobile info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x15); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_TMDS_POWER_TABLE: /* offset from mobile info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); + if (check_offset) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x17); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_TMDS_POWER_ON_TABLE: /* offset from tmds power */ + check_offset = combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE); + if (check_offset) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x2); + if (check_offset) + offset = check_offset; + } + break; + case COMBIOS_TMDS_POWER_OFF_TABLE: /* offset from tmds power */ + check_offset = combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE); + if (check_offset) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x4); + if (check_offset) + offset = check_offset; + } + break; + default: + break; + } + + return offset; + +} + struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line) { struct radeon_i2c_bus_rec i2c; @@ -98,125 +426,130 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) { struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_mode_info *mode_info = &dev_priv->mode_info; - uint16_t pll_info_block; + uint16_t pll_info; struct radeon_pll *pll = &mode_info->pll; int rev; - pll_info_block = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x30); - rev = radeon_bios8(dev_priv, pll_info_block); + pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE); + if (pll_info) { + rev = radeon_bios8(dev_priv, pll_info); - pll->reference_freq = radeon_bios16(dev_priv, pll_info_block + 0xe); - pll->reference_div = radeon_bios16(dev_priv, pll_info_block + 0x10); - pll->pll_out_min = radeon_bios32(dev_priv, pll_info_block + 0x12); - pll->pll_out_max = radeon_bios32(dev_priv, pll_info_block + 0x16); + pll->reference_freq = radeon_bios16(dev_priv, pll_info + 0xe); + pll->reference_div = radeon_bios16(dev_priv, pll_info + 0x10); + pll->pll_out_min = radeon_bios32(dev_priv, pll_info + 0x12); + pll->pll_out_max = radeon_bios32(dev_priv, pll_info + 0x16); - if (rev > 9) { - pll->pll_in_min = radeon_bios32(dev_priv, pll_info_block + 0x36); - pll->pll_in_max = radeon_bios32(dev_priv, pll_info_block + 0x3a); - } else { - pll->pll_in_min = 40; - pll->pll_in_max = 500; + if (rev > 9) { + pll->pll_in_min = radeon_bios32(dev_priv, pll_info + 0x36); + pll->pll_in_max = radeon_bios32(dev_priv, pll_info + 0x3a); + } else { + pll->pll_in_min = 40; + pll->pll_in_max = 500; + } + + pll->xclk = radeon_bios16(dev_priv, pll_info + 0x08); + + // sclk/mclk use fixed point + + return true; } - - pll->xclk = radeon_bios16(dev_priv, pll_info_block + 0x08); - - // sclk/mclk use fixed point - - return true; - + return false; } bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_radeon_private *dev_priv = dev->dev_private; - uint16_t tmp; + uint16_t lcd_info; char stmp[30]; - int tmp0; - int i; + int tmp, i; - tmp = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x40); - if (!tmp) { - DRM_INFO("No panel info found in BIOS\n"); - return false; + lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); - } + if (lcd_info) { + for (i = 0; i < 24; i++) + stmp[i] = radeon_bios8(dev_priv, lcd_info + i + 1); + stmp[24] = 0; - for (i = 0; i < 24; i++) - stmp[i] = radeon_bios8(dev_priv, tmp + i + 1); - stmp[24] = 0; + DRM_INFO("Panel ID String: %s\n", stmp); - DRM_INFO("Panel ID String: %s\n", stmp); + encoder->panel_xres = radeon_bios16(dev_priv, lcd_info + 25); + encoder->panel_yres = radeon_bios16(dev_priv, lcd_info + 27); - encoder->panel_xres = radeon_bios16(dev_priv, tmp + 25); - encoder->panel_yres = radeon_bios16(dev_priv, tmp + 27); + DRM_INFO("Panel Size %dx%d\n", encoder->panel_xres, encoder->panel_yres); - DRM_INFO("Panel Size %dx%d\n", encoder->panel_xres, encoder->panel_yres); + encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 44); + if (encoder->panel_pwr_delay > 2000 || encoder->panel_pwr_delay < 0) + encoder->panel_pwr_delay = 2000; - encoder->panel_pwr_delay = radeon_bios16(dev_priv, tmp + 44); - if (encoder->panel_pwr_delay > 2000 || encoder->panel_pwr_delay < 0) - encoder->panel_pwr_delay = 2000; + for (i = 0; i < 32; i++) { + tmp = radeon_bios16(dev_priv, lcd_info + 64 + i * 2); + if (tmp == 0) break; - for (i = 0; i < 32; i++) { - tmp0 = radeon_bios16(dev_priv, tmp + 64 + i * 2); - if (tmp0 == 0) break; + if ((radeon_bios16(dev_priv, tmp) == encoder->panel_xres) && + (radeon_bios16(dev_priv, tmp + 2) == encoder->panel_yres)) { + encoder->hblank = (radeon_bios16(dev_priv, tmp + 17) - + radeon_bios16(dev_priv, tmp + 19)) * 8; + encoder->hoverplus = (radeon_bios16(dev_priv, tmp + 21) - + radeon_bios16(dev_priv, tmp + 19) - 1) * 8; + encoder->hsync_width = radeon_bios8(dev_priv, tmp + 23) * 8; - if ((radeon_bios16(dev_priv, tmp0) == encoder->panel_xres) && - (radeon_bios16(dev_priv, tmp0 + 2) == encoder->panel_yres)) { - encoder->hblank = (radeon_bios16(dev_priv, tmp0 + 17) - - radeon_bios16(dev_priv, tmp0 + 19)) * 8; - encoder->hoverplus = (radeon_bios16(dev_priv, tmp0 + 21) - - radeon_bios16(dev_priv, tmp0 + 19) - 1) * 8; - encoder->hsync_width = radeon_bios8(dev_priv, tmp0 + 23) * 8; - - encoder->vblank = (radeon_bios16(dev_priv, tmp0 + 24) - - radeon_bios16(dev_priv, tmp0 + 26)); - encoder->voverplus = ((radeon_bios16(dev_priv, tmp0 + 28) & 0x7fff) - - radeon_bios16(dev_priv, tmp0 + 26)); - encoder->vsync_width = ((radeon_bios16(dev_priv, tmp0 + 28) & 0xf800) >> 11); - encoder->dotclock = radeon_bios16(dev_priv, tmp0 + 9) * 10; - encoder->flags = 0; + encoder->vblank = (radeon_bios16(dev_priv, tmp + 24) - + radeon_bios16(dev_priv, tmp + 26)); + encoder->voverplus = ((radeon_bios16(dev_priv, tmp + 28) & 0x7fff) - + radeon_bios16(dev_priv, tmp + 26)); + encoder->vsync_width = ((radeon_bios16(dev_priv, tmp + 28) & 0xf800) >> 11); + encoder->dotclock = radeon_bios16(dev_priv, tmp + 9) * 10; + encoder->flags = 0; + } } + return true; } - return true; + DRM_INFO("No panel info found in BIOS\n"); + return false; + } bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_radeon_private *dev_priv = dev->dev_private; - uint16_t tmp; + uint16_t tmds_info; int i, n; uint8_t ver; - tmp = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x34); - if (!tmp) { - DRM_INFO("No TMDS info found in BIOS\n"); - return false; + tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); + + if (tmds_info) { + ver = radeon_bios8(dev_priv, tmds_info); + DRM_INFO("DFP table revision: %d\n", ver); + if (ver == 3) { + n = radeon_bios8(dev_priv, tmds_info + 5) + 1; + if (n > 4) + n = 4; + for (i = 0; i < n; i++) { + encoder->tmds_pll[i].value = radeon_bios32(dev_priv, tmds_info + i * 10 + 0x08); + encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmds_info + i * 10 + 0x10); + } + return true; + } else if (ver == 4) { + int stride = 0; + n = radeon_bios8(dev_priv, tmds_info + 5) + 1; + if (n > 4) + n = 4; + for (i = 0; i < n; i++) { + encoder->tmds_pll[i].value = radeon_bios32(dev_priv, tmds_info + stride + 0x08); + encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmds_info + stride + 0x10); + if (i == 0) + stride += 10; + else + stride += 6; + } + return true; + } } - ver = radeon_bios8(dev_priv, tmp); - DRM_INFO("DFP table revision: %d\n", ver); - if (ver == 3) { - n = radeon_bios8(dev_priv, tmp + 5) + 1; - if (n > 4) n = 4; - for (i = 0; i < n; i++) { - encoder->tmds_pll[i].value = radeon_bios32(dev_priv, tmp+i*10+0x08); - encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmp+i*10+0x10); - } - return true; - } else if (ver == 4) { - int stride = 0; - n = radeon_bios8(dev_priv, tmp + 5) + 1; - if (n > 4) n = 4; - for (i = 0; i < n; i++) { - encoder->tmds_pll[i].value = radeon_bios32(dev_priv, tmp+stride+0x08); - encoder->tmds_pll[i].freq = radeon_bios16(dev_priv, tmp+stride+0x10); - if (i == 0) stride += 10; - else stride += 6; - } - return true; - } + DRM_INFO("No TMDS info found in BIOS\n"); return false; } @@ -262,17 +595,17 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) { struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_mode_info *mode_info = &dev_priv->mode_info; - uint32_t offset, entry; - uint16_t tmp0, tmp1, tmp; - enum radeon_combios_ddc ddctype; + uint32_t conn_info, entry; + uint16_t tmp; + enum radeon_combios_ddc ddc_type; enum radeon_combios_connector connector_type; int i; DRM_DEBUG("\n"); - offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x50); - if (offset) { + conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE); + if (conn_info) { for (i = 0; i < 4; i++) { - entry = offset + 2 + i * 2; + entry = conn_info + 2 + i * 2; if (!radeon_bios16(dev_priv, entry)) break; @@ -311,8 +644,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) mode_info->bios_connector[i].ddc_i2c.valid = false; - ddctype = (tmp >> 8) & 0xf; - switch (ddctype) { + ddc_type = (tmp >> 8) & 0xf; + switch (ddc_type) { case DDC_MONID: mode_info->bios_connector[i].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID); break; @@ -347,9 +680,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) radeon_apply_legacy_quirks(dev, i); } } else { - DRM_INFO("no connector table found in BIOS\n"); - offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x34); - if (offset) { + uint16_t tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); + if (tmds_info) { DRM_DEBUG("Found DFP table, assuming DVI connector\n"); mode_info->bios_connector[0].valid = true; @@ -358,45 +690,108 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) mode_info->bios_connector[0].tmds_type = TMDS_INT; mode_info->bios_connector[0].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); } else { - DRM_DEBUG("No table found\n"); + DRM_DEBUG("No connector info found\n"); return false; } } - if (dev_priv->flags & RADEON_IS_MOBILITY) { - offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x40); - if (offset) { + if (dev_priv->flags & RADEON_IS_MOBILITY || + dev_priv->chip_family == CHIP_RS400 || + dev_priv->chip_family == CHIP_RS480) { + uint16_t lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); + if (lcd_info) { + uint16_t lcd_ddc_info = lcd_ddc_info = combios_get_table_offset(dev, COMBIOS_LCD_DDC_INFO_TABLE); + mode_info->bios_connector[4].valid = true; mode_info->bios_connector[4].connector_type = CONNECTOR_LVDS; mode_info->bios_connector[4].dac_type = DAC_NONE; mode_info->bios_connector[4].tmds_type = TMDS_NONE; mode_info->bios_connector[4].ddc_i2c.valid = false; - tmp = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x42); - if (tmp) { - tmp0 = radeon_bios16(dev_priv, tmp + 0x15); - if (tmp0) { - tmp1 = radeon_bios8(dev_priv, tmp0 + 2) & 0x07; - if (tmp1) { - ddctype = tmp1; - - switch(ddctype) { - case DDC_MONID: - case DDC_DVI: - case DDC_CRT2: - case DDC_LCD: - case DDC_GPIO: - default: - break; - } - DRM_DEBUG("LCD DDC Info Table found!\n"); - } + if (lcd_ddc_info) { + ddc_type = radeon_bios8(dev_priv, lcd_ddc_info + 2); + switch(ddc_type) { + case DDC_MONID: + mode_info->bios_connector[4].ddc_i2c = + combios_setup_i2c_bus(RADEON_GPIO_MONID); + break; + case DDC_DVI: + mode_info->bios_connector[4].ddc_i2c = + combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); + break; + case DDC_VGA: + mode_info->bios_connector[4].ddc_i2c = + combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); + break; + case DDC_CRT2: + mode_info->bios_connector[4].ddc_i2c = + combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); + break; + case DDC_LCD: + mode_info->bios_connector[4].ddc_i2c = + combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK); + mode_info->bios_connector[4].ddc_i2c.mask_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.mask_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + mode_info->bios_connector[4].ddc_i2c.a_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.a_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + mode_info->bios_connector[4].ddc_i2c.put_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.put_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + mode_info->bios_connector[4].ddc_i2c.get_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.get_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + break; + case DDC_GPIO: + mode_info->bios_connector[4].ddc_i2c = + combios_setup_i2c_bus(RADEON_MDGPIO_EN_REG); + mode_info->bios_connector[4].ddc_i2c.mask_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.mask_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + mode_info->bios_connector[4].ddc_i2c.a_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.a_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + mode_info->bios_connector[4].ddc_i2c.put_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.put_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + mode_info->bios_connector[4].ddc_i2c.get_clk_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 3); + mode_info->bios_connector[4].ddc_i2c.get_data_mask = + radeon_bios32(dev_priv, lcd_ddc_info + 7); + break; + default: + break; } - } else - mode_info->bios_connector[4].ddc_i2c.valid = false; + DRM_DEBUG("LCD DDC Info Table found!\n"); + } + } else + mode_info->bios_connector[4].ddc_i2c.valid = false; + } + + /* check TV table */ + if (dev_priv->chip_family != CHIP_R100 && + dev_priv->chip_family != CHIP_R200) { + uint32_t tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); + if (tv_info) { + if (radeon_bios8(dev_priv, tv_info + 6) == 'T') { + mode_info->bios_connector[5].valid = true; + mode_info->bios_connector[5].connector_type = CONNECTOR_DIN; + mode_info->bios_connector[5].dac_type = DAC_TVDAC; + mode_info->bios_connector[5].tmds_type = TMDS_NONE; + mode_info->bios_connector[5].ddc_i2c.valid = false; + } } } + DRM_DEBUG("BIOS Connector table\n"); for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { if (!mode_info->bios_connector[i].valid) From 8867eca8721a02135f4b0e65a454d5e05141eee3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Aug 2008 03:05:11 -0400 Subject: [PATCH 44/49] set base in legacy crtc mode set --- linux-core/radeon_legacy_crtc.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index 6446f8cb..7f7ce617 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -917,6 +917,21 @@ static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, return true; } +void radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + switch(radeon_crtc->crtc_id) { + case 0: + radeon_set_crtc1_base(crtc, x, y); + break; + case 1: + radeon_set_crtc2_base(crtc, x, y); + break; + + } +} + static void radeon_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -942,6 +957,8 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, /* TODO TV */ + radeon_crtc_set_base(crtc, x, y); + switch(radeon_crtc->crtc_id) { case 0: radeon_set_crtc1_timing(crtc, adjusted_mode); @@ -955,21 +972,6 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, } } -void radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y) -{ - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - - switch(radeon_crtc->crtc_id) { - case 0: - radeon_set_crtc1_base(crtc, x, y); - break; - case 1: - radeon_set_crtc2_base(crtc, x, y); - break; - - } -} - static void radeon_crtc_prepare(struct drm_crtc *crtc) { radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); From b486ed7f7d89528c94f2345040324946f6eadc81 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Aug 2008 13:52:35 -0400 Subject: [PATCH 45/49] Get legacy working finally - extra ~ in RADEON_WRITE_P() - re-arrange crtc setup a bit - add debugging for tracing calls - fix pitch calculation --- linux-core/radeon_legacy_crtc.c | 74 ++++++++++++++++++----------- linux-core/radeon_legacy_encoders.c | 38 ++++++++++++++- shared-core/radeon_drv.h | 2 +- 3 files changed, 83 insertions(+), 31 deletions(-) diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index 7f7ce617..6dea4d41 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -123,42 +123,43 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; - uint32_t mask; + DRM_DEBUG("\n"); + mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS); switch(mode) { case DRM_MODE_DPMS_ON: - if (radeon_crtc->crtc_id) { + if (radeon_crtc->crtc_id) RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, 0, ~mask); - } else { + else { RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); } break; case DRM_MODE_DPMS_STANDBY: - if (radeon_crtc->crtc_id) { + if (radeon_crtc->crtc_id) RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask); - } else { + else { RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask); } break; case DRM_MODE_DPMS_SUSPEND: - if (radeon_crtc->crtc_id) { + if (radeon_crtc->crtc_id) RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask); - } else { + else { RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask); } break; case DRM_MODE_DPMS_OFF: - if (radeon_crtc->crtc_id) { + if (radeon_crtc->crtc_id) RADEON_WRITE_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask); - } else { + else { RADEON_WRITE_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B); RADEON_WRITE_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); } @@ -179,6 +180,9 @@ static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y) struct drm_radeon_gem_object *obj_priv; uint32_t base; uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; + uint32_t crtc_pitch; + + DRM_DEBUG("\n"); radeon_fb = to_radeon_framebuffer(crtc->fb); @@ -243,11 +247,20 @@ static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y) crtc_offset = base; + crtc_pitch = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) + + ((crtc->fb->bits_per_pixel * 8) - 1)) / + (crtc->fb->bits_per_pixel * 8)); + crtc_pitch |= crtc_pitch << 16; + + DRM_DEBUG("mc_fb_location: 0x%x\n", dev_priv->fb_location); + + RADEON_WRITE(RADEON_DISPLAY_BASE_ADDR, dev_priv->fb_location); + if (radeon_is_r300(dev_priv)) RADEON_WRITE(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0); - RADEON_WRITE(RADEON_CRTC_OFFSET_CNTL, crtc_offset_cntl); RADEON_WRITE(RADEON_CRTC_OFFSET, crtc_offset); + RADEON_WRITE(RADEON_CRTC_PITCH, crtc_pitch); return true; } @@ -267,10 +280,11 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo uint32_t crtc_h_sync_strt_wid; uint32_t crtc_v_total_disp; uint32_t crtc_v_sync_strt_wid; - uint32_t crtc_pitch; uint32_t disp_merge_cntl; - switch (crtc->fb->depth) { + DRM_DEBUG("\n"); + + switch (crtc->fb->bits_per_pixel) { case 15: /* 555 */ format = 3; @@ -302,7 +316,7 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo : 0)); crtc_ext_cntl = RADEON_READ(RADEON_CRTC_EXT_CNTL); - crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| + crtc_ext_cntl |= (RADEON_XCRT_CNT_EN | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_DISPLAY_DIS); @@ -338,11 +352,6 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo ? RADEON_CRTC_V_SYNC_POL : 0)); - crtc_pitch = (((crtc->fb->pitch * crtc->fb->bits_per_pixel) + - ((crtc->fb->bits_per_pixel * 8) -1)) / - (crtc->fb->bits_per_pixel * 8)); - crtc_pitch |= crtc_pitch << 16; - /* TODO -> Dell Server */ if (0) { uint32_t disp_hw_debug = RADEON_READ(RADEON_DISP_HW_DEBUG); @@ -381,7 +390,6 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo RADEON_WRITE(RADEON_CRTC_V_TOTAL_DISP, crtc_v_total_disp); RADEON_WRITE(RADEON_CRTC_V_SYNC_STRT_WID, crtc_v_sync_strt_wid); - RADEON_WRITE(RADEON_CRTC_PITCH, crtc_pitch); RADEON_WRITE(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); RADEON_WRITE(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); @@ -569,7 +577,7 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode RADEON_VCLK_SRC_SEL_PPLLCLK, ~(RADEON_VCLK_SRC_SEL_MASK)); - /*RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, state->vclk_ecp_cntl);*/ + /*RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);*/ } @@ -580,8 +588,11 @@ static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y) struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_framebuffer *radeon_fb; struct drm_radeon_gem_object *obj_priv; - uint32_t crtc2_offset, crtc2_offset_cntl, crtc2_tile_x0_y0 = 0; uint32_t base; + uint32_t crtc2_offset, crtc2_offset_cntl, crtc2_tile_x0_y0 = 0; + uint32_t crtc2_pitch; + + DRM_DEBUG("\n"); radeon_fb = to_radeon_framebuffer(crtc->fb); @@ -646,10 +657,18 @@ static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y) crtc2_offset = base; + crtc2_pitch = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) + + ((crtc->fb->bits_per_pixel * 8) - 1)) / + (crtc->fb->bits_per_pixel * 8)); + crtc2_pitch |= crtc2_pitch << 16; + + RADEON_WRITE(RADEON_DISPLAY2_BASE_ADDR, dev_priv->fb_location); + if (radeon_is_r300(dev_priv)) RADEON_WRITE(R300_CRTC2_TILE_X0_Y0, crtc2_tile_x0_y0); RADEON_WRITE(RADEON_CRTC2_OFFSET_CNTL, crtc2_offset_cntl); RADEON_WRITE(RADEON_CRTC2_OFFSET, crtc2_offset); + RADEON_WRITE(RADEON_CRTC2_PITCH, crtc2_pitch); return true; } @@ -668,12 +687,13 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo uint32_t crtc2_h_sync_strt_wid; uint32_t crtc2_v_total_disp; uint32_t crtc2_v_sync_strt_wid; - uint32_t crtc2_pitch; uint32_t disp2_merge_cntl; uint32_t fp_h2_sync_strt_wid; uint32_t fp_v2_sync_strt_wid; - switch (crtc->fb->depth) { + DRM_DEBUG("\n"); + + switch (crtc->fb->bits_per_pixel) { case 15: /* 555 */ format = 3; @@ -720,11 +740,6 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo ? RADEON_CRTC2_V_SYNC_POL : 0)); - crtc2_pitch = (((crtc->fb->pitch * crtc->fb->bits_per_pixel) + - ((crtc->fb->bits_per_pixel * 8) -1)) / - (crtc->fb->bits_per_pixel * 8)); - crtc2_pitch |= crtc2_pitch << 16; - /* check to see if TV DAC is enabled for another crtc and keep it enabled */ if (RADEON_READ(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON) crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; @@ -765,7 +780,6 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo RADEON_WRITE(RADEON_FP_H2_SYNC_STRT_WID, fp_h2_sync_strt_wid); RADEON_WRITE(RADEON_FP_V2_SYNC_STRT_WID, fp_v2_sync_strt_wid); - RADEON_WRITE(RADEON_CRTC2_PITCH, crtc2_pitch); RADEON_WRITE(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl); RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); @@ -944,6 +958,8 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; int i; + DRM_DEBUG("\n"); + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c index 46cf791e..998a9f73 100644 --- a/linux-core/radeon_legacy_encoders.c +++ b/linux-core/radeon_legacy_encoders.c @@ -47,6 +47,7 @@ static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder, uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active; uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp; + DRM_DEBUG("\n"); fp_vert_stretch = RADEON_READ(RADEON_FP_VERT_STRETCH) & (RADEON_VERT_STRETCH_RESERVED | @@ -199,7 +200,9 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man; - switch(mode) { + DRM_DEBUG("\n"); + + switch (mode) { case DRM_MODE_DPMS_ON: disp_pwr_man = RADEON_READ(RADEON_DISP_PWR_MAN); disp_pwr_man |= RADEON_AUTO_PWRUP_EN; @@ -250,6 +253,8 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t lvds_pll_cntl, lvds_gen_cntl; + DRM_DEBUG("\n"); + if (radeon_crtc->crtc_id == 0) radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); @@ -319,6 +324,9 @@ struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int b struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; + + DRM_DEBUG("\n"); + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); if (!radeon_encoder) { return NULL; @@ -358,6 +366,8 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode uint32_t dac_cntl = RADEON_READ(RADEON_DAC_CNTL); uint32_t dac_macro_cntl = RADEON_READ(RADEON_DAC_MACRO_CNTL); + DRM_DEBUG("\n"); + switch(mode) { case DRM_MODE_DPMS_ON: crtc_ext_cntl |= RADEON_CRTC_CRT_ON; @@ -402,6 +412,8 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl; + DRM_DEBUG("\n"); + if (radeon_crtc->crtc_id == 0) radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); @@ -470,6 +482,9 @@ struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; + + DRM_DEBUG("\n"); + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); if (!radeon_encoder) { return NULL; @@ -504,6 +519,8 @@ static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode) struct drm_radeon_private *dev_priv = dev->dev_private; uint32_t fp_gen_cntl = RADEON_READ(RADEON_FP_GEN_CNTL); + DRM_DEBUG("\n"); + switch(mode) { case DRM_MODE_DPMS_ON: fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); @@ -539,6 +556,8 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl; int i; + DRM_DEBUG("\n"); + if (radeon_crtc->crtc_id == 0) radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); @@ -631,6 +650,9 @@ struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, i struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; + + DRM_DEBUG("\n"); + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); if (!radeon_encoder) { return NULL; @@ -662,6 +684,8 @@ static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode) struct drm_radeon_private *dev_priv = dev->dev_private; uint32_t fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL); + DRM_DEBUG("\n"); + switch(mode) { case DRM_MODE_DPMS_ON: fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; @@ -698,6 +722,8 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL); + DRM_DEBUG("\n"); + if (radeon_crtc->crtc_id == 0) radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); @@ -762,6 +788,9 @@ struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, i struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; + + DRM_DEBUG("\n"); + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); if (!radeon_encoder) { return NULL; @@ -793,6 +822,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) struct drm_radeon_private *dev_priv = dev->dev_private; uint32_t fp2_gen_cntl, crtc2_gen_cntl, tv_master_cntl, tv_dac_cntl; + DRM_DEBUG("\n"); + if (dev_priv->chip_family == CHIP_R200) fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL); else { @@ -876,6 +907,8 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, uint32_t tv_dac_cntl, gpiopad_a, dac2_cntl, disp_output_cntl, fp2_gen_cntl; uint32_t disp_hw_debug; + DRM_DEBUG("\n"); + if (radeon_crtc->crtc_id == 0) radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); @@ -981,6 +1014,9 @@ struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; + + DRM_DEBUG("\n"); + radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); if (!radeon_encoder) { return NULL; diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index fb266093..2b8d7f6e 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -1283,7 +1283,7 @@ extern void RADEON_WRITE_PLL(struct drm_radeon_private *dev_priv, int addr, uint #define RADEON_WRITE_P(reg, val, mask) \ do { \ uint32_t tmp = RADEON_READ(reg); \ - tmp &= ~(mask); \ + tmp &= (mask); \ tmp |= ((val) & ~(mask)); \ RADEON_WRITE(reg, tmp); \ } while(0) From a1f12024702d0636ead0ef512fd0372d6d1aa79f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Aug 2008 14:07:33 -0400 Subject: [PATCH 46/49] Fix warnings --- linux-core/radeon_legacy_crtc.c | 9 -------- linux-core/radeon_legacy_encoders.c | 34 ++++++++--------------------- 2 files changed, 9 insertions(+), 34 deletions(-) diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index 6dea4d41..08d4a477 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -173,7 +173,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_framebuffer *radeon_fb; @@ -267,7 +266,6 @@ static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y) static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; int format; @@ -399,7 +397,6 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; uint32_t feedback_div = 0; @@ -583,7 +580,6 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_framebuffer *radeon_fb; @@ -675,7 +671,6 @@ static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y) static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; int format; @@ -790,7 +785,6 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; uint32_t feedback_div = 0; @@ -953,15 +947,12 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; - struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_encoder *encoder; int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; - int i; DRM_DEBUG("\n"); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); if (encoder->crtc == crtc) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c index 998a9f73..de9e8ac6 100644 --- a/linux-core/radeon_legacy_encoders.c +++ b/linux-core/radeon_legacy_encoders.c @@ -35,7 +35,6 @@ static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder, { struct drm_device *dev = encoder->dev; struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); int xres = mode->hdisplay; int yres = mode->vdisplay; @@ -207,6 +206,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) disp_pwr_man = RADEON_READ(RADEON_DISP_PWR_MAN); disp_pwr_man |= RADEON_AUTO_PWRUP_EN; RADEON_WRITE(RADEON_DISP_PWR_MAN, disp_pwr_man); + lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl |= RADEON_LVDS_PLL_EN; RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); udelay(1000); @@ -320,8 +320,6 @@ static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = { struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index) { - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; @@ -454,10 +452,7 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { - struct drm_device *dev = encoder->dev; - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - + // FIXME return connector_status_disconnected; } @@ -478,8 +473,6 @@ static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = { struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int has_tv) { - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; @@ -507,8 +500,8 @@ struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } @@ -646,8 +639,6 @@ static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = { struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index) { - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; @@ -784,8 +775,6 @@ static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = { struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index) { - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; @@ -820,7 +809,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; struct drm_radeon_private *dev_priv = dev->dev_private; - uint32_t fp2_gen_cntl, crtc2_gen_cntl, tv_master_cntl, tv_dac_cntl; + uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0; + //uint32_t tv_master_cntl = 0; DRM_DEBUG("\n"); @@ -903,9 +893,8 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - uint32_t tv_dac_cntl, gpiopad_a, dac2_cntl, disp_output_cntl, fp2_gen_cntl; - uint32_t disp_hw_debug; + uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0; + uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0; DRM_DEBUG("\n"); @@ -986,10 +975,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { - struct drm_device *dev = encoder->dev; - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - + // FIXME return connector_status_disconnected; } @@ -1010,8 +996,6 @@ static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = { struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int has_tv) { - struct drm_radeon_private *dev_priv = dev->dev_private; - struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_encoder *radeon_encoder; struct drm_encoder *encoder; From 9b79d356c171e86e529ad1a4e5e145a36d1af601 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Aug 2008 15:33:20 -0400 Subject: [PATCH 47/49] Add additional quirks from ddx --- linux-core/radeon_combios.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c index c293cd71..1080079f 100644 --- a/linux-core/radeon_combios.c +++ b/linux-core/radeon_combios.c @@ -558,16 +558,31 @@ static void radeon_apply_legacy_quirks(struct drm_device *dev, int bios_index) struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_mode_info *mode_info = &dev_priv->mode_info; - /* on XPRESS chips, CRT2_DDC and MONID_DCC both use the - * MONID gpio, but use different pins. - * CRT2_DDC uses the standard pinout, MONID_DDC uses - * something else. - */ + /* XPRESS DDC quirks */ if ((dev_priv->chip_family == CHIP_RS400 || dev_priv->chip_family == CHIP_RS480) && - mode_info->bios_connector[bios_index].connector_type == CONNECTOR_VGA && mode_info->bios_connector[bios_index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) { mode_info->bios_connector[bios_index].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID); + } else if ((dev_priv->chip_family == CHIP_RS400 || + dev_priv->chip_family == CHIP_RS480) && + mode_info->bios_connector[bios_index].ddc_i2c.mask_clk_reg == RADEON_GPIO_MONID) { + mode_info->bios_connector[bios_index].ddc_i2c.valid = true; + mode_info->bios_connector[bios_index].ddc_i2c.mask_clk_mask = (0x20 << 8); + mode_info->bios_connector[bios_index].ddc_i2c.mask_data_mask = 0x80; + mode_info->bios_connector[bios_index].ddc_i2c.a_clk_mask = (0x20 << 8); + mode_info->bios_connector[bios_index].ddc_i2c.a_data_mask = 0x80; + mode_info->bios_connector[bios_index].ddc_i2c.put_clk_mask = (0x20 << 8); + mode_info->bios_connector[bios_index].ddc_i2c.put_data_mask = 0x80; + mode_info->bios_connector[bios_index].ddc_i2c.get_clk_mask = (0x20 << 8); + mode_info->bios_connector[bios_index].ddc_i2c.get_data_mask = 0x80; + mode_info->bios_connector[bios_index].ddc_i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; + mode_info->bios_connector[bios_index].ddc_i2c.mask_data_reg = RADEON_GPIOPAD_MASK; + mode_info->bios_connector[bios_index].ddc_i2c.a_clk_reg = RADEON_GPIOPAD_A; + mode_info->bios_connector[bios_index].ddc_i2c.a_data_reg = RADEON_GPIOPAD_A; + mode_info->bios_connector[bios_index].ddc_i2c.put_clk_reg = RADEON_GPIOPAD_EN; + mode_info->bios_connector[bios_index].ddc_i2c.put_data_reg = RADEON_GPIOPAD_EN; + mode_info->bios_connector[bios_index].ddc_i2c.get_clk_reg = RADEON_LCD_GPIO_Y_REG; + mode_info->bios_connector[bios_index].ddc_i2c.get_data_reg = RADEON_LCD_GPIO_Y_REG; } /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, @@ -589,6 +604,15 @@ static void radeon_apply_legacy_quirks(struct drm_device *dev, int bios_index) } + /* X300 card with extra non-existent DVI port */ + if (dev->pdev->device == 0x5B60 && + dev->pdev->subsystem_vendor == 0x17af && + dev->pdev->subsystem_device == 0x201e && + bios_index == 2) { + if (mode_info->bios_connector[bios_index].connector_type == CONNECTOR_DVI_I) + mode_info->bios_connector[bios_index].valid = false; + } + } bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) From f38fff5416bc8e40ce9426f78bfea1bad415faab Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Aug 2008 18:13:21 -0400 Subject: [PATCH 48/49] Fill in and make use of more com bios tables on legacy chips --- linux-core/radeon_combios.c | 192 +++++++++++++++++++++++++++- linux-core/radeon_legacy_crtc.c | 180 ++++++++++++++------------ linux-core/radeon_legacy_encoders.c | 33 +++-- linux-core/radeon_mode.h | 36 +++++- linux-core/radeon_reg.h | 9 ++ 5 files changed, 352 insertions(+), 98 deletions(-) diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c index 1080079f..bb8d0b27 100644 --- a/linux-core/radeon_combios.c +++ b/linux-core/radeon_combios.c @@ -428,7 +428,7 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) struct radeon_mode_info *mode_info = &dev_priv->mode_info; uint16_t pll_info; struct radeon_pll *pll = &mode_info->pll; - int rev; + int8_t rev; pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE); if (pll_info) { @@ -450,17 +450,153 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) pll->xclk = radeon_bios16(dev_priv, pll_info + 0x08); // sclk/mclk use fixed point + //sclk = radeon_bios16(pll_info + 8) / 100.0; + //mclk = radeon_bios16(pll_info + 10) / 100.0; + //if (sclk == 0) sclk = 200; + //if (mclk == 0) mclk = 200; return true; } return false; } +bool radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint16_t dac_info; + uint8_t rev, bg, dac; + + /* first check TV table */ + dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); + if (dac_info) { + rev = radeon_bios8(dev_priv, dac_info + 0x3); + if (rev > 4) { + bg = radeon_bios8(dev_priv, dac_info + 0xc) & 0xf; + dac = radeon_bios8(dev_priv, dac_info + 0xd) & 0xf; + encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); + + bg = radeon_bios8(dev_priv, dac_info + 0xe) & 0xf; + dac = radeon_bios8(dev_priv, dac_info + 0xf) & 0xf; + encoder->pal_tvdac_adj = (bg << 16) | (dac << 20); + + bg = radeon_bios8(dev_priv, dac_info + 0x10) & 0xf; + dac = radeon_bios8(dev_priv, dac_info + 0x11) & 0xf; + encoder->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + + return true; + } else if (rev > 1) { + bg = radeon_bios8(dev_priv, dac_info + 0xc) & 0xf; + dac = (radeon_bios8(dev_priv, dac_info + 0xc) >> 4) & 0xf; + encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); + + bg = radeon_bios8(dev_priv, dac_info + 0xd) & 0xf; + dac = (radeon_bios8(dev_priv, dac_info + 0xd) >> 4) & 0xf; + encoder->pal_tvdac_adj = (bg << 16) | (dac << 20); + + bg = radeon_bios8(dev_priv, dac_info + 0xe) & 0xf; + dac = (radeon_bios8(dev_priv, dac_info + 0xe) >> 4) & 0xf; + encoder->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + + return true; + } + } + + /* then check CRT table */ + dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); + if (dac_info) { + rev = radeon_bios8(dev_priv, dac_info) & 0x3; + if (rev < 2) { + bg = radeon_bios8(dev_priv, dac_info + 0x3) & 0xf; + dac = (radeon_bios8(dev_priv, dac_info + 0x3) >> 4) & 0xf; + encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); + encoder->pal_tvdac_adj = encoder->ps2_tvdac_adj; + encoder->ntsc_tvdac_adj = encoder->ps2_tvdac_adj; + + return true; + } else { + bg = radeon_bios8(dev_priv, dac_info + 0x4) & 0xf; + dac = radeon_bios8(dev_priv, dac_info + 0x5) & 0xf; + encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); + encoder->pal_tvdac_adj = encoder->ps2_tvdac_adj; + encoder->ntsc_tvdac_adj = encoder->ps2_tvdac_adj; + + return true; + } + + } + + return false; +} + +bool radeon_combios_get_tv_info(struct radeon_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct drm_radeon_private *dev_priv = dev->dev_private; + uint16_t tv_info; + + tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); + if (tv_info) { + if (radeon_bios8(dev_priv, tv_info + 6) == 'T') { + switch (radeon_bios8(dev_priv, tv_info + 7) & 0xf) { + case 1: + encoder->tv_std = TV_STD_NTSC; + DRM_INFO("Default TV standard: NTSC\n"); + break; + case 2: + encoder->tv_std = TV_STD_PAL; + DRM_INFO("Default TV standard: PAL\n"); + break; + case 3: + encoder->tv_std = TV_STD_PAL_M; + DRM_INFO("Default TV standard: PAL-M\n"); + break; + case 4: + encoder->tv_std = TV_STD_PAL_60; + DRM_INFO("Default TV standard: PAL-60\n"); + break; + case 5: + encoder->tv_std = TV_STD_NTSC_J; + DRM_INFO("Default TV standard: NTSC-J\n"); + break; + case 6: + encoder->tv_std = TV_STD_SCART_PAL; + DRM_INFO("Default TV standard: SCART-PAL\n"); + break; + default: + encoder->tv_std = TV_STD_NTSC; + DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); + break; + } + + switch ((radeon_bios8(dev_priv, tv_info + 9) >> 2) & 0x3) { + case 0: + DRM_INFO("29.498928713 MHz TV ref clk\n"); + break; + case 1: + DRM_INFO("28.636360000 MHz TV ref clk\n"); + break; + case 2: + DRM_INFO("14.318180000 MHz TV ref clk\n"); + break; + case 3: + DRM_INFO("27.000000000 MHz TV ref clk\n"); + break; + default: + break; + } + return true; + } + } + return false; +} + bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_radeon_private *dev_priv = dev->dev_private; uint16_t lcd_info; + uint32_t panel_setup; char stmp[30]; int tmp, i; @@ -478,9 +614,57 @@ bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder) DRM_INFO("Panel Size %dx%d\n", encoder->panel_xres, encoder->panel_yres); - encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 44); - if (encoder->panel_pwr_delay > 2000 || encoder->panel_pwr_delay < 0) - encoder->panel_pwr_delay = 2000; + encoder->panel_vcc_delay = radeon_bios16(dev_priv, lcd_info + 44); + if (encoder->panel_vcc_delay > 2000 || encoder->panel_vcc_delay < 0) + encoder->panel_vcc_delay = 2000; + + encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 0x24); + encoder->panel_digon_delay = radeon_bios16(dev_priv, lcd_info + 0x38) & 0xf; + encoder->panel_blon_delay = (radeon_bios16(dev_priv, lcd_info + 0x38) >> 4) & 0xf; + + encoder->panel_ref_divider = radeon_bios16(dev_priv, lcd_info + 46); + encoder->panel_post_divider = radeon_bios8(dev_priv, lcd_info + 48); + encoder->panel_fb_divider = radeon_bios16(dev_priv, lcd_info + 49); + if ((encoder->panel_ref_divider != 0) && + (encoder->panel_fb_divider > 3)) + encoder->use_bios_dividers = true; + + panel_setup = radeon_bios32(dev_priv, lcd_info + 0x39); + encoder->lvds_gen_cntl = 0; + if (panel_setup & 0x1) + encoder->lvds_gen_cntl |= RADEON_LVDS_PANEL_FORMAT; + + if ((panel_setup >> 4) & 0x1) + encoder->lvds_gen_cntl |= RADEON_LVDS_PANEL_TYPE; + + switch ((panel_setup >> 8) & 0x8) { + case 0: + encoder->lvds_gen_cntl |= RADEON_LVDS_NO_FM; + break; + case 1: + encoder->lvds_gen_cntl |= RADEON_LVDS_2_GREY; + break; + case 2: + encoder->lvds_gen_cntl |= RADEON_LVDS_4_GREY; + break; + default: + break; + } + + if ((panel_setup >> 16) & 0x1) + encoder->lvds_gen_cntl |= RADEON_LVDS_FP_POL_LOW; + + if ((panel_setup >> 17) & 0x1) + encoder->lvds_gen_cntl |= RADEON_LVDS_LP_POL_LOW; + + if ((panel_setup >> 18) & 0x1) + encoder->lvds_gen_cntl |= RADEON_LVDS_DTM_POL_LOW; + + if ((panel_setup >> 23) & 0x1) + encoder->lvds_gen_cntl |= RADEON_LVDS_BL_CLK_SEL; + + encoder->lvds_gen_cntl |= (panel_setup & 0xf0000000); + for (i = 0; i < 32; i++) { tmp = radeon_bios16(dev_priv, lcd_info + 64 + i * 2); diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index 08d4a477..6775ffc0 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -356,13 +356,9 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo uint32_t tv_dac_cntl = RADEON_READ(RADEON_TV_DAC_CNTL); uint32_t dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2); uint32_t crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); -// state->dac2_cntl = info->StatedReg->dac2_cntl; -// state->tv_dac_cntl = info->StatedReg->tv_dac_cntl; -// state->crtc2_gen_cntl = info->StatedReg->crtc2_gen_cntl; -// state->disp_hw_debug = info->StatedReg->disp_hw_debug; -// state->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; -// state->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; + dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; /* For CRT on DAC2, don't turn it on if BIOS didn't enable it, even it's detected. @@ -395,19 +391,22 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo return true; } -static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) +static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder; uint32_t feedback_div = 0; uint32_t reference_div = 0; uint32_t post_divider = 0; uint32_t freq = 0; uint8_t pll_gain; + int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; + bool use_bios_divs = false; /* PLL registers */ - uint32_t ppll_ref_div; - uint32_t ppll_div_3; - uint32_t htotal_cntl; + uint32_t ppll_ref_div = 0; + uint32_t ppll_div_3 = 0; + uint32_t htotal_cntl = 0; uint32_t vclk_ecp_cntl; struct radeon_pll *pll = &dev_priv->mode_info.pll; @@ -432,44 +431,56 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode { 0, 0 } }; -#if 0 // TODO - if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { - ppll_ref_div = info->RefDivider; - ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); - htotal_cntl = 0; - return; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) + pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_encoder->use_bios_dividers) { + ppll_ref_div = radeon_encoder->panel_ref_divider; + ppll_div_3 = (radeon_encoder->panel_fb_divider | + (radeon_encoder->panel_post_divider << 16)); + htotal_cntl = 0; + use_bios_divs = true; + } else + pll_flags |= RADEON_PLL_USE_REF_DIV; + } + } } -#endif DRM_DEBUG("\n"); - radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags); - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - if (post_div->divider == post_divider) - break; - } + if (!use_bios_divs) { + radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags); - if (!post_div->divider) { - post_div = &post_divs[0]; - } + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + if (post_div->divider == post_divider) + break; + } - DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", - (unsigned)freq, - feedback_div, - reference_div, - post_divider); + if (!post_div->divider) { + post_div = &post_divs[0]; + } - ppll_ref_div = reference_div; + DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)freq, + feedback_div, + reference_div, + post_divider); + ppll_ref_div = reference_div; #if defined(__powerpc__) && (0) /* TODO */ - /* apparently programming this otherwise causes a hang??? */ - if (info->MacModel == RADEON_MAC_IBOOK) - state->ppll_div_3 = 0x000600ad; - else + /* apparently programming this otherwise causes a hang??? */ + if (info->MacModel == RADEON_MAC_IBOOK) + state->ppll_div_3 = 0x000600ad; + else #endif - ppll_div_3 = (feedback_div | (post_div->bitvalue << 16)); + ppll_div_3 = (feedback_div | (post_div->bitvalue << 16)); + htotal_cntl = mode->htotal & 0x7; - htotal_cntl = mode->htotal & 0x7; + } vclk_ecp_cntl = (RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL) & ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; @@ -783,19 +794,22 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo } -static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) +static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder; uint32_t feedback_div = 0; uint32_t reference_div = 0; uint32_t post_divider = 0; uint32_t freq = 0; uint8_t pll_gain; + int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; + bool use_bios_divs = false; /* PLL2 registers */ - uint32_t p2pll_ref_div; - uint32_t p2pll_div_0; - uint32_t htotal_cntl2; + uint32_t p2pll_ref_div = 0; + uint32_t p2pll_div_0 = 0; + uint32_t htotal_cntl2 = 0; uint32_t pixclks_cntl; struct radeon_pll *pll = &dev_priv->mode_info.pll; @@ -819,38 +833,51 @@ static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode { 0, 0 } }; -#if 0 - if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { - p2pll_ref_div = info->RefDivider; - p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16); - htotal_cntl2 = 0; - return; - } -#endif + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) + pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags); - - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - if (post_div->divider == post_divider) - break; + if (radeon_encoder->use_bios_dividers) { + p2pll_ref_div = radeon_encoder->panel_ref_divider; + p2pll_div_0 = (radeon_encoder->panel_fb_divider | + (radeon_encoder->panel_post_divider << 16)); + htotal_cntl2 = 0; + use_bios_divs = true; + } else + pll_flags |= RADEON_PLL_USE_REF_DIV; + } + } } - if (!post_div->divider) { - post_div = &post_divs[0]; + DRM_DEBUG("\n"); + + if (!use_bios_divs) { + radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags); + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + if (post_div->divider == post_divider) + break; + } + + if (!post_div->divider) { + post_div = &post_divs[0]; + } + + DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)freq, + feedback_div, + reference_div, + post_divider); + + p2pll_ref_div = reference_div; + p2pll_div_0 = (feedback_div | (post_div->bitvalue << 16)); + htotal_cntl2 = mode->htotal & 0x7; + } - DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", - (unsigned)freq, - feedback_div, - reference_div, - post_divider); - - p2pll_ref_div = reference_div; - - p2pll_div_0 = (feedback_div | (post_div->bitvalue << 16)); - - htotal_cntl2 = mode->htotal & 0x7; - pixclks_cntl = ((RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL) & ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); @@ -946,22 +973,9 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, int x, int y) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct drm_encoder *encoder; - int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; DRM_DEBUG("\n"); - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - - if (encoder->crtc == crtc) { - if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) - pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; - if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) - pll_flags |= RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV; - } - } - /* TODO TV */ radeon_crtc_set_base(crtc, x, y); @@ -969,11 +983,11 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc, switch(radeon_crtc->crtc_id) { case 0: radeon_set_crtc1_timing(crtc, adjusted_mode); - radeon_set_pll1(crtc, adjusted_mode, pll_flags); + radeon_set_pll1(crtc, adjusted_mode); break; case 1: radeon_set_crtc2_timing(crtc, adjusted_mode); - radeon_set_pll2(crtc, adjusted_mode, pll_flags); + radeon_set_pll2(crtc, adjusted_mode); break; } diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c index de9e8ac6..172f93de 100644 --- a/linux-core/radeon_legacy_encoders.c +++ b/linux-core/radeon_legacy_encoders.c @@ -213,10 +213,20 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + + /* enable lvds, turn on voltage */ lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); - lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); + RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + udelay(radeon_encoder->panel_digon_delay * 1000); + + /* enable data */ lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); - udelay(radeon_encoder->panel_pwr_delay * 1000); + RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + udelay(radeon_encoder->panel_blon_delay * 1000); + + /* enable backlight */ + lvds_gen_cntl |= RADEON_LVDS_BLON; RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); break; case DRM_MODE_DPMS_STANDBY: @@ -226,7 +236,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; - lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl); break; @@ -260,7 +270,10 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; - lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); + if (radeon_encoder->lvds_gen_cntl) + lvds_gen_cntl = radeon_encoder->lvds_gen_cntl; + else + lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | @@ -339,7 +352,6 @@ struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int b drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); - /* TODO get the LVDS info from the BIOS for panel size etc. */ /* get the lvds info from the bios */ radeon_combios_get_lvds_info(radeon_encoder); @@ -659,6 +671,7 @@ struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, i drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs); radeon_combios_get_tmds_info(radeon_encoder); + return encoder; } @@ -893,6 +906,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_radeon_private *dev_priv = dev->dev_private; struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0; uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0; @@ -924,8 +938,8 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, // FIXME TV tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | - RADEON_TV_DAC_STD_PS2 /*| - radeon_encoder->ps2_tvdac_adj*/); // fixme, get from bios + RADEON_TV_DAC_STD_PS2 | + radeon_encoder->ps2_tvdac_adj); RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl); } @@ -1015,8 +1029,9 @@ struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs); - /* TODO get the tv dac vals from bios tables */ - //radeon_combios_get_lvds_info(radeon_encoder); + /* get the tv dac vals from bios tables */ + radeon_combios_get_tv_info(radeon_encoder); + radeon_combios_get_tv_dac_info(radeon_encoder); return encoder; } diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h index 6a2e275c..3271375d 100644 --- a/linux-core/radeon_mode.h +++ b/linux-core/radeon_mode.h @@ -87,6 +87,17 @@ enum radeon_rmx_type { RMX_CENTER, }; +enum radeon_tv_std { + TV_STD_NTSC, + TV_STD_PAL, + TV_STD_PAL_M, + TV_STD_PAL_60, + TV_STD_NTSC_J, + TV_STD_SCART_PAL, + TV_STD_SECAM, + TV_STD_PAL_CN, +}; + struct radeon_i2c_bus_rec { bool valid; uint32_t mask_clk_reg; @@ -337,13 +348,33 @@ struct radeon_encoder { enum radeon_tmds_type tmds; } type; int atom_device; /* atom devices */ + + /* preferred mode */ uint32_t panel_xres, panel_yres; uint32_t hoverplus, hsync_width; uint32_t hblank; uint32_t voverplus, vsync_width; uint32_t vblank; - uint32_t panel_pwr_delay; uint32_t dotclock; + + /* legacy lvds */ + uint16_t panel_vcc_delay; + uint16_t panel_pwr_delay; + uint16_t panel_digon_delay; + uint16_t panel_blon_delay; + uint32_t panel_ref_divider; + uint32_t panel_post_divider; + uint32_t panel_fb_divider; + bool use_bios_dividers; + uint32_t lvds_gen_cntl; + + /* legacy tv dac */ + uint32_t ps2_tvdac_adj; + uint32_t ntsc_tvdac_adj; + uint32_t pal_tvdac_adj; + enum radeon_tv_std tv_std; + + /* legacy int tmds */ struct radeon_tmds_pll tmds_pll[4]; }; @@ -351,7 +382,6 @@ struct radeon_connector { struct drm_connector base; struct radeon_i2c_chan *ddc_bus; int use_digital; - }; struct radeon_framebuffer { @@ -407,6 +437,8 @@ extern bool radeon_combios_get_clock_info(struct drm_device *dev); extern void radeon_get_lvds_info(struct radeon_encoder *encoder); extern bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder); extern bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder); +extern bool radeon_combios_get_tv_info(struct radeon_encoder *encoder); +extern bool radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder); extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno); struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev, diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index ad91e04c..59108979 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -1027,14 +1027,23 @@ # define RADEON_LVDS_DISPLAY_DIS (1 << 1) # define RADEON_LVDS_PANEL_TYPE (1 << 2) # define RADEON_LVDS_PANEL_FORMAT (1 << 3) +# define RADEON_LVDS_NO_FM (0 << 4) +# define RADEON_LVDS_2_GREY (1 << 4) +# define RADEON_LVDS_4_GREY (2 << 4) # define RADEON_LVDS_RST_FM (1 << 6) # define RADEON_LVDS_EN (1 << 7) # define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 # define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) # define RADEON_LVDS_BL_MOD_EN (1 << 16) +# define RADEON_LVDS_BL_CLK_SEL (1 << 17) # define RADEON_LVDS_DIGON (1 << 18) # define RADEON_LVDS_BLON (1 << 19) +# define RADEON_LVDS_FP_POL_LOW (1 << 20) +# define RADEON_LVDS_LP_POL_LOW (1 << 21) +# define RADEON_LVDS_DTM_POL_LOW (1 << 22) # define RADEON_LVDS_SEL_CRTC2 (1 << 23) +# define RADEON_LVDS_FPDI_EN (1 << 27) +# define RADEON_LVDS_HSYNC_DELAY_SHIFT 28 #define RADEON_LVDS_PLL_CNTL 0x02d4 # define RADEON_HSYNC_DELAY_SHIFT 28 # define RADEON_HSYNC_DELAY_MASK (0xf << 28) From 2a65759d159478b126c660ef124777548dcc872c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Aug 2008 20:18:07 -0400 Subject: [PATCH 49/49] Add com bios asic init bits --- linux-core/radeon_combios.c | 255 ++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c index bb8d0b27..56116463 100644 --- a/linux-core/radeon_combios.c +++ b/linux-core/radeon_combios.c @@ -1016,3 +1016,258 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) return true; } +static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + if (offset) { + while (radeon_bios16(dev_priv, offset)) { + uint16_t cmd = ((radeon_bios16(dev_priv, offset) & 0xe000) >> 13); + uint32_t addr = (radeon_bios16(dev_priv, offset) & 0x1fff); + uint32_t val, and_mask, or_mask; + uint32_t tmp; + + offset += 2; + switch (cmd) { + case 0: + val = radeon_bios32(dev_priv, offset); + offset += 4; + RADEON_WRITE(addr, val); + break; + case 1: + val = radeon_bios32(dev_priv, offset); + offset += 4; + RADEON_WRITE(addr, val); + break; + case 2: + and_mask = radeon_bios32(dev_priv, offset); + offset += 4; + or_mask = radeon_bios32(dev_priv, offset); + offset += 4; + tmp = RADEON_READ(addr); + tmp &= and_mask; + tmp |= or_mask; + RADEON_WRITE(addr, tmp); + break; + case 3: + and_mask = radeon_bios32(dev_priv, offset); + offset += 4; + or_mask = radeon_bios32(dev_priv, offset); + offset += 4; + tmp = RADEON_READ(addr); + tmp &= and_mask; + tmp |= or_mask; + RADEON_WRITE(addr, tmp); + break; + case 4: + val = radeon_bios16(dev_priv, offset); + offset += 2; + udelay(val); + break; + case 5: + val = radeon_bios16(dev_priv, offset); + offset += 2; + switch (addr) { + case 8: + while (val--) { + if (!(RADEON_READ_PLL(dev_priv, RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + case 9: + while (val--) { + if ((RADEON_READ(RADEON_MC_STATUS) & + RADEON_MC_IDLE)) + break; + } + break; + default: + break; + } + break; + default: + break; + } + } + } +} + +static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + + if (offset) { + while (radeon_bios8(dev_priv, offset)) { + uint8_t cmd = ((radeon_bios8(dev_priv, offset) & 0xc0) >> 6); + uint8_t addr = (radeon_bios8(dev_priv, offset) & 0x3f); + uint32_t val, shift, tmp; + uint32_t and_mask, or_mask; + + offset++; + switch (cmd) { + case 0: + val = radeon_bios32(dev_priv, offset); + offset += 4; + RADEON_WRITE_PLL(dev_priv, addr, val); + break; + case 1: + shift = radeon_bios8(dev_priv, offset) * 8; + offset++; + and_mask = radeon_bios8(dev_priv, offset) << shift; + and_mask |= ~(0xff << shift); + offset++; + or_mask = radeon_bios8(dev_priv, offset) << shift; + offset++; + tmp = RADEON_READ_PLL(dev_priv, addr); + tmp &= and_mask; + tmp |= or_mask; + RADEON_WRITE_PLL(dev_priv, addr, tmp); + break; + case 2: + case 3: + tmp = 1000; + switch (addr) { + case 1: + udelay(150); + break; + case 2: + udelay(1000); + break; + case 3: + while (tmp--) { + if (!(RADEON_READ_PLL(dev_priv, RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + case 4: + while (tmp--) { + if (RADEON_READ_PLL(dev_priv, RADEON_CLK_PWRMGT_CNTL) & + RADEON_DLL_READY) + break; + } + break; + case 5: + tmp = RADEON_READ_PLL(dev_priv, RADEON_CLK_PWRMGT_CNTL); + if (tmp & RADEON_CG_NO1_DEBUG_0) { +#if 0 + uint32_t mclk_cntl = RADEON_READ_PLL(RADEON_MCLK_CNTL); + mclk_cntl &= 0xffff0000; + //mclk_cntl |= 0x00001111; /* ??? */ + RADEON_WRITE_PLL(dev_priv, RADEON_MCLK_CNTL, mclk_cntl); + udelay(10000); +#endif + RADEON_WRITE_PLL(dev_priv, RADEON_CLK_PWRMGT_CNTL, + tmp & ~RADEON_CG_NO1_DEBUG_0); + udelay(10000); + } + break; + default: + break; + } + break; + default: + break; + } + } + } +} + +static void combios_parse_ram_reset_table(struct drm_device *dev, uint16_t offset) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t tmp; + + if (offset) { + uint8_t val = radeon_bios8(dev_priv, offset); + while (val != 0xff) { + offset++; + + if (val == 0x0f) { + uint32_t channel_complete_mask; + + if (radeon_is_r300(dev_priv)) + channel_complete_mask = R300_MEM_PWRUP_COMPLETE; + else + channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; + tmp = 20000; + while (tmp--) { + if ((RADEON_READ(RADEON_MEM_STR_CNTL) & + channel_complete_mask) == + channel_complete_mask) + break; + } + } else { + uint32_t or_mask = radeon_bios16(dev_priv, offset); + offset += 2; + + tmp = RADEON_READ(RADEON_MEM_SDRAM_MODE_REG); + tmp &= RADEON_SDRAM_MODE_MASK; + tmp |= or_mask; + RADEON_WRITE(RADEON_MEM_SDRAM_MODE_REG, tmp); + + or_mask = val << 24; + tmp = RADEON_READ(RADEON_MEM_SDRAM_MODE_REG); + tmp &= RADEON_B3MEM_RESET_MASK; + tmp |= or_mask; + RADEON_WRITE(RADEON_MEM_SDRAM_MODE_REG, tmp); + } + val = radeon_bios8(dev_priv, offset); + } + } +} + +void radeon_combios_dyn_clk_setup(struct drm_device *dev, int enable) +{ + uint16_t dyn_clk_info = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); + + if (dyn_clk_info) + combios_parse_pll_table(dev, dyn_clk_info); +} + +void radeon_combios_asic_init(struct drm_device *dev) +{ + uint16_t table; + + /* ASIC INIT 1 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_1_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* PLL INIT */ + table = combios_get_table_offset(dev, COMBIOS_PLL_INIT_TABLE); + if (table) + combios_parse_pll_table(dev, table); + + /* ASIC INIT 2 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_2_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* ASIC INIT 4 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_4_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* RAM RESET */ + table = combios_get_table_offset(dev, COMBIOS_RAM_RESET_TABLE); + if (table) + combios_parse_ram_reset_table(dev, table); + + /* ASIC INIT 3 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_3_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* DYN CLK 1 */ + table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); + if (table) + combios_parse_pll_table(dev, table); + + /* ASIC INIT 5 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_5_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + +}