blob: fe289fc792f00af022e8832e8a172e2ab2a8f3f3 [file] [log] [blame]
/*
* Copyright (C) 2010, 2012-2013, 2015 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "drmP.h"
#include "mali_drm.h"
#include "mali_drv.h"
#define VIDEO_TYPE 0
#define MEM_TYPE 1
#define MALI_MM_ALIGN_SHIFT 4
#define MALI_MM_ALIGN_MASK ( (1 << MALI_MM_ALIGN_SHIFT) - 1)
static void *mali_sman_mm_allocate(void *private, unsigned long size, unsigned alignment)
{
printk(KERN_ERR "DRM: %s\n", __func__);
return NULL;
}
static void mali_sman_mm_free(void *private, void *ref)
{
printk(KERN_ERR "DRM: %s\n", __func__);
}
static void mali_sman_mm_destroy(void *private)
{
printk(KERN_ERR "DRM: %s\n", __func__);
}
static unsigned long mali_sman_mm_offset(void *private, void *ref)
{
printk(KERN_ERR "DRM: %s\n", __func__);
return ~((unsigned long)ref);
}
static int mali_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_mali_private_t *dev_priv = dev->dev_private;
drm_mali_fb_t *fb = data;
int ret;
printk(KERN_ERR "DRM: %s\n", __func__);
mutex_lock(&dev->struct_mutex);
{
struct drm_sman_mm sman_mm;
sman_mm.private = (void *)0xFFFFFFFF;
sman_mm.allocate = mali_sman_mm_allocate;
sman_mm.free = mali_sman_mm_free;
sman_mm.destroy = mali_sman_mm_destroy;
sman_mm.offset = mali_sman_mm_offset;
ret = drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
}
if (ret)
{
DRM_ERROR("VRAM memory manager initialisation error\n");
mutex_unlock(&dev->struct_mutex);
return ret;
}
dev_priv->vram_initialized = 1;
dev_priv->vram_offset = fb->offset;
mutex_unlock(&dev->struct_mutex);
DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
return 0;
}
static int mali_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, void *data, int pool)
{
drm_mali_private_t *dev_priv = dev->dev_private;
drm_mali_mem_t *mem = data;
int retval = 0;
struct drm_memblock_item *item;
printk(KERN_ERR "DRM: %s\n", __func__);
mutex_lock(&dev->struct_mutex);
if (0 == dev_priv->vram_initialized)
{
DRM_ERROR("Attempt to allocate from uninitialized memory manager.\n");
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
mem->size = (mem->size + MALI_MM_ALIGN_MASK) >> MALI_MM_ALIGN_SHIFT;
item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0,
(unsigned long)file_priv);
mutex_unlock(&dev->struct_mutex);
if (item)
{
mem->offset = dev_priv->vram_offset + (item->mm->offset(item->mm, item->mm_info) << MALI_MM_ALIGN_SHIFT);
mem->free = item->user_hash.key;
mem->size = mem->size << MALI_MM_ALIGN_SHIFT;
}
else
{
mem->offset = 0;
mem->size = 0;
mem->free = 0;
retval = -ENOMEM;
}
DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, mem->offset);
return retval;
}
static int mali_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_mali_private_t *dev_priv = dev->dev_private;
drm_mali_mem_t *mem = data;
int ret;
printk(KERN_ERR "DRM: %s\n", __func__);
mutex_lock(&dev->struct_mutex);
ret = drm_sman_free_key(&dev_priv->sman, mem->free);
mutex_unlock(&dev->struct_mutex);
DRM_DEBUG("free = 0x%lx\n", mem->free);
return ret;
}
static int mali_fb_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
printk(KERN_ERR "DRM: %s\n", __func__);
return mali_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
}
static int mali_ioctl_mem_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_mali_private_t *dev_priv = dev->dev_private;
drm_mali_mem_t *mem = data;
int ret;
dev_priv = dev->dev_private;
printk(KERN_ERR "DRM: %s\n", __func__);
mutex_lock(&dev->struct_mutex);
ret = drm_sman_set_range(&dev_priv->sman, MEM_TYPE, 0, mem->size >> MALI_MM_ALIGN_SHIFT);
if (ret)
{
DRM_ERROR("MEM memory manager initialisation error\n");
mutex_unlock(&dev->struct_mutex);
return ret;
}
mutex_unlock(&dev->struct_mutex);
return 0;
}
static int mali_ioctl_mem_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
printk(KERN_ERR "DRM: %s\n", __func__);
return mali_drm_alloc(dev, file_priv, data, MEM_TYPE);
}
static drm_local_map_t *mem_reg_init(struct drm_device *dev)
{
struct drm_map_list *entry;
drm_local_map_t *map;
printk(KERN_ERR "DRM: %s\n", __func__);
list_for_each_entry(entry, &dev->maplist, head)
{
map = entry->map;
if (!map)
{
continue;
}
if (map->type == _DRM_REGISTERS)
{
return map;
}
}
return NULL;
}
int mali_idle(struct drm_device *dev)
{
drm_mali_private_t *dev_priv = dev->dev_private;
uint32_t idle_reg;
unsigned long end;
int i;
printk(KERN_ERR "DRM: %s\n", __func__);
if (dev_priv->idle_fault)
{
return 0;
}
return 0;
}
void mali_lastclose(struct drm_device *dev)
{
drm_mali_private_t *dev_priv = dev->dev_private;
printk(KERN_ERR "DRM: %s\n", __func__);
if (!dev_priv)
{
return;
}
mutex_lock(&dev->struct_mutex);
drm_sman_cleanup(&dev_priv->sman);
dev_priv->vram_initialized = 0;
dev_priv->mmio = NULL;
mutex_unlock(&dev->struct_mutex);
}
void mali_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv)
{
drm_mali_private_t *dev_priv = dev->dev_private;
printk(KERN_ERR "DRM: %s\n", __func__);
mutex_lock(&dev->struct_mutex);
if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv))
{
mutex_unlock(&dev->struct_mutex);
return;
}
if (dev->driver->dma_quiescent)
{
dev->driver->dma_quiescent(dev);
}
drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
mutex_unlock(&dev->struct_mutex);
return;
}
struct drm_ioctl_desc mali_ioctls[] =
{
DRM_IOCTL_DEF(DRM_MALI_FB_ALLOC, mali_fb_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_MALI_FB_FREE, mali_drm_free, DRM_AUTH),
DRM_IOCTL_DEF(DRM_MALI_MEM_INIT, mali_ioctl_mem_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_MALI_MEM_ALLOC, mali_ioctl_mem_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_MALI_MEM_FREE, mali_drm_free, DRM_AUTH),
DRM_IOCTL_DEF(DRM_MALI_FB_INIT, mali_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
};
int mali_max_ioctl = DRM_ARRAY_SIZE(mali_ioctls);