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

Commit 229d3534 authored by Seung-Woo Kim's avatar Seung-Woo Kim Committed by Inki Dae
Browse files

drm/exynos: Support multi buffers



These formats(NV12M, NV12MT and YUV420M) have non contiguous  multi
planes, so each plane uses different buffer. The exynos drm should
support multi buffer for them.

Signed-off-by: default avatarSeung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: default avatarJoonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
parent 83052d4d
Loading
Loading
Loading
Loading
+0 −3
Original line number Original line Diff line number Diff line
@@ -30,9 +30,6 @@
struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
		unsigned int size);
		unsigned int size);


/* 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. */
/* remove allocated physical memory. */
void exynos_drm_buf_destroy(struct drm_device *dev,
void exynos_drm_buf_destroy(struct drm_device *dev,
		struct exynos_drm_gem_buf *buffer);
		struct exynos_drm_gem_buf *buffer);
+16 −12
Original line number Original line Diff line number Diff line
@@ -34,7 +34,6 @@
#include "exynos_drm_fb.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_buf.h"


#define to_exynos_crtc(x)	container_of(x, struct exynos_drm_crtc,\
#define to_exynos_crtc(x)	container_of(x, struct exynos_drm_crtc,\
				drm_crtc)
				drm_crtc)
@@ -80,19 +79,23 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
	struct exynos_drm_gem_buf *buffer;
	struct exynos_drm_gem_buf *buffer;
	unsigned int actual_w;
	unsigned int actual_w;
	unsigned int actual_h;
	unsigned int actual_h;
	int nr = exynos_drm_format_num_buffers(fb->pixel_format);
	int i;


	buffer = exynos_drm_fb_get_buf(fb);
	for (i = 0; i < nr; i++) {
		buffer = exynos_drm_fb_buffer(fb, i);
		if (!buffer) {
		if (!buffer) {
		DRM_LOG_KMS("buffer is null.\n");
			DRM_LOG_KMS("buffer is null\n");
			return -EFAULT;
			return -EFAULT;
		}
		}


	overlay->dma_addr = buffer->dma_addr;
		overlay->dma_addr[i] = buffer->dma_addr;
	overlay->vaddr = buffer->kvaddr;
		overlay->vaddr[i] = buffer->kvaddr;


	DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
		DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
			(unsigned long)overlay->vaddr,
				i, (unsigned long)overlay->vaddr[i],
			(unsigned long)overlay->dma_addr);
				(unsigned long)overlay->dma_addr[i]);
	}


	actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
	actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
	actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
	actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
@@ -104,6 +107,7 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
	overlay->fb_height = fb->height;
	overlay->fb_height = fb->height;
	overlay->bpp = fb->bits_per_pixel;
	overlay->bpp = fb->bits_per_pixel;
	overlay->pitch = fb->pitches[0];
	overlay->pitch = fb->pitches[0];
	overlay->pixel_format = fb->pixel_format;


	/* set overlay range to be displayed. */
	/* set overlay range to be displayed. */
	overlay->crtc_x = pos->crtc_x;
	overlay->crtc_x = pos->crtc_x;
+8 −5
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@


#define MAX_CRTC	2
#define MAX_CRTC	2
#define MAX_PLANE	5
#define MAX_PLANE	5
#define MAX_FB_BUFFER	3
#define DEFAULT_ZPOS	-1
#define DEFAULT_ZPOS	-1


struct drm_device;
struct drm_device;
@@ -82,9 +83,10 @@ struct exynos_drm_overlay_ops {
 * @scan_flag: interlace or progressive way.
 * @scan_flag: interlace or progressive way.
 *	(it could be DRM_MODE_FLAG_*)
 *	(it could be DRM_MODE_FLAG_*)
 * @bpp: pixel size.(in bit)
 * @bpp: pixel size.(in bit)
 * @dma_addr: bus(accessed by dma) address to the memory region allocated
 * @pixel_format: fourcc pixel format of this overlay
 *	for a overlay.
 * @dma_addr: array of bus(accessed by dma) address to the memory region
 * @vaddr: virtual memory addresss to this overlay.
 *	      allocated for a overlay.
 * @vaddr: array of virtual memory addresss to this overlay.
 * @zpos: order of overlay layer(z position).
 * @zpos: order of overlay layer(z position).
 * @default_win: a window to be enabled.
 * @default_win: a window to be enabled.
 * @color_key: color key on or off.
 * @color_key: color key on or off.
@@ -112,8 +114,9 @@ struct exynos_drm_overlay {
	unsigned int scan_flag;
	unsigned int scan_flag;
	unsigned int bpp;
	unsigned int bpp;
	unsigned int pitch;
	unsigned int pitch;
	dma_addr_t dma_addr;
	uint32_t pixel_format;
	void __iomem *vaddr;
	dma_addr_t dma_addr[MAX_FB_BUFFER];
	void __iomem *vaddr[MAX_FB_BUFFER];
	int zpos;
	int zpos;


	bool default_win;
	bool default_win;
+36 −8
Original line number Original line Diff line number Diff line
@@ -33,7 +33,6 @@


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


#define to_exynos_fb(x)	container_of(x, struct exynos_drm_fb, fb)
#define to_exynos_fb(x)	container_of(x, struct exynos_drm_fb, fb)
@@ -42,11 +41,11 @@
 * exynos specific framebuffer structure.
 * exynos specific framebuffer structure.
 *
 *
 * @fb: drm framebuffer obejct.
 * @fb: drm framebuffer obejct.
 * @exynos_gem_obj: exynos specific gem object containing a gem object.
 * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
 */
 */
struct exynos_drm_fb {
struct exynos_drm_fb {
	struct drm_framebuffer		fb;
	struct drm_framebuffer		fb;
	struct exynos_drm_gem_obj	*exynos_gem_obj;
	struct exynos_drm_gem_obj	*exynos_gem_obj[MAX_FB_BUFFER];
};
};


static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
@@ -70,7 +69,7 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
	DRM_DEBUG_KMS("%s\n", __FILE__);
	DRM_DEBUG_KMS("%s\n", __FILE__);


	return drm_gem_handle_create(file_priv,
	return drm_gem_handle_create(file_priv,
			&exynos_fb->exynos_gem_obj->base, handle);
			&exynos_fb->exynos_gem_obj[0]->base, handle);
}
}


static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
@@ -112,7 +111,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
	}
	}


	drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
	drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
	exynos_fb->exynos_gem_obj = to_exynos_gem_obj(obj);
	exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);


	return &exynos_fb->fb;
	return &exynos_fb->fb;
}
}
@@ -122,6 +121,10 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
		      struct drm_mode_fb_cmd2 *mode_cmd)
		      struct drm_mode_fb_cmd2 *mode_cmd)
{
{
	struct drm_gem_object *obj;
	struct drm_gem_object *obj;
	struct drm_framebuffer *fb;
	struct exynos_drm_fb *exynos_fb;
	int nr;
	int i;


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


@@ -133,17 +136,42 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,


	drm_gem_object_unreference_unlocked(obj);
	drm_gem_object_unreference_unlocked(obj);


	return exynos_drm_framebuffer_init(dev, mode_cmd, obj);
	fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj);
	if (IS_ERR(fb))
		return fb;

	exynos_fb = to_exynos_fb(fb);
	nr = exynos_drm_format_num_buffers(fb->pixel_format);

	for (i = 1; i < nr; i++) {
		obj = drm_gem_object_lookup(dev, file_priv,
				mode_cmd->handles[i]);
		if (!obj) {
			DRM_ERROR("failed to lookup gem object\n");
			exynos_drm_fb_destroy(fb);
			return ERR_PTR(-ENOENT);
		}

		drm_gem_object_unreference_unlocked(obj);

		exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
	}
	}


struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
	return fb;
}

struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
						int index)
{
{
	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
	struct exynos_drm_gem_buf *buffer;
	struct exynos_drm_gem_buf *buffer;


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


	buffer = exynos_fb->exynos_gem_obj->buffer;
	if (index >= MAX_FB_BUFFER)
		return NULL;

	buffer = exynos_fb->exynos_gem_obj[index]->buffer;
	if (!buffer)
	if (!buffer)
		return NULL;
		return NULL;


+17 −0
Original line number Original line Diff line number Diff line
@@ -28,11 +28,28 @@
#ifndef _EXYNOS_DRM_FB_H_
#ifndef _EXYNOS_DRM_FB_H_
#define _EXYNOS_DRM_FB_H
#define _EXYNOS_DRM_FB_H


static inline int exynos_drm_format_num_buffers(uint32_t format)
{
	switch (format) {
	case DRM_FORMAT_NV12M:
	case DRM_FORMAT_NV12MT:
		return 2;
	case DRM_FORMAT_YUV420M:
		return 3;
	default:
		return 1;
	}
}

struct drm_framebuffer *
struct drm_framebuffer *
exynos_drm_framebuffer_init(struct drm_device *dev,
exynos_drm_framebuffer_init(struct drm_device *dev,
			    struct drm_mode_fb_cmd2 *mode_cmd,
			    struct drm_mode_fb_cmd2 *mode_cmd,
			    struct drm_gem_object *obj);
			    struct drm_gem_object *obj);


/* get memory information of a drm framebuffer */
struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
						 int index);

void exynos_drm_mode_config_init(struct drm_device *dev);
void exynos_drm_mode_config_init(struct drm_device *dev);


#endif
#endif
Loading