2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors: Joonyoung Shim <jy0922.shim@samsung.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
14 #include "exynos_drm.h"
15 #include "exynos_drm_drv.h"
16 #include "exynos_drm_encoder.h"
17 #include "exynos_drm_fb.h"
18 #include "exynos_drm_gem.h"
20 #define to_exynos_plane(x) container_of(x, struct exynos_plane, base)
23 struct drm_plane base
;
24 struct exynos_drm_overlay overlay
;
28 static const uint32_t formats
[] = {
35 int exynos_plane_mode_set(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
36 struct drm_framebuffer
*fb
, int crtc_x
, int crtc_y
,
37 unsigned int crtc_w
, unsigned int crtc_h
,
38 uint32_t src_x
, uint32_t src_y
,
39 uint32_t src_w
, uint32_t src_h
)
41 struct exynos_plane
*exynos_plane
= to_exynos_plane(plane
);
42 struct exynos_drm_overlay
*overlay
= &exynos_plane
->overlay
;
43 unsigned int actual_w
;
44 unsigned int actual_h
;
48 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
50 nr
= exynos_drm_format_num_buffers(fb
->pixel_format
);
51 for (i
= 0; i
< nr
; i
++) {
52 struct exynos_drm_gem_buf
*buffer
= exynos_drm_fb_buffer(fb
, i
);
55 DRM_LOG_KMS("buffer is null\n");
59 overlay
->dma_addr
[i
] = buffer
->dma_addr
;
60 overlay
->vaddr
[i
] = buffer
->kvaddr
;
62 DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
63 i
, (unsigned long)overlay
->vaddr
[i
],
64 (unsigned long)overlay
->dma_addr
[i
]);
67 actual_w
= min((unsigned)(crtc
->mode
.hdisplay
- crtc_x
), crtc_w
);
68 actual_h
= min((unsigned)(crtc
->mode
.vdisplay
- crtc_y
), crtc_h
);
70 /* set drm framebuffer data. */
71 overlay
->fb_x
= src_x
;
72 overlay
->fb_y
= src_y
;
73 overlay
->fb_width
= fb
->width
;
74 overlay
->fb_height
= fb
->height
;
75 overlay
->src_width
= src_w
;
76 overlay
->src_height
= src_h
;
77 overlay
->bpp
= fb
->bits_per_pixel
;
78 overlay
->pitch
= fb
->pitches
[0];
79 overlay
->pixel_format
= fb
->pixel_format
;
81 /* set overlay range to be displayed. */
82 overlay
->crtc_x
= crtc_x
;
83 overlay
->crtc_y
= crtc_y
;
84 overlay
->crtc_width
= actual_w
;
85 overlay
->crtc_height
= actual_h
;
87 /* set drm mode data. */
88 overlay
->mode_width
= crtc
->mode
.hdisplay
;
89 overlay
->mode_height
= crtc
->mode
.vdisplay
;
90 overlay
->refresh
= crtc
->mode
.vrefresh
;
91 overlay
->scan_flag
= crtc
->mode
.flags
;
93 DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
94 overlay
->crtc_x
, overlay
->crtc_y
,
95 overlay
->crtc_width
, overlay
->crtc_height
);
97 exynos_drm_fn_encoder(crtc
, overlay
, exynos_drm_encoder_plane_mode_set
);
102 void exynos_plane_commit(struct drm_plane
*plane
)
104 struct exynos_plane
*exynos_plane
= to_exynos_plane(plane
);
105 struct exynos_drm_overlay
*overlay
= &exynos_plane
->overlay
;
107 exynos_drm_fn_encoder(plane
->crtc
, &overlay
->zpos
,
108 exynos_drm_encoder_plane_commit
);
111 void exynos_plane_dpms(struct drm_plane
*plane
, int mode
)
113 struct exynos_plane
*exynos_plane
= to_exynos_plane(plane
);
114 struct exynos_drm_overlay
*overlay
= &exynos_plane
->overlay
;
116 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
118 if (mode
== DRM_MODE_DPMS_ON
) {
119 if (exynos_plane
->enabled
)
122 exynos_drm_fn_encoder(plane
->crtc
, &overlay
->zpos
,
123 exynos_drm_encoder_plane_enable
);
125 exynos_plane
->enabled
= true;
127 if (!exynos_plane
->enabled
)
130 exynos_drm_fn_encoder(plane
->crtc
, &overlay
->zpos
,
131 exynos_drm_encoder_plane_disable
);
133 exynos_plane
->enabled
= false;
138 exynos_update_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
139 struct drm_framebuffer
*fb
, int crtc_x
, int crtc_y
,
140 unsigned int crtc_w
, unsigned int crtc_h
,
141 uint32_t src_x
, uint32_t src_y
,
142 uint32_t src_w
, uint32_t src_h
)
146 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
148 ret
= exynos_plane_mode_set(plane
, crtc
, fb
, crtc_x
, crtc_y
,
149 crtc_w
, crtc_h
, src_x
>> 16, src_y
>> 16,
150 src_w
>> 16, src_h
>> 16);
155 plane
->fb
= crtc
->fb
;
157 exynos_plane_commit(plane
);
158 exynos_plane_dpms(plane
, DRM_MODE_DPMS_ON
);
163 static int exynos_disable_plane(struct drm_plane
*plane
)
165 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
167 exynos_plane_dpms(plane
, DRM_MODE_DPMS_OFF
);
172 static void exynos_plane_destroy(struct drm_plane
*plane
)
174 struct exynos_plane
*exynos_plane
= to_exynos_plane(plane
);
176 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
178 exynos_disable_plane(plane
);
179 drm_plane_cleanup(plane
);
183 static int exynos_plane_set_property(struct drm_plane
*plane
,
184 struct drm_property
*property
,
187 struct drm_device
*dev
= plane
->dev
;
188 struct exynos_plane
*exynos_plane
= to_exynos_plane(plane
);
189 struct exynos_drm_private
*dev_priv
= dev
->dev_private
;
191 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
193 if (property
== dev_priv
->plane_zpos_property
) {
194 exynos_plane
->overlay
.zpos
= val
;
201 static struct drm_plane_funcs exynos_plane_funcs
= {
202 .update_plane
= exynos_update_plane
,
203 .disable_plane
= exynos_disable_plane
,
204 .destroy
= exynos_plane_destroy
,
205 .set_property
= exynos_plane_set_property
,
208 static void exynos_plane_attach_zpos_property(struct drm_plane
*plane
)
210 struct drm_device
*dev
= plane
->dev
;
211 struct exynos_drm_private
*dev_priv
= dev
->dev_private
;
212 struct drm_property
*prop
;
214 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
216 prop
= dev_priv
->plane_zpos_property
;
218 prop
= drm_property_create_range(dev
, 0, "zpos", 0,
223 dev_priv
->plane_zpos_property
= prop
;
226 drm_object_attach_property(&plane
->base
, prop
, 0);
229 struct drm_plane
*exynos_plane_init(struct drm_device
*dev
,
230 unsigned int possible_crtcs
, bool priv
)
232 struct exynos_plane
*exynos_plane
;
235 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
237 exynos_plane
= kzalloc(sizeof(struct exynos_plane
), GFP_KERNEL
);
239 DRM_ERROR("failed to allocate plane\n");
243 err
= drm_plane_init(dev
, &exynos_plane
->base
, possible_crtcs
,
244 &exynos_plane_funcs
, formats
, ARRAY_SIZE(formats
),
247 DRM_ERROR("failed to initialize plane\n");
253 exynos_plane
->overlay
.zpos
= DEFAULT_ZPOS
;
255 exynos_plane_attach_zpos_property(&exynos_plane
->base
);
257 return &exynos_plane
->base
;