ab74087413
git-svn-id: svn://kolibrios.org@3764 a494cfbc-eb01-0410-851d-a64ba20cac60
489 lines
11 KiB
C
489 lines
11 KiB
C
|
|
#include <drm/drmP.h>
|
|
#include <drm/radeon_drm.h>
|
|
#include "radeon.h"
|
|
#include "hmm.h"
|
|
#include "bitmap.h"
|
|
|
|
|
|
#define DRIVER_CAPS_0 HW_BIT_BLIT
|
|
|
|
//#define DRIVER_CAPS_0 0
|
|
#define DRIVER_CAPS_1 0
|
|
|
|
struct context *context_map[256];
|
|
|
|
struct hmm bm_mm;
|
|
|
|
extern struct drm_device *main_drm_device;
|
|
|
|
#if 0
|
|
|
|
void __attribute__((regparm(1))) destroy_bitmap(bitmap_t *bitmap)
|
|
{
|
|
// dma_addr_t *pages = bitmap->obj->allocated_pages;
|
|
int i;
|
|
|
|
free_handle(&bm_mm, bitmap->handle);
|
|
bitmap->handle = 0;
|
|
// bitmap->obj->base.read_domains = I915_GEM_DOMAIN_GTT;
|
|
// bitmap->obj->base.write_domain = I915_GEM_DOMAIN_CPU;
|
|
|
|
// mutex_lock(&main_device->struct_mutex);
|
|
// drm_gem_object_unreference(&bitmap->obj->base);
|
|
// mutex_unlock(&main_device->struct_mutex);
|
|
|
|
// if(pages != NULL)
|
|
// {
|
|
// for (i = 0; i < bitmap->page_count; i++)
|
|
// FreePage(pages[i]);
|
|
|
|
// DRM_DEBUG("%s release %d pages\n", __FUNCTION__, bitmap->page_count);
|
|
|
|
// free(pages);
|
|
// };
|
|
UserFree(bitmap->uaddr);
|
|
__DestroyObject(bitmap);
|
|
};
|
|
|
|
static int bitmap_get_pages_gtt(struct drm_i915_gem_object *obj)
|
|
{
|
|
int page_count;
|
|
|
|
/* Get the list of pages out of our struct file. They'll be pinned
|
|
* at this point until we release them.
|
|
*/
|
|
|
|
page_count = obj->base.size / PAGE_SIZE;
|
|
BUG_ON(obj->allocated_pages == NULL);
|
|
BUG_ON(obj->pages.page != NULL);
|
|
|
|
obj->pages.page = obj->allocated_pages;
|
|
obj->pages.nents = page_count;
|
|
|
|
|
|
// if (obj->tiling_mode != I915_TILING_NONE)
|
|
// i915_gem_object_do_bit_17_swizzle(obj);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void bitmap_put_pages_gtt(struct drm_i915_gem_object *obj)
|
|
{
|
|
int ret, i;
|
|
|
|
BUG_ON(obj->madv == __I915_MADV_PURGED);
|
|
|
|
ret = i915_gem_object_set_to_cpu_domain(obj, true);
|
|
if (ret) {
|
|
/* In the event of a disaster, abandon all caches and
|
|
* hope for the best.
|
|
*/
|
|
WARN_ON(ret != -EIO);
|
|
i915_gem_clflush_object(obj);
|
|
obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
|
|
}
|
|
|
|
if (obj->madv == I915_MADV_DONTNEED)
|
|
obj->dirty = 0;
|
|
|
|
obj->dirty = 0;
|
|
}
|
|
|
|
static const struct drm_i915_gem_object_ops bitmap_object_ops = {
|
|
.get_pages = bitmap_get_pages_gtt,
|
|
.put_pages = bitmap_put_pages_gtt,
|
|
};
|
|
|
|
|
|
|
|
struct io_call_10 /* SRV_CREATE_SURFACE */
|
|
{
|
|
u32 handle; // ignored
|
|
void *data; // ignored
|
|
|
|
u32 width;
|
|
u32 height;
|
|
u32 pitch; // ignored
|
|
|
|
u32 max_width;
|
|
u32 max_height;
|
|
u32 format; // reserved mbz
|
|
};
|
|
|
|
|
|
int create_surface(struct drm_device *dev, struct io_call_10 *pbitmap)
|
|
{
|
|
struct radeon_device *rdev = dev->dev_private;
|
|
struct radeon_bo *obj = NULL;
|
|
|
|
bitmap_t *bitmap;
|
|
u32 handle;
|
|
u32 width, max_width;
|
|
u32 height, max_height;
|
|
u32 size, max_size;
|
|
u32 pitch, max_pitch;
|
|
void *uaddr;
|
|
dma_addr_t *pages;
|
|
u32 page_count;
|
|
|
|
int i;
|
|
|
|
int ret;
|
|
|
|
pbitmap->handle = 0;
|
|
pbitmap->data = (void*)-1;
|
|
|
|
width = pbitmap->width;
|
|
height = pbitmap->height;
|
|
|
|
if((width == 0)||(height == 0)||(width > 4096)||(height > 4096))
|
|
goto err1;
|
|
|
|
max_width = (pbitmap->max_width ==0) ? width : pbitmap->max_width;
|
|
max_height = (pbitmap->max_height==0) ? height : pbitmap->max_height;
|
|
|
|
handle = alloc_handle(&bm_mm);
|
|
// printf("%s %d\n",__FUNCTION__, handle);
|
|
|
|
if(handle == 0)
|
|
goto err1;
|
|
|
|
bitmap = CreateObject(GetPid(), sizeof(*bitmap));
|
|
// printf("bitmap %x\n", bitmap);
|
|
if( bitmap == NULL)
|
|
goto err2;
|
|
|
|
bitmap->handle = handle;
|
|
bitmap->header.destroy = destroy_bitmap;
|
|
bitmap->obj = NULL;
|
|
|
|
hmm_set_data(&bm_mm, handle, bitmap);
|
|
|
|
pitch = ALIGN(width*4,64);
|
|
size = roundup(pitch*height, PAGE_SIZE);
|
|
|
|
// printf("pitch %d size %d\n", pitch, size);
|
|
|
|
max_pitch = ALIGN(max_width*4,64);
|
|
max_size = roundup(max_pitch*max_height, PAGE_SIZE);
|
|
|
|
// printf("max_pitch %d max_size %d\n", max_pitch, max_size);
|
|
|
|
ret = radeon_bo_create(rdev, size, PAGE_SIZE, false, RADEON_GEM_DOMAIN_GTT, NULL, &obj);
|
|
|
|
if (unlikely(ret != 0))
|
|
goto err3;
|
|
|
|
ret = radeon_bo_reserve(obj, false);
|
|
if (unlikely(ret != 0))
|
|
goto err3;
|
|
|
|
ret = radeon_bo_pin(obj, RADEON_GEM_DOMAIN_GTT, NULL);
|
|
if (unlikely(ret != 0))
|
|
goto err3;
|
|
|
|
#ifndef __TTM__
|
|
ret = radeon_bo_user_map(obj, (void**)&uaddr);
|
|
if (unlikely(ret != 0))
|
|
goto err3;
|
|
#endif
|
|
|
|
bitmap->page_count = size/PAGE_SIZE;
|
|
bitmap->max_count = max_size/PAGE_SIZE;
|
|
|
|
// DRM_DEBUG("%s alloc %d pages\n", __FUNCTION__, page_count);
|
|
|
|
bitmap->handle = handle;
|
|
bitmap->uaddr = uaddr;
|
|
bitmap->pitch = pitch;
|
|
bitmap->gaddr = radeon_bo_gpu_offset(obj);
|
|
|
|
bitmap->width = width;
|
|
bitmap->height = height;
|
|
bitmap->max_width = max_width;
|
|
bitmap->max_height = max_height;
|
|
|
|
bitmap->obj = obj;
|
|
bitmap->header.destroy = destroy_bitmap;
|
|
|
|
pbitmap->handle = handle;
|
|
pbitmap->data = uaddr;
|
|
pbitmap->pitch = pitch;
|
|
|
|
|
|
DRM_DEBUG("%s handle: %d pitch: %d gpu_addr: %x user_addr: %x\n",
|
|
__FUNCTION__, handle, pitch, bitmap->gaddr, uaddr);
|
|
|
|
return 0;
|
|
|
|
err5:
|
|
// mutex_lock(&dev->struct_mutex);
|
|
// drm_gem_object_unreference(&obj->base);
|
|
// mutex_unlock(&dev->struct_mutex);
|
|
|
|
err4:
|
|
// while (i--)
|
|
// FreePage(pages[i]);
|
|
// free(pages);
|
|
// UserFree(uaddr);
|
|
|
|
err3:
|
|
__DestroyObject(bitmap);
|
|
err2:
|
|
free_handle(&bm_mm, handle);
|
|
err1:
|
|
return -1;
|
|
};
|
|
|
|
|
|
int lock_surface(struct io_call_12 *pbitmap)
|
|
{
|
|
int ret;
|
|
|
|
bitmap_t *bitmap;
|
|
|
|
if(unlikely(pbitmap->handle == 0))
|
|
return -1;
|
|
|
|
bitmap = (bitmap_t*)hmm_get_data(&bm_mm, pbitmap->handle);
|
|
|
|
if(unlikely(bitmap==NULL))
|
|
return -1;
|
|
/*
|
|
mutex_lock(&main_device->struct_mutex);
|
|
ret = i915_gem_object_set_to_cpu_domain(bitmap->obj, true);
|
|
mutex_unlock(&main_device->struct_mutex);
|
|
|
|
if(ret != 0 )
|
|
{
|
|
pbitmap->data = NULL;
|
|
pbitmap->pitch = 0;
|
|
|
|
dbgprintf("%s fail\n", __FUNCTION__);
|
|
return ret;
|
|
};
|
|
*/
|
|
pbitmap->data = bitmap->uaddr;
|
|
pbitmap->pitch = bitmap->pitch;
|
|
|
|
return 0;
|
|
};
|
|
|
|
|
|
#if 0
|
|
|
|
int resize_surface(struct io_call_14 *pbitmap)
|
|
{
|
|
bitmap_t *bitmap;
|
|
dma_addr_t page, *pages;
|
|
u32 size, page_count;
|
|
u32 width, height;
|
|
u32 pitch;
|
|
int i;
|
|
int ret = 0;
|
|
|
|
|
|
if(unlikely(pbitmap->handle == 0))
|
|
return -1;
|
|
|
|
bitmap = (bitmap_t*)hmm_get_data(&bm_mm, pbitmap->handle);
|
|
|
|
if(unlikely(bitmap==NULL))
|
|
return -1;
|
|
|
|
if( pbitmap->new_width > bitmap->max_width ||
|
|
pbitmap->new_height > bitmap->max_height)
|
|
return -1;
|
|
|
|
width = pbitmap->new_width;
|
|
height = pbitmap->new_height;
|
|
|
|
pitch = ALIGN(width*4,64);
|
|
size = roundup(pitch * height, PAGE_SIZE);
|
|
page_count = size/PAGE_SIZE;
|
|
|
|
DRM_DEBUG("new width %d height %d pitch %d size %d\n",
|
|
width, height, pitch, size);
|
|
|
|
if(page_count > bitmap->page_count)
|
|
{
|
|
char *vaddr = bitmap->uaddr + PAGE_SIZE * bitmap->page_count;
|
|
|
|
pages = bitmap->obj->allocated_pages;
|
|
|
|
DRM_DEBUG("old pages %d new_pages %d vaddr %x\n",
|
|
bitmap->page_count, page_count, vaddr);
|
|
|
|
for(i = bitmap->page_count; i < page_count; i++, vaddr+= PAGE_SIZE)
|
|
{
|
|
page = AllocPage();
|
|
if ( page == 0 )
|
|
goto err4;
|
|
pages[i] = page;
|
|
MapPage(vaddr, page, 0x207); //map as shared page
|
|
};
|
|
|
|
DRM_DEBUG("%s alloc %d pages\n", __FUNCTION__,
|
|
page_count - bitmap->page_count);
|
|
|
|
i915_gem_object_unpin(bitmap->obj);
|
|
i915_gem_object_unbind(bitmap->obj);
|
|
bitmap->obj->base.size = size;
|
|
bitmap->obj->pages.nents = page_count;
|
|
|
|
ret = i915_gem_object_pin(bitmap->obj, PAGE_SIZE, true,true);
|
|
if (ret)
|
|
goto err4;
|
|
|
|
bitmap->page_count = page_count;
|
|
bitmap->gaddr = bitmap->obj->gtt_offset;
|
|
}
|
|
else if(page_count < bitmap->page_count)
|
|
{
|
|
char *vaddr = bitmap->uaddr + PAGE_SIZE * page_count;
|
|
|
|
i915_gem_object_unpin(bitmap->obj);
|
|
i915_gem_object_unbind(bitmap->obj);
|
|
|
|
pages = bitmap->obj->allocated_pages;
|
|
|
|
DRM_DEBUG("old pages %d new_pages %d vaddr %x\n",
|
|
bitmap->page_count, page_count, vaddr);
|
|
|
|
for(i = page_count; i < bitmap->page_count; i++, vaddr+= PAGE_SIZE)
|
|
{
|
|
MapPage(vaddr, 0, 0); //unmap
|
|
|
|
FreePage(pages[i]);
|
|
pages[i] = 0;
|
|
};
|
|
|
|
DRM_DEBUG("%s release %d pages\n", __FUNCTION__,
|
|
bitmap->page_count - page_count);
|
|
|
|
bitmap->obj->base.size = size;
|
|
bitmap->obj->pages.nents = page_count;
|
|
|
|
ret = i915_gem_object_pin(bitmap->obj, PAGE_SIZE, true,true);
|
|
if (ret)
|
|
goto err3;
|
|
|
|
bitmap->page_count = page_count;
|
|
bitmap->gaddr = bitmap->obj->gtt_offset;
|
|
};
|
|
|
|
bitmap->width = width;
|
|
bitmap->height = height;
|
|
bitmap->pitch = pitch;
|
|
|
|
|
|
pbitmap->data = bitmap->uaddr;
|
|
pbitmap->pitch = bitmap->pitch;
|
|
|
|
return 0;
|
|
|
|
err4:
|
|
while (i-- > bitmap->page_count)
|
|
FreePage(pages[i]);
|
|
|
|
err3:
|
|
return -1;
|
|
};
|
|
#endif
|
|
|
|
|
|
int init_bitmaps()
|
|
{
|
|
int ret;
|
|
|
|
ret = init_hmm(&bm_mm, 1024);
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
|
|
int get_driver_caps(hwcaps_t *caps)
|
|
{
|
|
int ret = 0;
|
|
|
|
ENTER();
|
|
switch(caps->idx)
|
|
{
|
|
case 0:
|
|
caps->opt[0] = DRIVER_CAPS_0;
|
|
caps->opt[1] = DRIVER_CAPS_1;
|
|
break;
|
|
|
|
case 1:
|
|
caps->cap1.max_tex_width = 4096;
|
|
caps->cap1.max_tex_height = 4096;
|
|
break;
|
|
default:
|
|
ret = 1;
|
|
};
|
|
caps->idx = 1;
|
|
LEAVE();
|
|
return ret;
|
|
}
|
|
|
|
|
|
void __attribute__((regparm(1))) destroy_context(struct context *context)
|
|
{
|
|
struct radeon_device *rdev = main_drm_device->dev_private;
|
|
|
|
DRM_DEBUG("destroy context %x\n", context);
|
|
|
|
context_map[context->slot] = NULL;
|
|
|
|
radeon_ib_free(rdev, &context->ib);
|
|
|
|
__DestroyObject(context);
|
|
};
|
|
|
|
|
|
#define CURRENT_TASK (0x80003000)
|
|
|
|
struct context *get_context(struct drm_device *dev)
|
|
{
|
|
struct radeon_device *rdev = dev->dev_private;
|
|
struct context *context;
|
|
struct io_call_10 io_10;
|
|
int slot = *((u8*)CURRENT_TASK);
|
|
int ret;
|
|
|
|
context = context_map[slot];
|
|
|
|
if( context != NULL)
|
|
return context;
|
|
|
|
context = CreateObject(GetPid(), sizeof(*context));
|
|
|
|
if( context != NULL)
|
|
{
|
|
ret = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &context->ib, NULL, 4096);
|
|
if (ret) {
|
|
DRM_ERROR("radeon: failed to get ib (%d).\n", ret);
|
|
goto err;
|
|
};
|
|
|
|
context->cmd_buffer = context->ib.ptr;
|
|
|
|
context->header.destroy = destroy_context;
|
|
context->mask = NULL;
|
|
context->seqno = 0;
|
|
context->slot = slot;
|
|
|
|
context_map[slot] = context;
|
|
};
|
|
return context;
|
|
|
|
err:
|
|
__DestroyObject(context);
|
|
return NULL;
|
|
};
|
|
|
|
#endif
|
|
|