Skip to content

Commit

Permalink
drm/exynos: changed buffer structure.
Browse files Browse the repository at this point in the history
the purpose of this patch is to consider IOMMU support in the future.
EXYNOS4 SoC supports IOMMU also so the address for DMA could be
physical address with IOMMU or device address with IOMMU.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
  • Loading branch information
Inki Dae committed Nov 15, 2011
1 parent c749366 commit 2c87112
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 133 deletions.
60 changes: 32 additions & 28 deletions drivers/gpu/drm/exynos/exynos_drm_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,80 +27,84 @@
#include "drm.h"

#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_buf.h"

static int lowlevel_buffer_allocate(struct drm_device *dev,
struct exynos_drm_buf_entry *entry)
struct exynos_drm_gem_buf *buffer)
{
DRM_DEBUG_KMS("%s\n", __FILE__);

entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size,
(dma_addr_t *)&entry->paddr, GFP_KERNEL);
if (!entry->paddr) {
buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size,
&buffer->dma_addr, GFP_KERNEL);
if (!buffer->kvaddr) {
DRM_ERROR("failed to allocate buffer.\n");
return -ENOMEM;
}

DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
(unsigned int)entry->vaddr, entry->paddr, entry->size);
DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buffer->kvaddr,
(unsigned long)buffer->dma_addr,
buffer->size);

return 0;
}

static void lowlevel_buffer_deallocate(struct drm_device *dev,
struct exynos_drm_buf_entry *entry)
struct exynos_drm_gem_buf *buffer)
{
DRM_DEBUG_KMS("%s.\n", __FILE__);

if (entry->paddr && entry->vaddr && entry->size)
dma_free_writecombine(dev->dev, entry->size, entry->vaddr,
entry->paddr);
if (buffer->dma_addr && buffer->size)
dma_free_writecombine(dev->dev, buffer->size, buffer->kvaddr,
(dma_addr_t)buffer->dma_addr);
else
DRM_DEBUG_KMS("entry data is null.\n");
DRM_DEBUG_KMS("buffer data are invalid.\n");
}

struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
unsigned int size)
{
struct exynos_drm_buf_entry *entry;
struct exynos_drm_gem_buf *buffer;

DRM_DEBUG_KMS("%s.\n", __FILE__);
DRM_DEBUG_KMS("desired size = 0x%x\n", size);

entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n");
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer) {
DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
return ERR_PTR(-ENOMEM);
}

entry->size = size;
buffer->size = size;

/*
* allocate memory region with size and set the memory information
* to vaddr and paddr of a entry object.
* to vaddr and dma_addr of a buffer object.
*/
if (lowlevel_buffer_allocate(dev, entry) < 0) {
kfree(entry);
entry = NULL;
if (lowlevel_buffer_allocate(dev, buffer) < 0) {
kfree(buffer);
buffer = NULL;
return ERR_PTR(-ENOMEM);
}

return entry;
return buffer;
}

void exynos_drm_buf_destroy(struct drm_device *dev,
struct exynos_drm_buf_entry *entry)
struct exynos_drm_gem_buf *buffer)
{
DRM_DEBUG_KMS("%s.\n", __FILE__);

if (!entry) {
DRM_DEBUG_KMS("entry is null.\n");
if (!buffer) {
DRM_DEBUG_KMS("buffer is null.\n");
return;
}

lowlevel_buffer_deallocate(dev, entry);
lowlevel_buffer_deallocate(dev, buffer);

kfree(entry);
entry = NULL;
kfree(buffer);
buffer = NULL;
}

MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
Expand Down
21 changes: 4 additions & 17 deletions drivers/gpu/drm/exynos/exynos_drm_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,15 @@
#ifndef _EXYNOS_DRM_BUF_H_
#define _EXYNOS_DRM_BUF_H_

/*
* exynos drm buffer entry structure.
*
* @paddr: physical address of allocated memory.
* @vaddr: kernel virtual address of allocated memory.
* @size: size of allocated memory.
*/
struct exynos_drm_buf_entry {
dma_addr_t paddr;
void __iomem *vaddr;
unsigned int size;
};

/* allocate physical memory. */
struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
unsigned int size);

/* get physical memory information of a drm framebuffer. */
struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
/* get memory information of a drm framebuffer. */
struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);

/* remove allocated physical memory. */
void exynos_drm_buf_destroy(struct drm_device *dev,
struct exynos_drm_buf_entry *entry);
struct exynos_drm_gem_buf *buffer);

#endif
47 changes: 14 additions & 33 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,16 @@
#include "drmP.h"
#include "drm_crtc_helper.h"

#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_buf.h"

#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
drm_crtc)

/*
* Exynos specific crtc postion structure.
*
* @fb_x: offset x on a framebuffer to be displyed
* - the unit is screen coordinates.
* @fb_y: offset y on a framebuffer to be displayed
* - the unit is screen coordinates.
* @crtc_x: offset x on hardware screen.
* @crtc_y: offset y on hardware screen.
* @crtc_w: width of hardware screen.
* @crtc_h: height of hardware screen.
*/
struct exynos_drm_crtc_pos {
unsigned int fb_x;
unsigned int fb_y;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_w;
unsigned int crtc_h;
};

