2 * Copyright (C) ROCKCHIP, Inc.
3 * Author:yzq<yzq@rock-chips.com>
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
16 #include <drm/rockchip_drm.h>
17 #include "rockchip_drm_drv.h"
18 #include "rockchip_drm_encoder.h"
19 #include "rockchip_drm_fb.h"
20 #include "rockchip_drm_gem.h"
22 #define to_rockchip_plane(x) container_of(x, struct rockchip_plane, base)
24 struct rockchip_plane {
25 struct drm_plane base;
26 struct rockchip_drm_overlay overlay;
30 static const uint32_t formats[] = {
38 * This function is to get X or Y size shown via screen. This needs length and
39 * start position of CRTC.
42 * CRTC ----------------
45 * There are six cases from a to f.
47 * <----- SCREEN ----->
49 * ----------|------------------|----------
53 * c --------------------------
58 static int rockchip_plane_get_size(int start, unsigned length, unsigned last)
60 int end = start + length;
65 size = min_t(unsigned, end, last);
66 } else if (start <= last) {
67 size = min_t(unsigned, last - start, length);
73 int rockchip_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
74 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
75 unsigned int crtc_w, unsigned int crtc_h,
76 uint32_t src_x, uint32_t src_y,
77 uint32_t src_w, uint32_t src_h)
79 struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
80 struct rockchip_drm_overlay *overlay = &rockchip_plane->overlay;
81 unsigned int actual_w;
82 unsigned int actual_h;
86 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
88 nr = rockchip_drm_fb_get_buf_cnt(fb);
89 for (i = 0; i < nr; i++) {
90 struct rockchip_drm_gem_buf *buffer = rockchip_drm_fb_buffer(fb, i);
93 DRM_LOG_KMS("buffer is null\n");
97 overlay->dma_addr[i] = buffer->dma_addr;
99 DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
100 i, (unsigned long)overlay->dma_addr[i]);
103 actual_w = rockchip_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay);
104 actual_h = rockchip_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay);
118 /* set drm framebuffer data. */
119 overlay->fb_x = src_x;
120 overlay->fb_y = src_y;
121 overlay->fb_width = fb->width;
122 overlay->fb_height = fb->height;
123 overlay->src_width = src_w;
124 overlay->src_height = src_h;
125 overlay->bpp = fb->bits_per_pixel;
126 overlay->pitch = fb->pitches[0];
127 overlay->pixel_format = fb->pixel_format;
129 /* set overlay range to be displayed. */
130 overlay->crtc_x = crtc_x;
131 overlay->crtc_y = crtc_y;
132 overlay->crtc_width = actual_w;
133 overlay->crtc_height = actual_h;
135 /* set drm mode data. */
136 overlay->mode_width = crtc->mode.hdisplay;
137 overlay->mode_height = crtc->mode.vdisplay;
138 overlay->refresh = crtc->mode.vrefresh;
139 overlay->pixclock = crtc->mode.clock*1000;
140 overlay->scan_flag = crtc->mode.flags;
142 // printk("--->yzq %s crtc->mode->refresh =%d \n",__func__,crtc->mode.vrefresh);
143 DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
144 overlay->crtc_x, overlay->crtc_y,
145 overlay->crtc_width, overlay->crtc_height);
147 rockchip_drm_fn_encoder(crtc, overlay, rockchip_drm_encoder_plane_mode_set);
152 void rockchip_plane_commit(struct drm_plane *plane)
154 struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
155 struct rockchip_drm_overlay *overlay = &rockchip_plane->overlay;
157 rockchip_drm_fn_encoder(plane->crtc, &overlay->zpos,
158 rockchip_drm_encoder_plane_commit);
161 void rockchip_plane_dpms(struct drm_plane *plane, int mode)
163 struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
164 struct rockchip_drm_overlay *overlay = &rockchip_plane->overlay;
166 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
168 if (mode == DRM_MODE_DPMS_ON) {
169 if (rockchip_plane->enabled)
172 rockchip_drm_fn_encoder(plane->crtc, &overlay->zpos,
173 rockchip_drm_encoder_plane_enable);
175 rockchip_plane->enabled = true;
177 if (!rockchip_plane->enabled)
180 rockchip_drm_fn_encoder(plane->crtc, &overlay->zpos,
181 rockchip_drm_encoder_plane_disable);
183 rockchip_plane->enabled = false;
188 rockchip_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
189 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
190 unsigned int crtc_w, unsigned int crtc_h,
191 uint32_t src_x, uint32_t src_y,
192 uint32_t src_w, uint32_t src_h)
196 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
198 ret = rockchip_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
199 crtc_w, crtc_h, src_x >> 16, src_y >> 16,
200 src_w >> 16, src_h >> 16);
206 rockchip_plane_commit(plane);
207 rockchip_plane_dpms(plane, DRM_MODE_DPMS_ON);
212 static int rockchip_disable_plane(struct drm_plane *plane)
214 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
216 rockchip_plane_dpms(plane, DRM_MODE_DPMS_OFF);
221 static void rockchip_plane_destroy(struct drm_plane *plane)
223 struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
225 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
227 rockchip_disable_plane(plane);
228 drm_plane_cleanup(plane);
229 kfree(rockchip_plane);
232 static int rockchip_plane_set_property(struct drm_plane *plane,
233 struct drm_property *property,
236 struct drm_device *dev = plane->dev;
237 struct rockchip_plane *rockchip_plane = to_rockchip_plane(plane);
238 struct rockchip_drm_private *dev_priv = dev->dev_private;
240 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
242 if (property == dev_priv->plane_zpos_property) {
243 rockchip_plane->overlay.zpos = val;
250 static struct drm_plane_funcs rockchip_plane_funcs = {
251 .update_plane = rockchip_update_plane,
252 .disable_plane = rockchip_disable_plane,
253 .destroy = rockchip_plane_destroy,
254 .set_property = rockchip_plane_set_property,
257 static void rockchip_plane_attach_zpos_property(struct drm_plane *plane)
259 struct drm_device *dev = plane->dev;
260 struct rockchip_drm_private *dev_priv = dev->dev_private;
261 struct drm_property *prop;
263 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
265 prop = dev_priv->plane_zpos_property;
267 prop = drm_property_create_range(dev, 0, "zpos", 0,
272 dev_priv->plane_zpos_property = prop;
275 drm_object_attach_property(&plane->base, prop, 0);
278 struct drm_plane *rockchip_plane_init(struct drm_device *dev,
279 unsigned int possible_crtcs, bool priv)
281 struct rockchip_plane *rockchip_plane;
284 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
286 rockchip_plane = kzalloc(sizeof(struct rockchip_plane), GFP_KERNEL);
287 if (!rockchip_plane) {
288 DRM_ERROR("failed to allocate plane\n");
292 err = drm_plane_init(dev, &rockchip_plane->base, possible_crtcs,
293 &rockchip_plane_funcs, formats, ARRAY_SIZE(formats),
296 DRM_ERROR("failed to initialize plane\n");
297 kfree(rockchip_plane);
302 rockchip_plane->overlay.zpos = DEFAULT_ZPOS;
304 rockchip_plane_attach_zpos_property(&rockchip_plane->base);
306 return &rockchip_plane->base;