mirror of
https://github.com/torvalds/linux.git
synced 2024-12-17 00:21:32 +00:00
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,
|
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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
|
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_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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include "exynos_drm_drv.h"
|
#include "exynos_drm_drv.h"
|
||||||
#include "exynos_drm_fb.h"
|
#include "exynos_drm_fb.h"
|
||||||
#include "exynos_drm_gem.h"
|
#include "exynos_drm_gem.h"
|
||||||
#include "exynos_drm_buf.h"
|
|
||||||
|
|
||||||
#define MAX_CONNECTOR 4
|
#define MAX_CONNECTOR 4
|
||||||
#define PREFERRED_BPP 32
|
#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_fix(fbi, fb->pitches[0], fb->depth);
|
||||||
drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
|
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) {
|
if (!buffer) {
|
||||||
DRM_LOG_KMS("buffer is null.\n");
|
DRM_LOG_KMS("buffer is null.\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -313,8 +313,8 @@ static void fimd_win_mode_set(struct device *dev,
|
|||||||
win_data->ovl_height = overlay->crtc_height;
|
win_data->ovl_height = overlay->crtc_height;
|
||||||
win_data->fb_width = overlay->fb_width;
|
win_data->fb_width = overlay->fb_width;
|
||||||
win_data->fb_height = overlay->fb_height;
|
win_data->fb_height = overlay->fb_height;
|
||||||
win_data->dma_addr = overlay->dma_addr + offset;
|
win_data->dma_addr = overlay->dma_addr[0] + offset;
|
||||||
win_data->vaddr = overlay->vaddr + offset;
|
win_data->vaddr = overlay->vaddr[0] + offset;
|
||||||
win_data->bpp = overlay->bpp;
|
win_data->bpp = overlay->bpp;
|
||||||
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
|
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
|
||||||
(overlay->bpp >> 3);
|
(overlay->bpp >> 3);
|
||||||
|
Loading…
Reference in New Issue
Block a user