/*
* Exynos specific crtc structure.
*
Expand Down Expand Up @@ -89,27 +70,27 @@ static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
exynos_drm_encoder_crtc_commit);
}

static int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
struct drm_framebuffer *fb,
struct drm_display_mode *mode,
struct exynos_drm_crtc_pos *pos)
int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
struct drm_framebuffer *fb,
struct drm_display_mode *mode,
struct exynos_drm_crtc_pos *pos)
{
struct exynos_drm_buf_entry *entry;
struct exynos_drm_gem_buf *buffer;
unsigned int actual_w;
unsigned int actual_h;

entry = exynos_drm_fb_get_buf(fb);
if (!entry) {
DRM_LOG_KMS("entry is null.\n");
buffer = exynos_drm_fb_get_buf(fb);
if (!buffer) {
DRM_LOG_KMS("buffer is null.\n");
return -EFAULT;
}

overlay->paddr = entry->paddr;
overlay->vaddr = entry->vaddr;
overlay->dma_addr = buffer->dma_addr;
overlay->vaddr = buffer->kvaddr;

DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
(unsigned long)overlay->vaddr,
(unsigned long)overlay->paddr);
(unsigned long)overlay->dma_addr);

actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
Expand Down
25 changes: 25 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,29 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);

/*
* Exynos specific crtc postion structure.
*
* @fb_x: offset x on a framebuffer to be displyed
* - the unit is screen coordinates.
* @fb_y: offset y on a framebuffer to be displayed
* - the unit is screen coordinates.
* @crtc_x: offset x on hardware screen.
* @crtc_y: offset y on hardware screen.
* @crtc_w: width of hardware screen.
* @crtc_h: height of hardware screen.
*/
struct exynos_drm_crtc_pos {
unsigned int fb_x;
unsigned int fb_y;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_w;
unsigned int crtc_h;
};

int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
struct drm_framebuffer *fb,
struct drm_display_mode *mode,
struct exynos_drm_crtc_pos *pos);
#endif
6 changes: 3 additions & 3 deletions drivers/gpu/drm/exynos/exynos_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ struct exynos_drm_overlay_ops {
* @scan_flag: interlace or progressive way.
* (it could be DRM_MODE_FLAG_*)
* @bpp: pixel size.(in bit)
* @paddr: bus(accessed by dma) physical memory address to this overlay
* and this is physically continuous.
* @dma_addr: bus(accessed by dma) address to the memory region allocated
* for a overlay.
* @vaddr: virtual memory addresss to this overlay.
* @default_win: a window to be enabled.
* @color_key: color key on or off.
Expand Down Expand Up @@ -108,7 +108,7 @@ struct exynos_drm_overlay {
unsigned int scan_flag;
unsigned int bpp;
unsigned int pitch;
dma_addr_t paddr;
dma_addr_t dma_addr;
void __iomem *vaddr;

bool default_win;
Expand Down
48 changes: 24 additions & 24 deletions drivers/gpu/drm/exynos/exynos_drm_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@
*
* @fb: drm framebuffer obejct.
* @exynos_gem_obj: exynos specific gem object containing a gem object.
* @entry: pointer to exynos drm buffer entry object.
* - containing only the information to physically continuous memory
* region allocated at default framebuffer creation.
* @buffer: pointer to exynos_drm_gem_buffer object.
* - contain the memory information to memory region allocated
* at default framebuffer creation.
*/
struct exynos_drm_fb {
struct drm_framebuffer fb;
struct exynos_drm_gem_obj *exynos_gem_obj;
struct exynos_drm_buf_entry *entry;
struct exynos_drm_gem_buf *buffer;
};

static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
Expand All @@ -65,8 +65,8 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
* default framebuffer has no gem object so
* a buffer of the default framebuffer should be released at here.
*/
if (!exynos_fb->exynos_gem_obj && exynos_fb->entry)
exynos_drm_buf_destroy(fb->dev, exynos_fb->entry);
if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer)
exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer);

kfree(exynos_fb);
exynos_fb = NULL;
Expand Down Expand Up @@ -145,23 +145,23 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
*/
if (!mode_cmd->handle) {
if (!file_priv) {
struct exynos_drm_buf_entry *entry;
struct exynos_drm_gem_buf *buffer;

/*
* in case that file_priv is NULL, it allocates
* only buffer and this buffer would be used
* for default framebuffer.
*/
entry = exynos_drm_buf_create(dev, size);
if (IS_ERR(entry)) {
ret = PTR_ERR(entry);
buffer = exynos_drm_buf_create(dev, size);
if (IS_ERR(buffer)) {
ret = PTR_ERR(buffer);
goto err_buffer;
}

exynos_fb->entry = entry;
exynos_fb->buffer = buffer;

DRM_LOG_KMS("default fb: paddr = 0x%lx, size = 0x%x\n",
(unsigned long)entry->paddr, size);
DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n",
(unsigned long)buffer->dma_addr, size);

goto out;
} else {
Expand Down Expand Up @@ -191,10 +191,10 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
* so that default framebuffer has no its own gem object,
* only its own buffer object.
*/
exynos_fb->entry = exynos_gem_obj->entry;
exynos_fb->buffer = exynos_gem_obj->buffer;

DRM_LOG_KMS("paddr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
(unsigned long)exynos_fb->entry->paddr, size,
DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
(unsigned long)exynos_fb->buffer->dma_addr, size,
(unsigned int)&exynos_gem_obj->base);

out:
Expand Down Expand Up @@ -222,22 +222,22 @@ struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
return exynos_drm_fb_init(file_priv, dev, mode_cmd);
}

struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
struct exynos_drm_buf_entry *entry;
struct exynos_drm_gem_buf *buffer;

DRM_DEBUG_KMS("%s\n", __FILE__);

entry = exynos_fb->entry;
if (!entry)
buffer = exynos_fb->buffer;
if (!buffer)
return NULL;

DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
(unsigned long)entry->vaddr,
(unsigned long)entry->paddr);
DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
(unsigned long)buffer->kvaddr,
(unsigned long)buffer->dma_addr);

return entry;
return buffer;
}

static void exynos_drm_output_poll_changed(struct drm_device *dev)
Expand Down
Loading

0 comments on commit 2c87112

Please sign in to comment.