aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorSeung-Woo Kim <sw0312.kim@samsung.com>2011-12-15 00:36:22 -0500
committerInki Dae <inki.dae@samsung.com>2011-12-28 21:21:42 -0500
commit229d3534f5bd73fe6247a9e2a92ab0ef69fbc980 (patch)
tree29adacc9826be07a9628ef7fedeb6dc85ca9db63 /drivers/gpu
parent83052d4d5cd518332440bb4ee63d68bb5f744e0f (diff)
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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.h3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c28
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h13
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c44
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.h17
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c4
7 files changed, 81 insertions, 32 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.h b/drivers/gpu/drm/exynos/exynos_drm_buf.h
index 6e91f9caa5db..c913f2bad760 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.h
@@ -30,9 +30,6 @@
30struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev, 30struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
31 unsigned int size); 31 unsigned int size);
32 32
33/* get memory information of a drm framebuffer. */
34struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
35
36/* remove allocated physical memory. */ 33/* remove allocated physical memory. */
37void exynos_drm_buf_destroy(struct drm_device *dev, 34void exynos_drm_buf_destroy(struct drm_device *dev,
38 struct exynos_drm_gem_buf *buffer); 35 struct exynos_drm_gem_buf *buffer);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index e1ce9fd5a160..e3861ac49295 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -34,7 +34,6 @@
34#include "exynos_drm_fb.h" 34#include "exynos_drm_fb.h"
35#include "exynos_drm_encoder.h" 35#include "exynos_drm_encoder.h"
36#include "exynos_drm_gem.h" 36#include "exynos_drm_gem.h"
37#include "exynos_drm_buf.h"
38 37
39#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ 38#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
40 drm_crtc) 39 drm_crtc)
@@ -80,19 +79,23 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
80 struct exynos_drm_gem_buf *buffer; 79 struct exynos_drm_gem_buf *buffer;
81 unsigned int actual_w; 80 unsigned int actual_w;
82 unsigned int actual_h; 81 unsigned int actual_h;
82 int nr = exynos_drm_format_num_buffers(fb->pixel_format);
83 int i;
84
85 for (i = 0; i < nr; i++) {
86 buffer = exynos_drm_fb_buffer(fb, i);
87 if (!buffer) {
88 DRM_LOG_KMS("buffer is null\n");
89 return -EFAULT;
90 }
83 91
84 buffer = exynos_drm_fb_get_buf(fb); 92 overlay->dma_addr[i] = buffer->dma_addr;
85 if (!buffer) { 93 overlay->vaddr[i] = buffer->kvaddr;
86 DRM_LOG_KMS("buffer is null.\n");
87 return -EFAULT;
88 }
89
90 overlay->dma_addr = buffer->dma_addr;
91 overlay->vaddr = buffer->kvaddr;
92 94
93 DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", 95 DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
94 (unsigned long)overlay->vaddr, 96 i, (unsigned long)overlay->vaddr[i],
95 (unsigned long)overlay->dma_addr); 97 (unsigned long)overlay->dma_addr[i]);
98 }
96 99
97 actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w); 100 actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
98 actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h); 101 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,
104 overlay->fb_height = fb->height; 107 overlay->fb_height = fb->height;
105 overlay->bpp = fb->bits_per_pixel; 108 overlay->bpp = fb->bits_per_pixel;
106 overlay->pitch = fb->pitches[0]; 109 overlay->pitch = fb->pitches[0];
110 overlay->pixel_format = fb->pixel_format;
107 111
108 /* set overlay range to be displayed. */ 112 /* set overlay range to be displayed. */
109 overlay->crtc_x = pos->crtc_x; 113 overlay->crtc_x = pos->crtc_x;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 8e8d8f0f8f33..24f4ef48e474 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -34,6 +34,7 @@
34 34
35#define MAX_CRTC 2 35#define MAX_CRTC 2
36#define MAX_PLANE 5 36#define MAX_PLANE 5
37#define MAX_FB_BUFFER 3
37#define DEFAULT_ZPOS -1 38#define DEFAULT_ZPOS -1
38 39
39struct drm_device; 40struct drm_device;
@@ -82,9 +83,10 @@ struct exynos_drm_overlay_ops {
82 * @scan_flag: interlace or progressive way. 83 * @scan_flag: interlace or progressive way.
83 * (it could be DRM_MODE_FLAG_*) 84 * (it could be DRM_MODE_FLAG_*)
84 * @bpp: pixel size.(in bit) 85 * @bpp: pixel size.(in bit)
85 * @dma_addr: bus(accessed by dma) address to the memory region allocated 86 * @pixel_format: fourcc pixel format of this overlay
86 * for a overlay. 87 * @dma_addr: array of bus(accessed by dma) address to the memory region
87 * @vaddr: virtual memory addresss to this overlay. 88 * allocated for a overlay.
89 * @vaddr: array of virtual memory addresss to this overlay.
88 * @zpos: order of overlay layer(z position). 90 * @zpos: order of overlay layer(z position).
89 * @default_win: a window to be enabled. 91 * @default_win: a window to be enabled.
90 * @color_key: color key on or off. 92 * @color_key: color key on or off.
@@ -112,8 +114,9 @@ struct exynos_drm_overlay {
112 unsigned int scan_flag; 114 unsigned int scan_flag;
113 unsigned int bpp; 115 unsigned int bpp;
114 unsigned int pitch; 116 unsigned int pitch;
115 dma_addr_t dma_addr; 117 uint32_t pixel_format;
116 void __iomem *vaddr; 118 dma_addr_t dma_addr[MAX_FB_BUFFER];
119 void __iomem *vaddr[MAX_FB_BUFFER];
117 int zpos; 120 int zpos;
118 121
119 bool default_win; 122 bool default_win;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 8f36ae5e5d71..3733fe6723d3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -33,7 +33,6 @@
33 33
34#include "exynos_drm_drv.h" 34#include "exynos_drm_drv.h"
35#include "exynos_drm_fb.h" 35#include "exynos_drm_fb.h"
36#include "exynos_drm_buf.h"
37#include "exynos_drm_gem.h" 36#include "exynos_drm_gem.h"
38 37
39#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) 38#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb)
@@ -42,11 +41,11 @@
42 * exynos specific framebuffer structure. 41 * exynos specific framebuffer structure.
43 * 42 *
44 * @fb: drm framebuffer obejct. 43 * @fb: drm framebuffer obejct.
45 * @exynos_gem_obj: exynos specific gem object containing a gem object. 44 * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
46 */ 45 */
47struct exynos_drm_fb { 46struct exynos_drm_fb {
48 struct drm_framebuffer fb; 47 struct drm_framebuffer fb;
49 struct exynos_drm_gem_obj *exynos_gem_obj; 48 struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
50}; 49};
51 50
52static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) 51static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
@@ -70,7 +69,7 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
70 DRM_DEBUG_KMS("%s\n", __FILE__); 69 DRM_DEBUG_KMS("%s\n", __FILE__);
71 70
72 return drm_gem_handle_create(file_priv, 71 return drm_gem_handle_create(file_priv,
73 &exynos_fb->exynos_gem_obj->base, handle); 72 &exynos_fb->exynos_gem_obj[0]->base, handle);
74} 73}
75 74
76static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, 75static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
@@ -112,7 +111,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
112 } 111 }
113 112
114 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); 113 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
115 exynos_fb->exynos_gem_obj = to_exynos_gem_obj(obj); 114 exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
116 115
117 return &exynos_fb->fb; 116 return &exynos_fb->fb;
118} 117}
@@ -122,6 +121,10 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
122 struct drm_mode_fb_cmd2 *mode_cmd) 121 struct drm_mode_fb_cmd2 *mode_cmd)
123{ 122{
124 struct drm_gem_object *obj; 123 struct drm_gem_object *obj;
124 struct drm_framebuffer *fb;
125 struct exynos_drm_fb *exynos_fb;
126 int nr;
127 int i;
125 128
126 DRM_DEBUG_KMS("%s\n", __FILE__); 129 DRM_DEBUG_KMS("%s\n", __FILE__);
127 130
@@ -133,17 +136,42 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
133 136
134 drm_gem_object_unreference_unlocked(obj); 137 drm_gem_object_unreference_unlocked(obj);
135 138
136 return exynos_drm_framebuffer_init(dev, mode_cmd, obj); 139 fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj);
140 if (IS_ERR(fb))
141 return fb;
142
143 exynos_fb = to_exynos_fb(fb);
144 nr = exynos_drm_format_num_buffers(fb->pixel_format);
145
146 for (i = 1; i < nr; i++) {
147 obj = drm_gem_object_lookup(dev, file_priv,
148 mode_cmd->handles[i]);
149 if (!obj) {
150 DRM_ERROR("failed to lookup gem object\n");
151 exynos_drm_fb_destroy(fb);
152 return ERR_PTR(-ENOENT);
153 }
154
155 drm_gem_object_unreference_unlocked(obj);
156
157 exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
158 }
159
160 return fb;
137} 161}
138 162
139struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb) 163struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
164 int index)
140{ 165{
141 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); 166 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
142 struct exynos_drm_gem_buf *buffer; 167 struct exynos_drm_gem_buf *buffer;
143 168
144 DRM_DEBUG_KMS("%s\n", __FILE__); 169 DRM_DEBUG_KMS("%s\n", __FILE__);
145 170
146 buffer = exynos_fb->exynos_gem_obj->buffer; 171 if (index >= MAX_FB_BUFFER)
172 return NULL;
173
174 buffer = exynos_fb->exynos_gem_obj[index]->buffer;
147 if (!buffer) 175 if (!buffer)
148 return NULL; 176 return NULL;
149 177
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h
index 8b3e12f97719..3ecb30d93552 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h
@@ -28,11 +28,28 @@
28#ifndef _EXYNOS_DRM_FB_H_ 28#ifndef _EXYNOS_DRM_FB_H_
29#define _EXYNOS_DRM_FB_H 29#define _EXYNOS_DRM_FB_H
30 30
31static inline int exynos_drm_format_num_buffers(uint32_t format)
32{
33 switch (format) {
34 case DRM_FORMAT_NV12M:
35 case DRM_FORMAT_NV12MT:
36 return 2;
37 case DRM_FORMAT_YUV420M:
38 return 3;
39 default:
40 return 1;
41 }
42}
43
31struct drm_framebuffer * 44struct drm_framebuffer *
32exynos_drm_framebuffer_init(struct drm_device *dev, 45exynos_drm_framebuffer_init(struct drm_device *dev,
33 struct drm_mode_fb_cmd2 *mode_cmd, 46 struct drm_mode_fb_cmd2 *mode_cmd,
34 struct drm_gem_object *obj); 47 struct drm_gem_object *obj);
35 48
49/* get memory information of a drm framebuffer */
50struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
51 int index);
52
36void exynos_drm_mode_config_init(struct drm_device *dev); 53void exynos_drm_mode_config_init(struct drm_device *dev);
37 54
38#endif 55#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 26992d3e970f..d7ae29d2f3d6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -34,7 +34,6 @@
34#include "exynos_drm_drv.h" 34#include "exynos_drm_drv.h"
35#include "exynos_drm_fb.h" 35#include "exynos_drm_fb.h"
36#include "exynos_drm_gem.h" 36#include "exynos_drm_gem.h"
37#include "exynos_drm_buf.h"
38 37
39#define MAX_CONNECTOR 4 38#define MAX_CONNECTOR 4
40#define PREFERRED_BPP 32 39#define PREFERRED_BPP 32
@@ -99,7 +98,8 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
99 drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); 98 drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
100 drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); 99 drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
101 100
102 buffer = exynos_drm_fb_get_buf(fb); 101 /* RGB formats use only one buffer */
102 buffer = exynos_drm_fb_buffer(fb, 0);
103 if (!buffer) { 103 if (!buffer) {
104 DRM_LOG_KMS("buffer is null.\n"); 104 DRM_LOG_KMS("buffer is null.\n");
105 return -EFAULT; 105 return -EFAULT;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 95c621018443..777b93c07186 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -313,8 +313,8 @@ static void fimd_win_mode_set(struct device *dev,
313 win_data->ovl_height = overlay->crtc_height; 313 win_data->ovl_height = overlay->crtc_height;
314 win_data->fb_width = overlay->fb_width; 314 win_data->fb_width = overlay->fb_width;
315 win_data->fb_height = overlay->fb_height; 315 win_data->fb_height = overlay->fb_height;
316 win_data->dma_addr = overlay->dma_addr + offset; 316 win_data->dma_addr = overlay->dma_addr[0] + offset;
317 win_data->vaddr = overlay->vaddr + offset; 317 win_data->vaddr = overlay->vaddr[0] + offset;
318 win_data->bpp = overlay->bpp; 318 win_data->bpp = overlay->bpp;
319 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * 319 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
320 (overlay->bpp >> 3); 320 (overlay->bpp >> 3);