Skip to content

Commit

Permalink
drm/exynos: Support multi buffers
Browse files Browse the repository at this point in the history
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: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
  • Loading branch information
Seung-Woo Kim authored and Inki Dae committed Dec 29, 2011
1 parent 83052d4 commit 229d353
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 32 deletions.
3 changes: 0 additions & 3 deletions drivers/gpu/drm/exynos/exynos_drm_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@
struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
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. */
void exynos_drm_buf_destroy(struct drm_device *dev,
struct exynos_drm_gem_buf *buffer);
Expand Down
28 changes: 16 additions & 12 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#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)
Expand Down Expand Up @@ -80,19 +79,23 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
struct exynos_drm_gem_buf *buffer;
unsigned int actual_w;
unsigned int actual_h;
int nr = exynos_drm_format_num_buffers(fb->pixel_format);
int i;

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

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

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

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

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

/* set overlay range to be displayed. */
overlay->crtc_x = pos->crtc_x;
Expand Down
13 changes: 8 additions & 5 deletions drivers/gpu/drm/exynos/exynos_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

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

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

bool default_win;
Expand Down
44 changes: 36 additions & 8 deletions drivers/gpu/drm/exynos/exynos_drm_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

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

#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb)
Expand All @@ -42,11 +41,11 @@
* exynos specific framebuffer structure.
*
* @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 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)
Expand All @@ -70,7 +69,7 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
DRM_DEBUG_KMS("%s\n", __FILE__);

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,
Expand Down Expand Up @@ -112,7 +111,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
}

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;
}
Expand All @@ -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_gem_object *obj;
struct drm_framebuffer *fb;
struct exynos_drm_fb *exynos_fb;
int nr;
int i;

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

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

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);
}

return fb;
}

struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *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_gem_buf *buffer;

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)
return NULL;

Expand Down
17 changes: 17 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,28 @@
#ifndef _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 *
exynos_drm_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
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);

#endif
4 changes: 2 additions & 2 deletions drivers/gpu/drm/exynos/exynos_drm_fbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_buf.h"

#define MAX_CONNECTOR 4
#define PREFERRED_BPP 32
Expand Down Expand Up @@ -99,7 +98,8 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);

buffer = exynos_drm_fb_get_buf(fb);
/* RGB formats use only one buffer */
buffer = exynos_drm_fb_buffer(fb, 0);
if (!buffer) {
DRM_LOG_KMS("buffer is null.\n");
return -EFAULT;
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/exynos/exynos_drm_fimd.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,8 @@ static void fimd_win_mode_set(struct device *dev,
win_data->ovl_height = overlay->crtc_height;
win_data->fb_width = overlay->fb_width;
win_data->fb_height = overlay->fb_height;
win_data->dma_addr = overlay->dma_addr + offset;
win_data->vaddr = overlay->vaddr + offset;
win_data->dma_addr = overlay->dma_addr[0] + offset;
win_data->vaddr = overlay->vaddr[0] + offset;
win_data->bpp = overlay->bpp;
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
(overlay->bpp >> 3);
Expand Down

0 comments on commit 229d353

Please sign in to comment.