Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c871127 authored by Inki Dae's avatar Inki Dae
Browse files

drm/exynos: changed buffer structure.



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: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
parent c7493668
Loading
Loading
Loading
Loading
+32 −28
Original line number Diff line number Diff line
@@ -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>");
+4 −17
Original line number Diff line number Diff line
@@ -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
+14 −33
Original line number Diff line number Diff line
@@ -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.
 *
@@ -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,
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);
+25 −0
Original line number Diff line number Diff line
@@ -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
+3 −3
Original line number Diff line number Diff line
@@ -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.
@@ -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;
Loading