diff options
28 files changed, 753 insertions, 302 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 392abaf9..98616e4b 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -44,7 +44,7 @@ nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.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 \ - radeon_cursor.o radeon_pm.o + radeon_cursor.o radeon_pm.o radeon_gem_proc.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/ati_pcigart.c b/linux-core/ati_pcigart.c index 50e990f1..6b0d8947 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -39,7 +39,7 @@ #define ATI_PCIE_WRITE 0x4 #define ATI_PCIE_READ 0x8 -static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info *gart_info, dma_addr_t addr, u32 *pci_gart) +static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info *gart_info, dma_addr_t addr, volatile u32 *pci_gart) { u32 page_base; @@ -61,7 +61,7 @@ static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info * *pci_gart = cpu_to_le32(page_base); } -static __inline__ dma_addr_t gart_get_page_from_table(struct drm_ati_pcigart_info *gart_info, u32 *pci_gart) +static __inline__ dma_addr_t gart_get_page_from_table(struct drm_ati_pcigart_info *gart_info, volatile u32 *pci_gart) { dma_addr_t retval; switch(gart_info->gart_reg_if) { @@ -93,7 +93,7 @@ int drm_ati_alloc_pcigart_table(struct drm_device *dev, #ifdef CONFIG_X86 /* IGPs only exist on x86 in any case */ if (gart_info->gart_reg_if == DRM_ATI_GART_IGP) - set_memory_uc(gart_info->table_handle->vaddr, gart_info->table_size >> PAGE_SHIFT); + set_memory_uc((unsigned long)gart_info->table_handle->vaddr, gart_info->table_size >> PAGE_SHIFT); #endif memset(gart_info->table_handle->vaddr, 0, gart_info->table_size); @@ -107,7 +107,7 @@ static void drm_ati_free_pcigart_table(struct drm_device *dev, #ifdef CONFIG_X86 /* IGPs only exist on x86 in any case */ if (gart_info->gart_reg_if == DRM_ATI_GART_IGP) - set_memory_wb(gart_info->table_handle->vaddr, gart_info->table_size >> PAGE_SHIFT); + set_memory_wb((unsigned long)gart_info->table_handle->vaddr, gart_info->table_size >> PAGE_SHIFT); #endif drm_pci_free(dev, gart_info->table_handle); gart_info->table_handle = NULL; @@ -260,7 +260,7 @@ static int ati_pcigart_bind_ttm(struct drm_ttm_backend *backend, j = offset; while (j < (offset + atipci_be->num_pages)) { - if (gart_get_page_from_table(info, pci_gart+j)) + if (gart_get_page_from_table(info, pci_gart + j)) return -EBUSY; j++; } diff --git a/linux-core/atombios_crtc.c b/linux-core/atombios_crtc.c index 3856f8ca..2e144c90 100644 --- a/linux-core/atombios_crtc.c +++ b/linux-core/atombios_crtc.c @@ -276,7 +276,7 @@ void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y) radeon_fb = to_radeon_framebuffer(crtc->fb); - obj = radeon_fb->base.mm_private; + obj = radeon_fb->obj; obj_priv = obj->driver_private; fb_location = obj_priv->bo->offset + dev_priv->fb_location; diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index c966badc..15c426cb 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -1544,7 +1544,6 @@ int drm_mapbufs(struct drm_device *dev, void *data, 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, diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 6a73a71b..13fba4f2 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -240,7 +240,6 @@ struct drm_framebuffer { void *fbdev; u32 pseudo_palette[17]; struct list_head filp_head; - void *mm_private; }; struct drm_property_blob { diff --git a/linux-core/drm_crtc_helper.c b/linux-core/drm_crtc_helper.c index b334f5b5..776a98e1 100644 --- a/linux-core/drm_crtc_helper.c +++ b/linux-core/drm_crtc_helper.c @@ -771,15 +771,13 @@ int drm_helper_hotplug_stage_two(struct drm_device *dev) EXPORT_SYMBOL(drm_helper_hotplug_stage_two); int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, - struct drm_mode_fb_cmd *mode_cmd, - void *mm_private) + struct drm_mode_fb_cmd *mode_cmd) { fb->width = mode_cmd->width; fb->height = mode_cmd->height; fb->pitch = mode_cmd->pitch; fb->bits_per_pixel = mode_cmd->bpp; fb->depth = mode_cmd->depth; - fb->mm_private = mm_private; return 0; } diff --git a/linux-core/drm_crtc_helper.h b/linux-core/drm_crtc_helper.h index 01b14239..c0719157 100644 --- a/linux-core/drm_crtc_helper.h +++ b/linux-core/drm_crtc_helper.h @@ -75,8 +75,7 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_m extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, - struct drm_mode_fb_cmd *mode_cmd, - void *mm_private); + struct drm_mode_fb_cmd *mode_cmd); static inline void drm_crtc_helper_add(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs *funcs) { diff --git a/linux-core/radeon_buffer.c b/linux-core/radeon_buffer.c index e5a90892..f047b1ac 100644 --- a/linux-core/radeon_buffer.c +++ b/linux-core/radeon_buffer.c @@ -170,10 +170,12 @@ void radeon_emit_copy_blit(struct drm_device * dev, ADVANCE_RING(); } - BEGIN_RING(4); + BEGIN_RING(6); OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); OUT_RING(RADEON_RB2D_DC_FLUSH_ALL); RADEON_WAIT_UNTIL_2D_IDLE(); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); ADVANCE_RING(); COMMIT_RING(); @@ -252,7 +254,8 @@ void radeon_emit_solid_fill(struct drm_device * dev, RADEON_GMC_DST_CLIPPING | RADEON_GMC_BRUSH_SOLID_COLOR | (format << 8) | - RADEON_ROP3_S | + RADEON_ROP3_P | + RADEON_CLR_CMP_SRC_SOURCE | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); OUT_RING((pitch << 22) | (dst_offset >> 10)); // PITCH OUT_RING(0); // SC_TOP_LEFT // DST CLIPPING @@ -265,10 +268,14 @@ void radeon_emit_solid_fill(struct drm_device * dev, ADVANCE_RING(); } - BEGIN_RING(4); + BEGIN_RING(8); OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); OUT_RING(RADEON_RB2D_DC_FLUSH_ALL); RADEON_WAIT_UNTIL_2D_IDLE(); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); ADVANCE_RING(); COMMIT_RING(); @@ -350,7 +357,6 @@ static int radeon_move_vram(struct drm_buffer_object * bo, struct drm_bo_mem_reg tmp_mem; struct drm_bo_mem_reg *old_mem = &bo->mem; int ret; - bool was_local = false; /* old - LOCAL memory node bo->mem tmp - TT type memory node @@ -398,7 +404,6 @@ int radeon_move(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 *old_mem = &bo->mem; drm_radeon_private_t *dev_priv = dev->dev_private; if (!dev_priv->cp_running) diff --git a/linux-core/radeon_connectors.c b/linux-core/radeon_connectors.c index f217fe77..18873f0f 100644 --- a/linux-core/radeon_connectors.c +++ b/linux-core/radeon_connectors.c @@ -87,19 +87,23 @@ static int radeon_lvds_get_modes(struct drm_connector *connector) if (radeon_connector->ddc_bus) { radeon_i2c_do_lock(radeon_connector, 1); - edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); + edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); 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); kfree(edid); + if (ret == 0) + goto native; return ret; } } +native: encoder = radeon_best_single_encoder(connector); if (!encoder) - return connector_status_disconnected; + return 0; + /* we have no EDID modes */ mode = radeon_fp_native_mode(encoder); if (mode) { @@ -301,8 +305,11 @@ static struct connector_funcs { { CONNECTOR_LVDS, &radeon_lvds_connector_funcs, &radeon_lvds_connector_helper_funcs, DRM_MODE_CONNECTOR_LVDS, "LVDS" }, { 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" }, - + { CONNECTOR_DVI_D, &radeon_dvi_connector_funcs, &radeon_dvi_connector_helper_funcs, DRM_MODE_CONNECTOR_DVID, "DVI" }, + { CONNECTOR_HDMI_TYPE_A, &radeon_dvi_connector_funcs, &radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_HDMIA, "HDMI" }, + { CONNECTOR_HDMI_TYPE_B, &radeon_dvi_connector_funcs, &radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_HDMIB, "HDMI" }, #if 0 + { CONNECTOR_HDMI_TYPE_A, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, { CONNECTOR_DVI_D, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, { CONNECTOR_STV, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, @@ -310,7 +317,6 @@ static struct connector_funcs { { CONNECTOR_DIGITAL, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, { CONNECTOR_SCART, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, - { CONNECTOR_HDMI_TYPE_A, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, { CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, { CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, { CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA }, diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index ddc933cc..0b9467fd 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -263,7 +263,9 @@ bool radeon_setup_enc_conn(struct drm_device *dev) /* TMDS on DVI */ if ((mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I) || - (mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_D)) { + (mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_D) || + (mode_info->bios_connector[i].connector_type == CONNECTOR_HDMI_TYPE_A) || + (mode_info->bios_connector[i].connector_type == CONNECTOR_HDMI_TYPE_B)) { if (radeon_is_avivo(dev_priv) || radeon_r4xx_atom) encoder = radeon_encoder_atom_tmds_add(dev, i, mode_info->bios_connector[i].tmds_type); else { @@ -601,17 +603,22 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) if (fb->fbdev) radeonfb_remove(dev, fb); + if (radeon_fb->obj) { + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(radeon_fb->obj); + mutex_unlock(&dev->struct_mutex); + } drm_framebuffer_cleanup(fb); kfree(radeon_fb); } static int radeon_user_framebuffer_create_handle(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int *handle) + struct drm_file *file_priv, + unsigned int *handle) { - struct drm_gem_object *object = fb->mm_private; + struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); - return drm_gem_handle_create(file_priv, object, handle); + return drm_gem_handle_create(file_priv, radeon_fb->obj, handle); } static const struct drm_framebuffer_funcs radeon_fb_funcs = { @@ -622,7 +629,7 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = { struct drm_framebuffer * radeon_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd, - void *mm_private) + struct drm_gem_object *obj) { struct radeon_framebuffer *radeon_fb; @@ -631,7 +638,10 @@ radeon_framebuffer_create(struct drm_device *dev, return NULL; drm_framebuffer_init(dev, &radeon_fb->base, &radeon_fb_funcs); - drm_helper_mode_fill_fb_struct(&radeon_fb->base, mode_cmd, mm_private); + drm_helper_mode_fill_fb_struct(&radeon_fb->base, mode_cmd); + + radeon_fb->obj = obj; + return &radeon_fb->base; } @@ -641,10 +651,11 @@ radeon_user_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd) { struct radeon_framebuffer *radeon_fb; - void *mm_private; + struct drm_gem_object *obj; + + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); - mm_private = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); - return radeon_framebuffer_create(dev, mode_cmd, mm_private); + return radeon_framebuffer_create(dev, mode_cmd, obj); } static const struct drm_mode_config_funcs radeon_mode_funcs = { diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index f1fe3012..f4194688 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -37,14 +37,14 @@ #include "drm_pciids.h" int radeon_no_wb; -int radeon_dynclks = 1; +int radeon_dynclks = -1; int radeon_r4xx_atom = 0; int radeon_agpmode = 0; MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n"); module_param_named(no_wb, radeon_no_wb, int, 0444); -unsigned int radeon_modeset = 0; +int radeon_modeset = 0; module_param_named(modeset, radeon_modeset, int, 0400); MODULE_PARM_DESC(dynclks, "Disable/Enable dynamic clocks"); @@ -60,8 +60,12 @@ module_param_named(agpmode, radeon_agpmode, int, 0444); static int dri_library_name(struct drm_device * dev, char * buf) { drm_radeon_private_t *dev_priv = dev->dev_private; - int family = dev_priv->flags & RADEON_FAMILY_MASK; + int family; + if (!dev_priv) + return 0; + + family = dev_priv->flags & RADEON_FAMILY_MASK; return snprintf(buf, PAGE_SIZE, "%s\n", (family < CHIP_R200) ? "radeon" : ((family < CHIP_R300) ? "r200" : @@ -122,6 +126,8 @@ static struct drm_driver driver = { .dma_ioctl = radeon_cp_buffers, .master_create = radeon_master_create, .master_destroy = radeon_master_destroy, + .proc_init = radeon_gem_proc_init, + .proc_cleanup = radeon_gem_proc_cleanup, .fops = { .owner = THIS_MODULE, .open = drm_open, diff --git a/linux-core/radeon_fb.c b/linux-core/radeon_fb.c index 8d4181e8..d3722c37 100644 --- a/linux-core/radeon_fb.c +++ b/linux-core/radeon_fb.c @@ -1148,7 +1148,8 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) unregister_framebuffer(info); drm_bo_kunmap(&radeon_fb->kmap_obj); mutex_lock(&dev->struct_mutex); - drm_gem_object_unreference(fb->mm_private); + drm_gem_object_unreference(radeon_fb->obj); + radeon_fb->obj = NULL; mutex_unlock(&dev->struct_mutex); framebuffer_release(info); } diff --git a/linux-core/radeon_fence.c b/linux-core/radeon_fence.c index 591ad53b..b662da21 100644 --- a/linux-core/radeon_fence.c +++ b/linux-core/radeon_fence.c @@ -39,7 +39,6 @@ int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class, uint32_t *native_type) { struct drm_radeon_private *dev_priv = (struct drm_radeon_private *) dev->dev_private; - RING_LOCALS; if (!dev_priv) return -EINVAL; diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 5e2ad98b..2e20de3c 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -126,7 +126,6 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_radeon_gem_object *obj_priv; struct drm_gem_object *obj; int ret = 0; - uint32_t flags; int handle; /* create a gem object to contain this object in */ @@ -157,8 +156,6 @@ fail: int radeon_gem_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uint32_t write_domain, uint32_t *flags_p, bool unfenced) { - struct drm_device *dev = obj->dev; - drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_radeon_gem_object *obj_priv; uint32_t flags = 0; int ret; @@ -419,24 +416,14 @@ int radeon_gem_busy(struct drm_device *dev, void *data, return 0; } -int radeon_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return -ENOSYS; - - -} - -int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, +int radeon_gem_wait_rendering(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_radeon_gem_indirect *args = data; - struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_radeon_gem_wait_rendering *args = data; struct drm_gem_object *obj; struct drm_radeon_gem_object *obj_priv; - uint32_t start, end; int ret; - RING_LOCALS; + obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (obj == NULL) @@ -444,64 +431,18 @@ int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, obj_priv = obj->driver_private; - DRM_DEBUG("got here %p %d\n", obj, args->used); - //RING_SPACE_TEST_WITH_RETURN(dev_priv); - //VB_AGE_TEST_WITH_RETURN(dev_priv); - - ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - 0 , 0); - if (ret) - return ret; - - /* Wait for the 3D stream to idle before the indirect buffer - * containing 2D acceleration commands is processed. - */ - BEGIN_RING(2); - - RADEON_WAIT_UNTIL_3D_IDLE(); - - ADVANCE_RING(); + mutex_lock(&obj_priv->bo->mutex); + ret = drm_bo_wait(obj_priv->bo, 0, 1, 1, 0); + mutex_unlock(&obj_priv->bo->mutex); - start = 0; - end = args->used; - - if (start != end) { - int offset = (dev_priv->gart_vm_start + - + obj_priv->bo->offset + start); - int dwords = (end - start + 3) / sizeof(u32); - - /* Fire off the indirect buffer */ - BEGIN_RING(3); - - OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); - OUT_RING(offset); - OUT_RING(dwords); - - ADVANCE_RING(); - } - - COMMIT_RING(); - - /* we need to fence the buffer */ - ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &obj_priv->fence); - if (ret) { - - drm_putback_buffer_objects(dev); - ret = 0; - goto fail; - } - - /* dereference he fence object */ - drm_fence_usage_deref_unlocked(&obj_priv->fence); - mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); - ret = 0; - fail: return ret; } + + /* * Depending on card genertation, chipset bugs, etc... the amount of vram * accessible to the CPU can vary. This function is our best shot at figuring @@ -525,6 +466,7 @@ static uint32_t radeon_get_accessible_vram(struct drm_device *dev) dev_priv->chip_family == CHIP_RV350 || dev_priv->chip_family == CHIP_RV380 || dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_R423 || dev_priv->chip_family == CHIP_RV410 || radeon_is_avivo(dev_priv)) { uint32_t temp = RADEON_READ(RADEON_HOST_PATH_CNTL); @@ -585,6 +527,9 @@ void radeon_vram_setup(struct drm_device *dev) if (accessible > bar_size) accessible = bar_size; + if (accessible > vram) + accessible = vram; + DRM_INFO("Detected VRAM RAM=%dK, accessible=%uK, BAR=%uK\n", vram, accessible, bar_size); @@ -612,7 +557,7 @@ static int radeon_gart_init(struct drm_device *dev) base = dev->agp->base; if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { - DRM_INFO("Can't use agp base @0x%08xlx, won't fit\n", + DRM_INFO("Can't use agp base @0x%08lx, won't fit\n", dev->agp->base); base = 0; } @@ -728,7 +673,7 @@ int radeon_alloc_gart_objects(struct drm_device *dev) return -EINVAL; } - DRM_DEBUG("Ring ptr %p mapped at %d %p, read ptr %p maped at %d %p\n", + DRM_DEBUG("Ring ptr %p mapped at %ld %p, read ptr %p maped at %ld %p\n", 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); @@ -825,7 +770,6 @@ static void radeon_wait_for_vsync(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; uint32_t crtc_gen_cntl; - int ret; crtc_gen_cntl = RADEON_READ(RADEON_CRTC_GEN_CNTL); if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || @@ -844,7 +788,6 @@ static void radeon_wait_for_vsync2(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; uint32_t crtc2_gen_cntl; - struct timeval timeout; crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || @@ -913,7 +856,6 @@ void radeon_init_memory_map(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; u32 mem_size, aper_size; - u32 tmp; dev_priv->mc_fb_location = radeon_read_fb_location(dev_priv); radeon_read_agp_location(dev_priv, &dev_priv->mc_agp_loc_lo, &dev_priv->mc_agp_loc_hi); @@ -960,6 +902,7 @@ void radeon_init_memory_map(struct drm_device *dev) dev_priv->chip_family == CHIP_RV350 || dev_priv->chip_family == CHIP_RV380 || dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_R423 || dev_priv->chip_family == CHIP_RV410) aper0_base &= ~(mem_size - 1); @@ -1004,6 +947,10 @@ void radeon_init_memory_map(struct drm_device *dev) - dev_priv->fb_location; } + /* add an MTRR for the VRAM */ + dev_priv->aper_size = aper_size; + dev_priv->vram_mtrr = mtrr_add(dev_priv->fb_aper_offset, dev_priv->aper_size, MTRR_TYPE_WRCOMB, 1); + } /* init memory manager - start with all of VRAM and a 32MB GART aperture for now */ @@ -1094,6 +1041,8 @@ void radeon_gem_mm_fini(struct drm_device *dev) DRM_DEBUG("delaying takedown of VRAM memory\n"); } + if (dev_priv->vram_mtrr) + mtrr_del(dev_priv->vram_mtrr, dev_priv->fb_aper_offset, dev_priv->aper_size); mutex_unlock(&dev->struct_mutex); drm_bo_driver_finish(dev); @@ -1143,11 +1092,11 @@ int radeon_gem_object_unpin(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, uint32_t *card_offset) +int radeon_gem_ib_get(struct drm_radeon_cs_parser *parser) { int i, index = -1; int ret; - drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; for (i = 0; i < RADEON_NUM_IB; i++) { if (!(dev_priv->ib_alloc_bitmap & (1 << i))){ @@ -1173,12 +1122,12 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32 } if (index == -1) { - DRM_ERROR("Major case fail to allocate IB from freelist %x\n", dev_priv->ib_alloc_bitmap); + DRM_ERROR("Major case fail to allocate IB from freelist %llx\n", dev_priv->ib_alloc_bitmap); return -EINVAL; } - if (dwords > RADEON_IB_SIZE / sizeof(uint32_t)) + if (parser->chunks[parser->ib_index].length_dw > RADEON_IB_SIZE / sizeof(uint32_t)) return -EINVAL; ret = drm_bo_do_validate(dev_priv->ib_objs[index]->bo, 0, @@ -1189,26 +1138,26 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32 return -EINVAL; } - *card_offset = dev_priv->gart_vm_start + dev_priv->ib_objs[index]->bo->offset; - *ib = dev_priv->ib_objs[index]->kmap.virtual; + parser->ib = dev_priv->ib_objs[index]->kmap.virtual; + parser->card_offset = dev_priv->gart_vm_start + dev_priv->ib_objs[index]->bo->offset; dev_priv->ib_alloc_bitmap |= (1 << i); return 0; } -static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords) +static void radeon_gem_ib_free(struct drm_radeon_cs_parser *parser) { + struct drm_device *dev = parser->dev; drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_fence_object *fence; int ret; int i; for (i = 0; i < RADEON_NUM_IB; i++) { - - if (dev_priv->ib_objs[i]->kmap.virtual == ib) { + if (dev_priv->ib_objs[i]->kmap.virtual == parser->ib) { /* emit a fence object */ ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); + dev_priv->irq_emitted = 0; if (ret) { - drm_putback_buffer_objects(dev); } /* dereference the fence object */ @@ -1238,21 +1187,58 @@ 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) +static int radeon_gem_find_reloc(struct drm_radeon_cs_parser *parser, + uint32_t offset, uint32_t *handle, + uint32_t *read_domains, uint32_t *write_domain) +{ + struct drm_device *dev = parser->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_kernel_chunk *reloc_chunk = &parser->chunks[parser->reloc_index]; + + if (!reloc_chunk->kdata) + return -EINVAL; + + if (offset > reloc_chunk->length_dw){ + DRM_ERROR("Offset larger than chunk %d %d\n", offset, reloc_chunk->length_dw); + return -EINVAL; + } + + *handle = reloc_chunk->kdata[offset]; + *read_domains = reloc_chunk->kdata[offset + 1]; + *write_domain = reloc_chunk->kdata[offset + 2]; + return 0; +} + +static int radeon_gem_relocate(struct drm_radeon_cs_parser *parser, + uint32_t *reloc, uint32_t *offset) { + struct drm_device *dev = parser->dev; drm_radeon_private_t *dev_priv = dev->dev_private; /* relocate the handle */ - uint32_t read_domains = reloc[2]; - uint32_t write_domain = reloc[3]; + uint32_t read_domains, write_domain; 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 -EINVAL; + if (parser->reloc_index == -1) { + obj = drm_gem_object_lookup(dev, parser->file_priv, reloc[1]); + if (!obj) + return -EINVAL; + read_domains = reloc[2]; + write_domain = reloc[3]; + } else { + uint32_t handle; + + /* have to lookup handle in other chunk */ + ret = radeon_gem_find_reloc(parser, reloc[1], &handle, &read_domains, &write_domain); + if (ret < 0) + return ret; + + obj = drm_gem_object_lookup(dev, parser->file_priv, handle); + if (!obj) + return -EINVAL; + } obj_priv = obj->driver_private; radeon_gem_set_domain(obj, read_domains, write_domain, &flags, false); @@ -1522,7 +1508,7 @@ static int radeon_gem_dma_bufs_init(struct drm_device *dev) if (ret < 0) return ret; - ret = drm_buffer_object_create(dev, size, drm_bo_type_device, + ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel, 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); @@ -1540,7 +1526,7 @@ static int radeon_gem_dma_bufs_init(struct drm_device *dev) DRM_DEBUG("\n"); radeon_gem_addbufs(dev); - DRM_DEBUG("%x %d\n", dev_priv->mm.dma_bufs.bo->map_list.hash.key, size); + DRM_DEBUG("%lx %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; diff --git a/linux-core/radeon_gem_proc.c b/linux-core/radeon_gem_proc.c new file mode 100644 index 00000000..04f5a5fc --- /dev/null +++ b/linux-core/radeon_gem_proc.c @@ -0,0 +1,146 @@ +/* + * Copyright © 2008 Intel Corporation + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Eric Anholt <eric@anholt.net> + * Keith Packard <keithp@keithp.com> + * + */ + +#include "drmP.h" +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_drv.h" + + +static int radeon_ring_info(char *buf, char **start, off_t offset, + int request, int *eof, void *data) +{ + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + int len = 0; + + if (offset > DRM_PROC_LIMIT) { + *eof = 1; + return 0; + } + + *start = &buf[offset]; + *eof = 0; + DRM_PROC_PRINT("RADEON_CP_RB_WPTR %08x\n", + RADEON_READ(RADEON_CP_RB_WPTR)); + + DRM_PROC_PRINT("RADEON_CP_RB_RPTR %08x\n", + RADEON_READ(RADEON_CP_RB_RPTR)); + + + if (len > request + offset) + return request; + *eof = 1; + return len - offset; +} + +static int radeon_interrupt_info(char *buf, char **start, off_t offset, + int request, int *eof, void *data) +{ + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + int len = 0; + + if (offset > DRM_PROC_LIMIT) { + *eof = 1; + return 0; + } + + *start = &buf[offset]; + *eof = 0; + DRM_PROC_PRINT("Interrupt enable: %08x\n", + RADEON_READ(RADEON_GEN_INT_CNTL)); + + if (dev_priv->chip_family >= CHIP_RS690) { + DRM_PROC_PRINT("DxMODE_INT_MASK: %08x\n", + RADEON_READ(R500_DxMODE_INT_MASK)); + } + DRM_PROC_PRINT("Interrupts received: %d\n", + atomic_read(&dev_priv->irq_received)); + DRM_PROC_PRINT("Current sequence: %d %d\n", + READ_BREADCRUMB(dev_priv), RADEON_READ(RADEON_SCRATCH_REG3)); + DRM_PROC_PRINT("Counter sequence: %d\n", + dev_priv->counter); + if (dev_priv->chip_family >= CHIP_R300) + DRM_PROC_PRINT("CS: %d\n", + GET_SCRATCH(6)); + + + if (len > request + offset) + return request; + *eof = 1; + return len - offset; +} + +static struct drm_proc_list { + /** file name */ + const char *name; + /** proc callback*/ + int (*f) (char *, char **, off_t, int, int *, void *); +} radeon_gem_proc_list[] = { + {"radeon_gem_interrupt", radeon_interrupt_info}, + {"radeon_gem_ring", radeon_ring_info}, +}; + + +#define RADEON_GEM_PROC_ENTRIES ARRAY_SIZE(radeon_gem_proc_list) + +int radeon_gem_proc_init(struct drm_minor *minor) +{ + struct proc_dir_entry *ent; + int i, j; + + for (i = 0; i < RADEON_GEM_PROC_ENTRIES; i++) { + ent = create_proc_entry(radeon_gem_proc_list[i].name, + S_IFREG | S_IRUGO, minor->dev_root); + if (!ent) { + DRM_ERROR("Cannot create /proc/dri/.../%s\n", + radeon_gem_proc_list[i].name); + for (j = 0; j < i; j++) + remove_proc_entry(radeon_gem_proc_list[i].name, + minor->dev_root); + return -1; + } + ent->read_proc = radeon_gem_proc_list[i].f; + ent->data = minor; + } + return 0; +} + +void radeon_gem_proc_cleanup(struct drm_minor *minor) +{ + int i; + + if (!minor->dev_root) + return; + + for (i = 0; i < RADEON_GEM_PROC_ENTRIES; i++) + remove_proc_entry(radeon_gem_proc_list[i].name, minor->dev_root); +} diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index 820bd548..c0a3c0fa 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -231,7 +231,7 @@ static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y) radeon_fb = to_radeon_framebuffer(crtc->fb); - obj = radeon_fb->base.mm_private; + obj = radeon_fb->obj; obj_priv = obj->driver_private; crtc_offset = obj_priv->bo->offset; @@ -654,7 +654,7 @@ static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y) radeon_fb = to_radeon_framebuffer(crtc->fb); - obj = radeon_fb->base.mm_private; + obj = radeon_fb->obj; obj_priv = obj->driver_private; crtc2_offset = obj_priv->bo->offset; diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c index 261501d1..3df89d30 100644 --- a/linux-core/radeon_legacy_encoders.c +++ b/linux-core/radeon_legacy_encoders.c @@ -1070,6 +1070,7 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) 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_R423 || dev_priv->chip_family == CHIP_RV410) tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | R420_TV_DAC_GDACPD | @@ -1095,6 +1096,7 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) 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_R423 || dev_priv->chip_family == CHIP_RV410) tv_dac_cntl |= (R420_TV_DAC_RDACPD | R420_TV_DAC_GDACPD | @@ -1158,6 +1160,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, 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_R423 || dev_priv->chip_family == CHIP_RV410) { tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | RADEON_TV_DAC_BGADJ_MASK | diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h index 64608e35..23de1088 100644 --- a/linux-core/radeon_mode.h +++ b/linux-core/radeon_mode.h @@ -255,6 +255,7 @@ struct radeon_connector { struct radeon_framebuffer { struct drm_framebuffer base; struct drm_bo_kmap_obj kmap_obj; + struct drm_gem_object *obj; }; extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, @@ -323,7 +324,7 @@ extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno); struct drm_framebuffer *radeon_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd, - void *mm_private); + struct drm_gem_object *obj); int radeonfb_probe(struct drm_device *dev); diff --git a/linux-core/radeon_pm.c b/linux-core/radeon_pm.c index 6b1e6f84..259d42da 100644 --- a/linux-core/radeon_pm.c +++ b/linux-core/radeon_pm.c @@ -54,10 +54,10 @@ int radeon_suspend(struct drm_device *dev, pm_message_t state) if (!radeon_fb) continue; - if (!radeon_fb->base.mm_private) + if (!radeon_fb->obj) continue; - radeon_gem_object_unpin(radeon_fb->base.mm_private); + radeon_gem_object_unpin(radeon_fb->obj); } if (!(dev_priv->flags & RADEON_IS_IGP)) @@ -93,7 +93,6 @@ int radeon_resume(struct drm_device *dev) struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb; int i; - u32 tmp; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return 0; @@ -104,10 +103,7 @@ int radeon_resume(struct drm_device *dev) return -1; /* Turn on bus mastering -todo fix properly */ - if (dev_priv->chip_family < CHIP_RV380) { - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - RADEON_WRITE(RADEON_BUS_CNTL, tmp); - } + radeon_enable_bm(dev_priv); DRM_ERROR("\n"); /* on atom cards re init the whole card @@ -179,10 +175,10 @@ int radeon_resume(struct drm_device *dev) if (!radeon_fb) continue; - if (!radeon_fb->base.mm_private) + if (!radeon_fb->obj) continue; - radeon_gem_object_pin(radeon_fb->base.mm_private, + radeon_gem_object_pin(radeon_fb->obj, PAGE_SIZE, RADEON_GEM_DOMAIN_VRAM); } /* blat the mode back in */ diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index b15e8928..f39a7afd 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -356,6 +356,9 @@ void r300_init_reg_flags(struct drm_device *dev) } else { + ADD_RANGE(RADEON_SE_COORD_FMT, 1); + ADD_RANGE(RADEON_SE_CNTL_STATUS, 1); + ADD_RANGE(RADEON_PP_TXFILTER_0, 1); ADD_RANGE(RADEON_PP_TXFORMAT_0, 1); ADD_RANGE(RADEON_PP_TEX_SIZE_0, 1); diff --git a/shared-core/r300_reg.h b/shared-core/r300_reg.h index 9e9cb526..1e4631db 100644 --- a/shared-core/r300_reg.h +++ b/shared-core/r300_reg.h @@ -1353,7 +1353,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */ #define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */ -#define R300_RB3D_AARESOLVE_CTL 0x4E88 +//#define R300_RB3D_AARESOLVE_CTL 0x4E88 /* gap */ /* Guess by Vladimir. diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 190b1432..9a1e0e02 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -120,7 +120,7 @@ void radeon_read_agp_location(drm_radeon_private_t *dev_priv, u32 *agp_lo, u32 * *agp_lo = RADEON_READ(R600_MC_VM_AGP_BOT); *agp_hi = RADEON_READ(R600_MC_VM_AGP_TOP); } else if (dev_priv->chip_family == CHIP_RV515) { - *agp_lo = radeon_read_mc_reg(dev_priv, RV515_MC_FB_LOCATION); + *agp_lo = radeon_read_mc_reg(dev_priv, RV515_MC_AGP_LOCATION); *agp_hi = 0; } else if (dev_priv->chip_family == CHIP_RS600) { *agp_lo = 0; @@ -133,7 +133,7 @@ void radeon_read_agp_location(drm_radeon_private_t *dev_priv, u32 *agp_lo, u32 * *agp_lo = radeon_read_mc_reg(dev_priv, R520_MC_AGP_LOCATION); *agp_hi = 0; } else { - *agp_lo = RADEON_READ(RADEON_MC_FB_LOCATION); + *agp_lo = RADEON_READ(RADEON_MC_AGP_LOCATION); *agp_hi = 0; } } @@ -194,6 +194,24 @@ static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) } } +void radeon_enable_bm(struct drm_radeon_private *dev_priv) +{ + u32 tmp; + /* Turn on bus mastering */ + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { + /* rs600/rs690/rs740 */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { + /* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); + } /* PCIE cards appears to not need this */ +} void radeon_pll_errata_after_index(struct drm_radeon_private *dev_priv) { @@ -573,10 +591,15 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) BEGIN_RING(8); /* isync can only be written through cp on r5xx write it here */ OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); + if (dev_priv->chip_family > CHIP_RV280) + OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + dev_priv->mm_enabled ? 0 : RADEON_ISYNC_CPSCRATCH_IDLEGUI); + else OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D | RADEON_ISYNC_ANY3D_IDLE2D | - RADEON_ISYNC_WAIT_IDLEGUI | - RADEON_ISYNC_CPSCRATCH_IDLEGUI); + RADEON_ISYNC_WAIT_IDLEGUI); RADEON_PURGE_CACHE(); RADEON_PURGE_ZCACHE(); RADEON_WAIT_UNTIL_IDLE(); @@ -686,7 +709,6 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, drm_radeon_private_t * dev_priv) { u32 ring_start, cur_read_ptr; - u32 tmp; /* Initialize the memory controller. With new memory map, the fb location * is not changed, it should have been properly initialized already. Part @@ -791,11 +813,12 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, dev_priv->ring_rptr->handle + (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); - RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); + if (dev_priv->chip_family >= CHIP_R300) + RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7f); + else + RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x1f); - /* Turn on bus mastering */ - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - RADEON_WRITE(RADEON_BUS_CNTL, tmp); + radeon_enable_bm(dev_priv); dev_priv->scratch[0] = 0; RADEON_WRITE(RADEON_LAST_FRAME_REG, 0); @@ -806,6 +829,15 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, dev_priv->scratch[2] = 0; RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); + dev_priv->scratch[3] = 0; + RADEON_WRITE(RADEON_LAST_SWI_REG, 0); + + dev_priv->scratch[4] = 0; + RADEON_WRITE(RADEON_SCRATCH_REG4, 0); + + dev_priv->scratch[6] = 0; + RADEON_WRITE(RADEON_SCRATCH_REG6, 0); + radeon_do_wait_for_idle(dev_priv); /* Sync everything up */ @@ -825,7 +857,7 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, static void radeon_test_writeback(drm_radeon_private_t * dev_priv) { - u32 tmp; + u32 tmp, scratch1_store; void *ring_read_ptr; if (dev_priv->mm.ring_read.bo) @@ -833,6 +865,7 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv) else ring_read_ptr = dev_priv->ring_rptr->handle; + scratch1_store = RADEON_READ(RADEON_SCRATCH_REG1); /* Writeback doesn't seem to work everywhere, test it here and possibly * enable it if it appears to work */ @@ -858,6 +891,9 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv) DRM_INFO("writeback forced off\n"); } + /* write back previous value */ + RADEON_WRITE(RADEON_SCRATCH_REG1, scratch1_store); + if (!dev_priv->writeback_works) { /* Disable writeback to avoid unnecessary bus master transfers */ RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | RADEON_RB_NO_UPDATE); @@ -2353,6 +2389,8 @@ int radeon_modeset_cp_resume(struct drm_device *dev) radeon_do_engine_reset(dev); + radeon_test_writeback(dev_priv); + radeon_do_cp_start(dev_priv); return 0; } @@ -2434,16 +2472,22 @@ int radeon_modeset_agp_init(struct drm_device *dev) ret = drm_agp_enable(dev, mode); if (ret) { - DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode); + DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); return ret; } /* workaround some hw issues */ - if (dev_priv->chip_family <= CHIP_R200) { + if (dev_priv->chip_family < CHIP_R200) { RADEON_WRITE(RADEON_AGP_CNTL, RADEON_READ(RADEON_AGP_CNTL) | 0x000e0000); } return 0; } + +void radeon_modeset_agp_destroy(struct drm_device *dev) +{ + if (dev->agp->acquired) + drm_agp_release(dev); +} #endif int radeon_modeset_cp_init(struct drm_device *dev) @@ -2457,7 +2501,7 @@ int radeon_modeset_cp_init(struct drm_device *dev) dev_priv->writeback_works = 0; if (dev_priv->chip_family > CHIP_R600) - return; + return 0; dev_priv->usec_timeout = RADEON_DEFAULT_CP_TIMEOUT; dev_priv->ring.size = RADEON_DEFAULT_RING_SIZE; @@ -2562,15 +2606,23 @@ int radeon_static_clocks_init(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; - if ((dev_priv->flags & RADEON_IS_MOBILITY) && !radeon_is_avivo(dev_priv)) { - radeon_set_dynamic_clock(dev, radeon_dynclks); - } else if (radeon_is_avivo(dev_priv)) { - if (radeon_dynclks) { - radeon_atom_static_pwrmgt_setup(dev, 1); - radeon_atom_dyn_clk_setup(dev, 1); + if (radeon_dynclks != -1) { + + if (dev_priv->chip_family == CHIP_RS400 || + dev_priv->chip_family == CHIP_RS480) + radeon_dynclks = 0; + + if ((dev_priv->flags & RADEON_IS_MOBILITY) && !radeon_is_avivo(dev_priv)) { + radeon_set_dynamic_clock(dev, radeon_dynclks); + } else if (radeon_is_avivo(dev_priv)) { + if (radeon_dynclks) { + radeon_atom_static_pwrmgt_setup(dev, 1); + radeon_atom_dyn_clk_setup(dev, 1); + } } } - radeon_force_some_clocks(dev); + if (radeon_is_r300(dev_priv) || radeon_is_rv100(dev_priv)) + radeon_force_some_clocks(dev); return 0; } @@ -2617,9 +2669,16 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) DRM_DEBUG("%s card detected\n", ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); - if ((dev_priv->flags & RADEON_IS_AGP) && (radeon_agpmode == -1)) { - DRM_INFO("Forcing AGP to PCI mode\n"); - dev_priv->flags &= ~RADEON_IS_AGP; + if (dev_priv->flags & RADEON_IS_AGP) { + + /* disable AGP for any chips after RV280 if not specified */ + if ((dev_priv->chip_family > CHIP_RV280) && (radeon_agpmode == 0)) + radeon_agpmode = -1; + + if (radeon_agpmode == -1) { + DRM_INFO("Forcing AGP to PCI mode\n"); + dev_priv->flags &= ~RADEON_IS_AGP; + } } @@ -2709,7 +2768,6 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master) void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) { struct drm_radeon_master_private *master_priv = master->driver_priv; - struct drm_radeon_private *dev_priv = dev->dev_private; if (!master_priv) return; @@ -2731,21 +2789,10 @@ void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) */ int radeon_driver_firstopen(struct drm_device *dev) { - int ret; - drm_local_map_t *map; drm_radeon_private_t *dev_priv = dev->dev_private; dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - radeon_gem_mm_init(dev); - - ret = drm_addmap(dev, dev_priv->fb_aper_offset, - drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, - _DRM_WRITE_COMBINING, &map); - if (ret != 0) - return ret; - return 0; } @@ -2757,6 +2804,10 @@ int radeon_driver_unload(struct drm_device *dev) drm_irq_uninstall(dev); radeon_modeset_cleanup(dev); radeon_gem_mm_fini(dev); +#if __OS_HAS_AGP + if (dev_priv->flags & RADEON_IS_AGP) + radeon_modeset_agp_destroy(dev); +#endif } drm_bo_driver_finish(dev); diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index f9147136..3dde321d 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -29,21 +29,165 @@ #include "radeon_drv.h" #include "r300_reg.h" +int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) +{ + struct drm_radeon_cs_parser parser; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_radeon_cs2 *cs = data; + uint32_t cs_id; + struct drm_radeon_cs_chunk __user **chunk_ptr = NULL; + uint64_t *chunk_array; + uint64_t *chunk_array_ptr; + long size; + int r, i; + + /* set command stream id to 0 which is fake id */ + cs_id = 0; + cs->cs_id = cs_id; + + if (dev_priv == NULL) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + if (!cs->num_chunks) { + return 0; + } + + + chunk_array = drm_calloc(cs->num_chunks, sizeof(uint64_t), DRM_MEM_DRIVER); + if (!chunk_array) { + return -ENOMEM; + } + + chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks); + + if (DRM_COPY_FROM_USER(chunk_array, chunk_array_ptr, sizeof(uint64_t)*cs->num_chunks)) { + r = -EFAULT; + goto out; + } + + parser.dev = dev; + parser.file_priv = fpriv; + parser.reloc_index = -1; + parser.ib_index = -1; + parser.num_chunks = cs->num_chunks; + /* copy out the chunk headers */ + parser.chunks = drm_calloc(parser.num_chunks, sizeof(struct drm_radeon_kernel_chunk), DRM_MEM_DRIVER); + if (!parser.chunks) { + return -ENOMEM; + } + + for (i = 0; i < parser.num_chunks; i++) { + struct drm_radeon_cs_chunk user_chunk; + + chunk_ptr = (void __user *)(unsigned long)chunk_array[i]; + + if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))){ + r = -EFAULT; + goto out; + } + parser.chunks[i].chunk_id = user_chunk.chunk_id; + + if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) + parser.reloc_index = i; + + if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_IB) + parser.ib_index = i; + + if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_OLD) { + parser.ib_index = i; + parser.reloc_index = -1; + } + + parser.chunks[i].length_dw = user_chunk.length_dw; + parser.chunks[i].chunk_data = (uint32_t *)(unsigned long)user_chunk.chunk_data; + + parser.chunks[i].kdata = NULL; + size = parser.chunks[i].length_dw * sizeof(uint32_t); + + switch(parser.chunks[i].chunk_id) { + case RADEON_CHUNK_ID_IB: + case RADEON_CHUNK_ID_OLD: + if (size == 0) { + r = -EINVAL; + goto out; + } + case RADEON_CHUNK_ID_RELOCS: + if (size) { + parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER); + if (!parser.chunks[i].kdata) { + r = -ENOMEM; + goto out; + } + + if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) { + r = -EFAULT; + goto out; + } + } else + parser.chunks[i].kdata = NULL; + break; + default: + break; + } + DRM_DEBUG("chunk %d %d %d %p\n", i, parser.chunks[i].chunk_id, parser.chunks[i].length_dw, + parser.chunks[i].chunk_data); + } + + + if (parser.chunks[parser.ib_index].length_dw > (16 * 1024)) { + DRM_ERROR("cs->dwords too big: %d\n", parser.chunks[parser.ib_index].length_dw); + r = -EINVAL; + goto out; + } + + /* get ib */ + r = dev_priv->cs.ib_get(&parser); + if (r) { + DRM_ERROR("ib_get failed\n"); + goto out; + } + + /* now parse command stream */ + r = dev_priv->cs.parse(&parser); + if (r) { + goto out; + } + + /* emit cs id sequence */ + dev_priv->cs.id_emit(&parser, &cs_id); + + cs->cs_id = cs_id; + +out: + dev_priv->cs.ib_free(&parser); + + for (i = 0; i < parser.num_chunks; i++) { + if (parser.chunks[i].kdata) + drm_free(parser.chunks[i].kdata, parser.chunks[i].length_dw * sizeof(uint32_t), DRM_MEM_DRIVER); + } + + drm_free(parser.chunks, sizeof(struct drm_radeon_kernel_chunk)*parser.num_chunks, DRM_MEM_DRIVER); + drm_free(chunk_array, sizeof(uint64_t)*parser.num_chunks, DRM_MEM_DRIVER); + + return r; +} + int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) { + struct drm_radeon_cs_parser parser; 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; + struct drm_radeon_kernel_chunk chunk_fake[1]; /* 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)); + cs->cs_id = cs_id; if (dev_priv == NULL) { DRM_ERROR("called with no initialization\n"); @@ -69,68 +213,89 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) r = -EFAULT; goto out; } + + chunk_fake[0].chunk_id = RADEON_CHUNK_ID_OLD; + chunk_fake[0].length_dw = cs->dwords; + chunk_fake[0].kdata = packets; + + parser.dev = dev; + parser.file_priv = fpriv; + parser.num_chunks = 1; + parser.chunks = chunk_fake; + parser.ib_index = 0; + parser.reloc_index = -1; + /* get ib */ - r = dev_priv->cs.ib_get(dev, &ib, cs->dwords, &card_offset); + r = dev_priv->cs.ib_get(&parser); if (r) { goto out; } /* now parse command stream */ - r = dev_priv->cs.parse(dev, fpriv, ib, packets, cs->dwords); + r = dev_priv->cs.parse(&parser); 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 */ - dev_priv->cs.id_emit(dev, &cs_id); + dev_priv->cs.id_emit(&parser, &cs_id); COMMIT_RING(); - DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + cs->cs_id = cs_id; out: - dev_priv->cs.ib_free(dev, ib, cs->dwords); + dev_priv->cs.ib_free(&parser); drm_free(packets, size, DRM_MEM_DRIVER); 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) +static int radeon_nomm_relocate(struct drm_radeon_cs_parser *parser, uint32_t *reloc, uint32_t *offset) { *offset = reloc[1]; return 0; } #define RELOC_SIZE 2 +#define RELOC_SIZE_NEW 0 #define RADEON_2D_OFFSET_MASK 0x3fffff -static __inline__ int radeon_cs_relocate_packet0(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_radeon_cs_parser *parser, uint32_t offset_dw) { + struct drm_device *dev = parser->dev; 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 hdr, reg, val, packet3_hdr; uint32_t tmp, offset; + struct drm_radeon_kernel_chunk *ib_chunk; int ret; + ib_chunk = &parser->chunks[parser->ib_index]; +// if (parser->reloc_index == -1) +// is_old = 1; + + hdr = ib_chunk->kdata[offset_dw]; + reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + val = ib_chunk->kdata[offset_dw + 1]; + packet3_hdr = ib_chunk->kdata[offset_dw + 2]; + /* 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; + if (parser->reloc_index == -1) { + if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { + DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg); + return -EINVAL; + } + } else { + if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16))) { + DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16), reg); + 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); + ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset); if (ret) return ret; tmp = (val & RADEON_2D_OFFSET_MASK) << 10; @@ -148,7 +313,7 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct case R200_PP_TXOFFSET_1: case RADEON_PP_TXOFFSET_0: case RADEON_PP_TXOFFSET_1: - ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); + ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset); if (ret) return ret; @@ -159,25 +324,32 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct break; } - packets[offset_dw + 1] = val; + ib_chunk->kdata[offset_dw + 1] = val; return 0; } -static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *packets, uint32_t offset_dw) +static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser, + 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; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; + uint32_t hdr, num_dw, reg; uint32_t offset, val, tmp; int ret; + struct drm_radeon_kernel_chunk *ib_chunk; + + ib_chunk = &parser->chunks[parser->ib_index]; +// if (parser->reloc_index == -1) +// is_old = 1; + + hdr = ib_chunk->kdata[offset_dw]; + num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; + reg = hdr & 0xff00; 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); + val = ib_chunk->kdata[offset_dw + 2]; + ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + num_dw + 2, &offset); if (ret) return ret; @@ -187,7 +359,7 @@ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *f offset >>= 10; val |= offset; - packets[offset_dw + 2] = val; + ib_chunk->kdata[offset_dw + 2] = val; } default: return -EINVAL; @@ -195,41 +367,16 @@ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *f return 0; } -static __inline__ int radeon_cs_check_offset(struct drm_device *dev, - uint32_t reg, uint32_t val) +int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) { - 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_ZB_DEPTHOFFSET: - offset = val; - break; - case R300_TX_OFFSET_0: - case R300_TX_OFFSET_0+4: - offset = val & 0xffffffe0; - break; - } - - return 0; -} - -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; - 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; + uint32_t hdr, num_dw, reg; int count_dw = 1; int ret; + hdr = parser->chunks[parser->ib_index].kdata[offset_dw]; + num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; + reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + while (count_dw < num_dw) { /* need to have something like the r300 validation here - list of allowed registers */ @@ -250,7 +397,7 @@ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, return -EINVAL; } - ret = radeon_cs_relocate_packet0(dev, file_priv, packets, offset_dw); + ret = radeon_cs_relocate_packet0(parser, offset_dw); if (ret) return ret; DRM_DEBUG("need to relocate %x %d\n", reg, flags); @@ -269,24 +416,25 @@ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, return 0; } -int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, - void *ib, uint32_t *packets, uint32_t dwords) +int radeon_cs_parse(struct drm_radeon_cs_parser *parser) { - drm_radeon_private_t *dev_priv = dev->dev_private; volatile int rb; - int size_dw = dwords; + struct drm_radeon_kernel_chunk *ib_chunk; /* scan the packet for various things */ - int count_dw = 0; + int count_dw = 0, size_dw; int ret = 0; + ib_chunk = &parser->chunks[parser->ib_index]; + size_dw = ib_chunk->length_dw; + while (count_dw < size_dw && ret == 0) { - int hdr = packets[count_dw]; + int hdr = ib_chunk->kdata[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, file_priv, packets, count_dw); + ret = radeon_cs_packet0(parser, count_dw); break; case RADEON_CP_PACKET1: case RADEON_CP_PACKET2: @@ -299,7 +447,7 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: - radeon_cs_relocate_packet3(dev, file_priv, packets, count_dw); + radeon_cs_relocate_packet3(parser, count_dw); break; case RADEON_CNTL_BITBLT_MULTI: @@ -308,6 +456,7 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, DRM_ERROR("need relocate packet 3 for %x\n", reg); break; + case RADEON_3D_DRAW_IMMD: /* triggers drawing using in-packet vertex data */ 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 */ @@ -329,10 +478,10 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, /* copy the packet into the IB */ - memcpy(ib, packets, dwords * sizeof(uint32_t)); + memcpy(parser->ib, ib_chunk->kdata, ib_chunk->length_dw * sizeof(uint32_t)); /* read back last byte to flush WC buffers */ - rb = readl((ib + (dwords-1) * sizeof(uint32_t))); + rb = readl((parser->ib + (ib_chunk->length_dw-1) * sizeof(uint32_t))); return 0; } @@ -351,51 +500,89 @@ uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon) return (radeon->cs.id_scnt | radeon->cs.id_wcnt); } -void r100_cs_id_emit(struct drm_device *dev, uint32_t *id) +void r100_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id) { - drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; RING_LOCALS; + dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev); /* 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); + BEGIN_RING(10); + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(parser->card_offset); + OUT_RING(parser->chunks[parser->ib_index].length_dw); + OUT_RING(CP_PACKET2()); OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0)); OUT_RING(*id); + OUT_RING_REG(RADEON_LAST_SWI_REG, dev_priv->irq_emitted); + OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); ADVANCE_RING(); + COMMIT_RING(); + } -void r300_cs_id_emit(struct drm_device *dev, uint32_t *id) +void r300_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id) { - drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; + int i; RING_LOCALS; + dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev); + /* ISYNC_CNTL should not have CPSCRACTH bit set */ *id = radeon_cs_id_get(dev_priv); + /* emit id in SCRATCH6 */ - BEGIN_RING(8); - OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0)); + BEGIN_RING(16); + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(parser->card_offset); + OUT_RING(parser->chunks[parser->ib_index].length_dw); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(0); + for (i = 0; i < 11; i++) /* emit fillers like fglrx */ + OUT_RING(CP_PACKET2()); + ADVANCE_RING(); + COMMIT_RING(); + + BEGIN_RING(16); + OUT_RING_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH); + OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1)); 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); + OUT_RING_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FINISH|R300_RB3D_DC_FLUSH); + /* emit inline breadcrumb for TTM fencing */ +#if 1 RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING_REG(RADEON_LAST_SWI_REG, dev_priv->irq_emitted); +#else + OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1)); + OUT_RING(3); /* breadcrumb register */ + OUT_RING(dev_priv->irq_emitted); + OUT_RING(CP_PACKET2()); +#endif + OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); ADVANCE_RING(); + COMMIT_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); + return GET_SCRATCH(4); } 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); + return GET_SCRATCH(6); } int radeon_cs_init(struct drm_device *dev) diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index c924c689..002e4004 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -511,9 +511,10 @@ typedef struct { #define DRM_RADEON_GEM_PREAD 0x21 #define DRM_RADEON_GEM_PWRITE 0x22 #define DRM_RADEON_GEM_SET_DOMAIN 0x23 -#define DRM_RADEON_GEM_INDIRECT 0x24 // temporary for X server +#define DRM_RADEON_GEM_WAIT_RENDERING 0x24 #define DRM_RADEON_CS 0x25 +#define DRM_RADEON_CS2 0x26 #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) @@ -551,9 +552,9 @@ typedef struct { #define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread) #define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite) #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_GEM_WAIT_RENDERING DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_RENDERING, struct drm_radeon_gem_wait_rendering) #define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) +#define DRM_IOCTL_RADEON_CS2 DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS2, struct drm_radeon_cs2) typedef struct drm_radeon_init { @@ -820,7 +821,8 @@ struct drm_radeon_gem_set_domain { uint32_t write_domain; }; -struct drm_radeon_gem_exec_buffer { +struct drm_radeon_gem_wait_rendering { + uint32_t handle; }; struct drm_radeon_gem_pin { @@ -864,21 +866,32 @@ struct drm_radeon_gem_pwrite { uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ }; -struct drm_radeon_gem_indirect { - uint32_t handle; - 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; +}; + +#define RADEON_CHUNK_ID_RELOCS 0x01 +#define RADEON_CHUNK_ID_IB 0x02 +#define RADEON_CHUNK_ID_OLD 0xff + +struct drm_radeon_cs_chunk { + uint32_t chunk_id; + uint32_t length_dw; + uint64_t chunk_data; +}; +struct drm_radeon_cs2 { + uint32_t num_chunks; + uint32_t cs_id; + uint64_t chunks; /* this points to uint64_t * which point to + cs chunks */ }; diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index a6ce129d..a95ab152 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -124,6 +124,7 @@ enum radeon_family { CHIP_RV350, CHIP_RV380, CHIP_R420, + CHIP_R423, CHIP_RV410, CHIP_RS400, CHIP_RS480, @@ -294,6 +295,24 @@ struct drm_radeon_master_private { #define RADEON_FLUSH_EMITED (1 < 0) #define RADEON_PURGE_EMITED (1 < 1) +struct drm_radeon_kernel_chunk { + uint32_t chunk_id; + uint32_t length_dw; + uint32_t __user *chunk_data; + uint32_t *kdata; +}; + +struct drm_radeon_cs_parser { + struct drm_device *dev; + struct drm_file *file_priv; + uint32_t num_chunks; + struct drm_radeon_kernel_chunk *chunks; + int ib_index; + int reloc_index; + uint32_t card_offset; + void *ib; +}; + /* command submission struct */ struct drm_radeon_cs_priv { uint32_t id_wcnt; @@ -301,21 +320,22 @@ struct drm_radeon_cs_priv { uint32_t id_last_wcnt; uint32_t id_last_scnt; - 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); + int (*parse)(struct drm_radeon_cs_parser *parser); + void (*id_emit)(struct drm_radeon_cs_parser *parser, 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 *card_offset); + int (*ib_get)(struct drm_radeon_cs_parser *parser); uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib); - void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords); + void (*ib_free)(struct drm_radeon_cs_parser *parser); /* do a relocation either MM or non-MM */ - int (*relocate)(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *reloc, uint32_t *offset); + int (*relocate)(struct drm_radeon_cs_parser *parser, + uint32_t *reloc, uint32_t *offset); }; + + struct radeon_pm_regs { uint32_t crtc_ext_cntl; uint32_t bios_scratch[8]; @@ -441,6 +461,11 @@ typedef struct drm_radeon_private { struct drm_radeon_cs_priv cs; struct radeon_pm_regs pmregs; + int irq_emitted; + atomic_t irq_received; + + uint32_t aper_size; + int vram_mtrr; } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { @@ -460,6 +485,7 @@ extern int radeon_r4xx_atom; extern struct drm_ioctl_desc radeon_ioctls[]; extern int radeon_max_ioctl; extern int radeon_agpmode; +extern int radeon_modeset; /* Check whether the given hardware address is inside the framebuffer or the * GART area. @@ -572,7 +598,11 @@ int radeon_resume(struct drm_device *dev); # define RADEON_SCISSOR_2_ENABLE (1 << 30) #define RADEON_BUS_CNTL 0x0030 +/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ # define RADEON_BUS_MASTER_DIS (1 << 6) +/* rs600/rs690/rs740 */ +# define RS600_BUS_MASTER_DIS (1 << 14) +# define RS600_MSI_REARM (1 << 20) #define RADEON_CLOCK_CNTL_DATA 0x000c # define RADEON_PLL_WR_EN (1 << 7) @@ -732,11 +762,11 @@ int radeon_resume(struct drm_device *dev); #define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) -#define GET_SCRATCH( x ) (dev_priv->writeback_works ? \ - (dev_priv->mm.ring_read.bo ? \ - readl(dev_priv->mm.ring_read.kmap.virtual + RADEON_SCRATCHOFF(x)) : \ - DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(x))) : \ - RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x))) +#define GET_SCRATCH( x ) (dev_priv->writeback_works ? \ + (dev_priv->mm.ring_read.bo ? \ + readl(dev_priv->mm.ring_read.kmap.virtual + RADEON_SCRATCHOFF(x)) : \ + DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(x))) : \ + RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x))) #define RADEON_CRTC_CRNT_FRAME 0x0214 #define RADEON_CRTC2_CRNT_FRAME 0x0314 @@ -1034,6 +1064,7 @@ int radeon_resume(struct drm_device *dev); #define RADEON_AIC_CNTL 0x01d0 # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) +# define RS400_MSI_REARM (1 << 3) #define RADEON_AIC_STAT 0x01d4 #define RADEON_AIC_PT_BASE 0x01d8 #define RADEON_AIC_LO_ADDR 0x01dc @@ -1606,7 +1637,7 @@ extern uint64_t radeon_evict_flags(struct drm_buffer_object *bo); #define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1) /* Breadcrumb - swi irq */ -#define READ_BREADCRUMB(dev_priv) RADEON_READ(RADEON_LAST_SWI_REG) +#define READ_BREADCRUMB(dev_priv) GET_SCRATCH(3) static inline int radeon_update_breadcrumb(struct drm_device *dev) { @@ -1643,6 +1674,7 @@ static inline int radeon_update_breadcrumb(struct drm_device *dev) (dev_priv->chip_family == CHIP_R350) || \ (dev_priv->chip_family == CHIP_RV380) || \ (dev_priv->chip_family == CHIP_R420) || \ + (dev_priv->chip_family == CHIP_R423) || \ (dev_priv->chip_family == CHIP_RV410) || \ (dev_priv->chip_family == CHIP_RS400) || \ (dev_priv->chip_family == CHIP_RS480)) @@ -1668,10 +1700,10 @@ extern int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment, uint32_t pin_domain); int radeon_gem_object_unpin(struct drm_gem_object *obj); -int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int radeon_gem_wait_rendering(struct drm_device *dev, void *data, + struct drm_file *file_priv); struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, int alignment, int initial_domain, bool discardable); int radeon_modeset_init(struct drm_device *dev); @@ -1687,11 +1719,14 @@ extern int radeon_master_create(struct drm_device *dev, struct drm_master *maste 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_cs2_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); void radeon_init_memory_map(struct drm_device *dev); +void radeon_enable_bm(struct drm_radeon_private *dev_priv); - +extern int radeon_gem_proc_init(struct drm_minor *minor); +extern void radeon_gem_proc_cleanup(struct drm_minor *minor); #define MARK_SAFE 1 #define MARK_CHECK_OFFSET 2 #define MARK_CHECK_SCISSOR 3 diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index dcf58e43..46a27943 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -195,6 +195,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) if (!stat) return IRQ_NONE; + atomic_inc(&dev_priv->irq_received); stat &= dev_priv->irq_enable_reg; /* SW interrupt */ @@ -222,15 +223,19 @@ int radeon_emit_irq(struct drm_device * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; unsigned int ret; + int i; RING_LOCALS; - ret = radeon_update_breadcrumb(dev); + if (!dev_priv->irq_emitted) { + ret = radeon_update_breadcrumb(dev); - BEGIN_RING(4); - OUT_RING_REG(RADEON_LAST_SWI_REG, ret); - OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); - ADVANCE_RING(); - COMMIT_RING(); + BEGIN_RING(4); + OUT_RING_REG(RADEON_LAST_SWI_REG, ret); + OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); + ADVANCE_RING(); + COMMIT_RING(); + } else + ret = dev_priv->irq_emitted; return ret; } diff --git a/shared-core/radeon_mem.c b/shared-core/radeon_mem.c index dbd73c50..2622cf3c 100644 --- a/shared-core/radeon_mem.c +++ b/shared-core/radeon_mem.c @@ -294,7 +294,7 @@ int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *fi return -EFAULT; if (*heap) { - DRM_ERROR("heap already initialized?"); + DRM_DEBUG("heap already initialized?"); return -EFAULT; } diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 7262b2aa..e0a00f02 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -1884,10 +1884,11 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, OUT_RING((image->width << 16) | height); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); - COMMIT_RING(); radeon_cp_discard_buffer(dev, file_priv->master, buf); + COMMIT_RING(); + /* Update the input parameters for next time */ image->y += height; image->height -= height; @@ -3288,8 +3289,9 @@ struct drm_ioctl_desc radeon_ioctls[] = { DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH), 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_GEM_WAIT_RENDERING, radeon_gem_wait_rendering, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_CS2, radeon_cs2_ioctl, DRM_AUTH), }; int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); |