kolibrios-gitea/drivers/video/drm/radeon/bitmap.c
Sergey Semyonov (Serge) ab74087413 drm: v3.10
git-svn-id: svn://kolibrios.org@3764 a494cfbc-eb01-0410-851d-a64ba20cac60
2013-07-05 07:43:48 +00:00

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