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: 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>
This commit is contained in:
parent
83052d4d5c
commit
229d3534f5
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
@ -80,20 +79,24 @@ 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;
|
||||
|
||||
buffer = exynos_drm_fb_get_buf(fb);
|
||||
if (!buffer) {
|
||||
DRM_LOG_KMS("buffer is null.\n");
|
||||
return -EFAULT;
|
||||
for (i = 0; i < nr; i++) {
|
||||
buffer = exynos_drm_fb_buffer(fb, i);
|
||||
if (!buffer) {
|
||||
DRM_LOG_KMS("buffer is null\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
overlay->dma_addr[i] = buffer->dma_addr;
|
||||
overlay->vaddr[i] = buffer->kvaddr;
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
overlay->dma_addr = buffer->dma_addr;
|
||||
overlay->vaddr = buffer->kvaddr;
|
||||
|
||||
DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
|
||||
(unsigned long)overlay->vaddr,
|
||||
(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);
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#define MAX_CRTC 2
|
||||
#define MAX_PLANE 5
|
||||
#define MAX_FB_BUFFER 3
|
||||
#define DEFAULT_ZPOS -1
|
||||
|
||||
struct drm_device;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue