diff options
author | Seung-Woo Kim <sw0312.kim@samsung.com> | 2011-12-15 00:36:22 -0500 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2011-12-28 21:21:42 -0500 |
commit | 229d3534f5bd73fe6247a9e2a92ab0ef69fbc980 (patch) | |
tree | 29adacc9826be07a9628ef7fedeb6dc85ca9db63 /drivers/gpu | |
parent | 83052d4d5cd518332440bb4ee63d68bb5f744e0f (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.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 44 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.h | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 4 |
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 @@ | |||
30 | struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev, | 30 | struct 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. */ | ||
34 | struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb); | ||
35 | |||
36 | /* remove allocated physical memory. */ | 33 | /* remove allocated physical memory. */ |
37 | void exynos_drm_buf_destroy(struct drm_device *dev, | 34 | void 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 | ||
39 | struct drm_device; | 40 | struct 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 | */ |
47 | struct exynos_drm_fb { | 46 | struct 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 | ||
52 | static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) | 51 | 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, | |||
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 | ||
76 | static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, | 75 | static 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 | ||
139 | struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb) | 163 | struct 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 | ||
31 | static 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 | |||
31 | struct drm_framebuffer * | 44 | struct drm_framebuffer * |
32 | exynos_drm_framebuffer_init(struct drm_device *dev, | 45 | exynos_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 */ | ||
50 | struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, | ||
51 | int index); | ||
52 | |||
36 | void exynos_drm_mode_config_init(struct drm_device *dev); | 53 | void 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); |