blob: b85d102f21578d2db4916c4c18c53762eb50b75d [file] [log] [blame]
Philipp Zabelb8d181e2013-10-10 16:18:45 +02001/*
2 * i.MX IPUv3 DP Overlay Planes
3 *
4 * Copyright (C) 2013 Philipp Zabel, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <drm/drmP.h>
17#include <drm/drm_fb_cma_helper.h>
18#include <drm/drm_gem_cma_helper.h>
Liu Ying33f14232016-07-08 17:40:55 +080019#include <drm/drm_plane_helper.h>
Philipp Zabelb8d181e2013-10-10 16:18:45 +020020
Philipp Zabel39b90042013-09-30 16:13:39 +020021#include "video/imx-ipu-v3.h"
Philipp Zabelb8d181e2013-10-10 16:18:45 +020022#include "ipuv3-plane.h"
23
24#define to_ipu_plane(x) container_of(x, struct ipu_plane, base)
25
26static const uint32_t ipu_plane_formats[] = {
Philipp Zabelc639a1c2014-12-12 13:40:38 +010027 DRM_FORMAT_ARGB1555,
Philipp Zabelb8d181e2013-10-10 16:18:45 +020028 DRM_FORMAT_XRGB1555,
Philipp Zabelc639a1c2014-12-12 13:40:38 +010029 DRM_FORMAT_ABGR1555,
Philipp Zabelb8d181e2013-10-10 16:18:45 +020030 DRM_FORMAT_XBGR1555,
Philipp Zabelc639a1c2014-12-12 13:40:38 +010031 DRM_FORMAT_RGBA5551,
32 DRM_FORMAT_BGRA5551,
Lucas Stachcb166a32015-08-04 17:22:06 +020033 DRM_FORMAT_ARGB4444,
Philipp Zabelb8d181e2013-10-10 16:18:45 +020034 DRM_FORMAT_ARGB8888,
35 DRM_FORMAT_XRGB8888,
36 DRM_FORMAT_ABGR8888,
37 DRM_FORMAT_XBGR8888,
Philipp Zabel59d6b712015-04-16 15:56:40 +020038 DRM_FORMAT_RGBA8888,
39 DRM_FORMAT_RGBX8888,
40 DRM_FORMAT_BGRA8888,
41 DRM_FORMAT_BGRA8888,
Philipp Zabel79321312016-02-12 14:35:55 +010042 DRM_FORMAT_UYVY,
43 DRM_FORMAT_VYUY,
Philipp Zabelb8d181e2013-10-10 16:18:45 +020044 DRM_FORMAT_YUYV,
45 DRM_FORMAT_YVYU,
46 DRM_FORMAT_YUV420,
47 DRM_FORMAT_YVU420,
Enrico Jorns33bee522015-11-24 16:29:22 +010048 DRM_FORMAT_RGB565,
Philipp Zabelb8d181e2013-10-10 16:18:45 +020049};
50
51int ipu_plane_irq(struct ipu_plane *ipu_plane)
52{
53 return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
54 IPU_IRQ_EOF);
55}
56
Liu Ying33f14232016-07-08 17:40:55 +080057int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb)
Philipp Zabelb8d181e2013-10-10 16:18:45 +020058{
Liu Ying33f14232016-07-08 17:40:55 +080059 struct drm_gem_cma_object *cma_obj[3], *old_cma_obj[3];
60 struct drm_plane_state *state = ipu_plane->base.state;
61 struct drm_framebuffer *old_fb = state->fb;
62 unsigned long eba, ubo, vbo, old_eba, old_ubo, old_vbo;
Philipp Zabel67ca6b62016-02-23 10:22:51 +010063 int active, i;
Liu Ying33f14232016-07-08 17:40:55 +080064 int x = state->src_x >> 16;
65 int y = state->src_y >> 16;
Philipp Zabelb8d181e2013-10-10 16:18:45 +020066
Philipp Zabel67ca6b62016-02-23 10:22:51 +010067 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
68 cma_obj[i] = drm_fb_cma_get_gem_obj(fb, i);
69 if (!cma_obj[i]) {
70 DRM_DEBUG_KMS("plane %d entry is null.\n", i);
71 return -EFAULT;
72 }
Philipp Zabelb8d181e2013-10-10 16:18:45 +020073 }
74
Liu Ying33f14232016-07-08 17:40:55 +080075 for (i = 0; i < drm_format_num_planes(old_fb->pixel_format); i++) {
76 old_cma_obj[i] = drm_fb_cma_get_gem_obj(old_fb, i);
77 if (!old_cma_obj[i]) {
78 DRM_DEBUG_KMS("plane %d entry is null.\n", i);
79 return -EFAULT;
80 }
81 }
82
Philipp Zabel67ca6b62016-02-23 10:22:51 +010083 eba = cma_obj[0]->paddr + fb->offsets[0] +
Lucas Stachbc2b0672014-01-10 16:17:29 +010084 fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
Philipp Zabel356f9522014-10-08 17:19:14 +020085
Philipp Zabel67ca6b62016-02-23 10:22:51 +010086 if (eba & 0x7) {
87 DRM_DEBUG_KMS("base address must be a multiple of 8.\n");
88 return -EINVAL;
89 }
90
91 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384) {
92 DRM_DEBUG_KMS("pitches out of range.\n");
93 return -EINVAL;
94 }
95
Liu Ying33f14232016-07-08 17:40:55 +080096 if (fb->pitches[0] != old_fb->pitches[0]) {
Philipp Zabel67ca6b62016-02-23 10:22:51 +010097 DRM_DEBUG_KMS("pitches must not change while plane is enabled.\n");
98 return -EINVAL;
99 }
100
Philipp Zabel67ca6b62016-02-23 10:22:51 +0100101 switch (fb->pixel_format) {
102 case DRM_FORMAT_YUV420:
103 case DRM_FORMAT_YVU420:
104 /*
105 * Multiplanar formats have to meet the following restrictions:
106 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
107 * - EBA, UBO and VBO are a multiple of 8
108 * - UBO and VBO are unsigned and not larger than 0xfffff8
109 * - Only EBA may be changed while scanout is active
110 * - The strides of U and V planes must be identical.
111 */
112 ubo = cma_obj[1]->paddr + fb->offsets[1] +
113 fb->pitches[1] * y / 2 + x / 2 - eba;
114 vbo = cma_obj[2]->paddr + fb->offsets[2] +
115 fb->pitches[2] * y / 2 + x / 2 - eba;
116
Liu Ying33f14232016-07-08 17:40:55 +0800117 old_eba = old_cma_obj[0]->paddr + old_fb->offsets[0] +
118 old_fb->pitches[0] * y +
119 (old_fb->bits_per_pixel >> 3) * x;
120 old_ubo = old_cma_obj[1]->paddr + old_fb->offsets[1] +
121 old_fb->pitches[1] * y / 2 + x / 2 - old_eba;
122 old_vbo = old_cma_obj[2]->paddr + old_fb->offsets[2] +
123 old_fb->pitches[2] * y / 2 + x / 2 - old_eba;
124
Philipp Zabel67ca6b62016-02-23 10:22:51 +0100125 if ((ubo & 0x7) || (vbo & 0x7)) {
126 DRM_DEBUG_KMS("U/V buffer offsets must be a multiple of 8.\n");
127 return -EINVAL;
128 }
129
130 if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) {
131 DRM_DEBUG_KMS("U/V buffer offsets must be positive and not larger than 0xfffff8.\n");
132 return -EINVAL;
133 }
134
Liu Ying33f14232016-07-08 17:40:55 +0800135 if (old_ubo != ubo || old_vbo != vbo) {
Philipp Zabel67ca6b62016-02-23 10:22:51 +0100136 DRM_DEBUG_KMS("U/V buffer offsets must not change while plane is enabled.\n");
137 return -EINVAL;
138 }
139
140 if (fb->pitches[1] != fb->pitches[2]) {
141 DRM_DEBUG_KMS("U/V pitches must be identical.\n");
142 return -EINVAL;
143 }
144
145 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) {
146 DRM_DEBUG_KMS("U/V pitches out of range.\n");
147 return -EINVAL;
148 }
149
Liu Ying33f14232016-07-08 17:40:55 +0800150 if (old_fb->pitches[1] != fb->pitches[1]) {
Philipp Zabel67ca6b62016-02-23 10:22:51 +0100151 DRM_DEBUG_KMS("U/V pitches must not change while plane is enabled.\n");
152 return -EINVAL;
153 }
154
Philipp Zabel67ca6b62016-02-23 10:22:51 +0100155 dev_dbg(ipu_plane->base.dev->dev,
156 "phys = %pad %pad %pad, x = %d, y = %d",
157 &cma_obj[0]->paddr, &cma_obj[1]->paddr,
158 &cma_obj[2]->paddr, x, y);
159 break;
160 default:
161 dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
162 &cma_obj[0]->paddr, x, y);
163 break;
164 }
165
Liu Ying33f14232016-07-08 17:40:55 +0800166 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
167 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
168 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
169
170 return 0;
171}
172
173static inline unsigned long
174drm_plane_state_to_eba(struct drm_plane_state *state)
175{
176 struct drm_framebuffer *fb = state->fb;
177 struct drm_gem_cma_object *cma_obj;
178
179 cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
180 BUG_ON(!cma_obj);
181
182 return cma_obj->paddr + fb->offsets[0] +
183 fb->pitches[0] * (state->src_y >> 16) +
184 (fb->bits_per_pixel >> 3) * (state->src_x >> 16);
185}
186
187static inline unsigned long
188drm_plane_state_to_ubo(struct drm_plane_state *state)
189{
190 struct drm_framebuffer *fb = state->fb;
191 struct drm_gem_cma_object *cma_obj;
192 unsigned long eba = drm_plane_state_to_eba(state);
193
194 cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
195 BUG_ON(!cma_obj);
196
197 return cma_obj->paddr + fb->offsets[1] +
198 fb->pitches[1] * (state->src_y >> 16) / 2 +
199 (state->src_x >> 16) / 2 - eba;
200}
201
202static inline unsigned long
203drm_plane_state_to_vbo(struct drm_plane_state *state)
204{
205 struct drm_framebuffer *fb = state->fb;
206 struct drm_gem_cma_object *cma_obj;
207 unsigned long eba = drm_plane_state_to_eba(state);
208
209 cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
210 BUG_ON(!cma_obj);
211
212 return cma_obj->paddr + fb->offsets[2] +
213 fb->pitches[2] * (state->src_y >> 16) / 2 +
214 (state->src_x >> 16) / 2 - eba;
215}
216
217static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane,
218 struct drm_plane_state *old_state)
219{
220 struct drm_plane *plane = &ipu_plane->base;
221 struct drm_plane_state *state = plane->state;
222 struct drm_framebuffer *fb = state->fb;
223 unsigned long eba, ubo, vbo;
224 int active;
225
226 eba = drm_plane_state_to_eba(state);
227
228 switch (fb->pixel_format) {
229 case DRM_FORMAT_YUV420:
230 case DRM_FORMAT_YVU420:
231 if (old_state->fb)
232 break;
233
234 /*
235 * Multiplanar formats have to meet the following restrictions:
236 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
237 * - EBA, UBO and VBO are a multiple of 8
238 * - UBO and VBO are unsigned and not larger than 0xfffff8
239 * - Only EBA may be changed while scanout is active
240 * - The strides of U and V planes must be identical.
241 */
242 ubo = drm_plane_state_to_ubo(state);
243 vbo = drm_plane_state_to_vbo(state);
244
245 if (fb->pixel_format == DRM_FORMAT_YUV420)
246 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
247 fb->pitches[1], ubo, vbo);
248 else
249 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
250 fb->pitches[1], vbo, ubo);
251
252 dev_dbg(ipu_plane->base.dev->dev,
253 "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
254 state->src_x >> 16, state->src_y >> 16);
255 break;
256 default:
257 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
258 eba, state->src_x >> 16, state->src_y >> 16);
259
260 break;
261 }
262
263 if (old_state->fb) {
Philipp Zabel356f9522014-10-08 17:19:14 +0200264 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
265 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
266 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
267 } else {
268 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
269 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
270 }
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200271}
272
273void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
274{
275 if (!IS_ERR_OR_NULL(ipu_plane->dp))
276 ipu_dp_put(ipu_plane->dp);
277 if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
278 ipu_dmfc_put(ipu_plane->dmfc);
279 if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
280 ipu_idmac_put(ipu_plane->ipu_ch);
281}
282
283int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
284{
285 int ret;
286
287 ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
288 if (IS_ERR(ipu_plane->ipu_ch)) {
289 ret = PTR_ERR(ipu_plane->ipu_ch);
290 DRM_ERROR("failed to get idmac channel: %d\n", ret);
291 return ret;
292 }
293
294 ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
295 if (IS_ERR(ipu_plane->dmfc)) {
296 ret = PTR_ERR(ipu_plane->dmfc);
297 DRM_ERROR("failed to get dmfc: ret %d\n", ret);
298 goto err_out;
299 }
300
301 if (ipu_plane->dp_flow >= 0) {
302 ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
303 if (IS_ERR(ipu_plane->dp)) {
304 ret = PTR_ERR(ipu_plane->dp);
305 DRM_ERROR("failed to get dp flow: %d\n", ret);
306 goto err_out;
307 }
308 }
309
310 return 0;
311err_out:
312 ipu_plane_put_resources(ipu_plane);
313
314 return ret;
315}
316
Liu Ying33f14232016-07-08 17:40:55 +0800317static void ipu_plane_enable(struct ipu_plane *ipu_plane)
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200318{
Philipp Zabel285bbb02014-04-14 23:53:20 +0200319 if (ipu_plane->dp)
320 ipu_dp_enable(ipu_plane->ipu);
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200321 ipu_dmfc_enable_channel(ipu_plane->dmfc);
322 ipu_idmac_enable_channel(ipu_plane->ipu_ch);
323 if (ipu_plane->dp)
324 ipu_dp_enable_channel(ipu_plane->dp);
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200325}
326
Liu Ying33f14232016-07-08 17:40:55 +0800327static void ipu_plane_disable(struct ipu_plane *ipu_plane)
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200328{
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200329 ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
330
331 if (ipu_plane->dp)
332 ipu_dp_disable_channel(ipu_plane->dp);
333 ipu_idmac_disable_channel(ipu_plane->ipu_ch);
334 ipu_dmfc_disable_channel(ipu_plane->dmfc);
Philipp Zabel285bbb02014-04-14 23:53:20 +0200335 if (ipu_plane->dp)
336 ipu_dp_disable(ipu_plane->ipu);
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200337}
338
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200339static int ipu_disable_plane(struct drm_plane *plane)
340{
341 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
342
343 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
344
Liu Ying33f14232016-07-08 17:40:55 +0800345 ipu_plane_disable(ipu_plane);
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200346
347 return 0;
348}
349
350static void ipu_plane_destroy(struct drm_plane *plane)
351{
352 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
353
354 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
355
356 ipu_disable_plane(plane);
357 drm_plane_cleanup(plane);
358 kfree(ipu_plane);
359}
360
Liu Ying8b3ce872016-05-24 18:10:40 +0800361static const struct drm_plane_funcs ipu_plane_funcs = {
Liu Ying33f14232016-07-08 17:40:55 +0800362 .update_plane = drm_plane_helper_update,
363 .disable_plane = drm_plane_helper_disable,
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200364 .destroy = ipu_plane_destroy,
365};
366
Liu Ying33f14232016-07-08 17:40:55 +0800367static int ipu_plane_atomic_check(struct drm_plane *plane,
368 struct drm_plane_state *state)
369{
370 struct drm_plane_state *old_state = plane->state;
371 struct drm_crtc_state *crtc_state;
372 struct device *dev = plane->dev->dev;
373 struct drm_framebuffer *fb = state->fb;
374 struct drm_framebuffer *old_fb = old_state->fb;
375 unsigned long eba, ubo, vbo, old_ubo, old_vbo;
376
377 /* Ok to disable */
378 if (!fb)
379 return old_fb ? 0 : -EINVAL;
380
381 /* CRTC should be enabled */
382 if (!state->crtc->enabled)
383 return -EINVAL;
384
385 /* no scaling */
386 if (state->src_w >> 16 != state->crtc_w ||
387 state->src_h >> 16 != state->crtc_h)
388 return -EINVAL;
389
390 crtc_state = state->crtc->state;
391
392 switch (plane->type) {
393 case DRM_PLANE_TYPE_PRIMARY:
394 /* full plane doesn't support partial off screen */
395 if (state->crtc_x || state->crtc_y ||
396 state->crtc_w != crtc_state->adjusted_mode.hdisplay ||
397 state->crtc_h != crtc_state->adjusted_mode.vdisplay)
398 return -EINVAL;
399
400 /* full plane minimum width is 13 pixels */
401 if (state->crtc_w < 13)
402 return -EINVAL;
403 break;
404 case DRM_PLANE_TYPE_OVERLAY:
405 if (state->crtc_x < 0 || state->crtc_y < 0)
406 return -EINVAL;
407
408 if (state->crtc_x + state->crtc_w >
409 crtc_state->adjusted_mode.hdisplay)
410 return -EINVAL;
411 if (state->crtc_y + state->crtc_h >
412 crtc_state->adjusted_mode.vdisplay)
413 return -EINVAL;
414 break;
415 default:
416 dev_warn(dev, "Unsupported plane type\n");
417 return -EINVAL;
418 }
419
420 if (state->crtc_h < 2)
421 return -EINVAL;
422
423 /*
424 * since we cannot touch active IDMAC channels, we do not support
425 * resizing the enabled plane or changing its format
426 */
427 if (old_fb && (state->src_w != old_state->src_w ||
428 state->src_h != old_state->src_h ||
429 fb->pixel_format != old_fb->pixel_format))
430 return -EINVAL;
431
432 eba = drm_plane_state_to_eba(state);
433
434 if (eba & 0x7)
435 return -EINVAL;
436
437 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384)
438 return -EINVAL;
439
440 if (old_fb && fb->pitches[0] != old_fb->pitches[0])
441 return -EINVAL;
442
443 switch (fb->pixel_format) {
444 case DRM_FORMAT_YUV420:
445 case DRM_FORMAT_YVU420:
446 /*
447 * Multiplanar formats have to meet the following restrictions:
448 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
449 * - EBA, UBO and VBO are a multiple of 8
450 * - UBO and VBO are unsigned and not larger than 0xfffff8
451 * - Only EBA may be changed while scanout is active
452 * - The strides of U and V planes must be identical.
453 */
454 ubo = drm_plane_state_to_ubo(state);
455 vbo = drm_plane_state_to_vbo(state);
456
457 if ((ubo & 0x7) || (vbo & 0x7))
458 return -EINVAL;
459
460 if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
461 return -EINVAL;
462
463 if (old_fb) {
464 old_ubo = drm_plane_state_to_ubo(old_state);
465 old_vbo = drm_plane_state_to_vbo(old_state);
466 if (ubo != old_ubo || vbo != old_vbo)
467 return -EINVAL;
468 }
469
470 if (fb->pitches[1] != fb->pitches[2])
471 return -EINVAL;
472
473 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
474 return -EINVAL;
475
476 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
477 return -EINVAL;
478 }
479
480 return 0;
481}
482
483static void ipu_plane_atomic_disable(struct drm_plane *plane,
484 struct drm_plane_state *old_state)
485{
486 ipu_disable_plane(plane);
487}
488
489static void ipu_plane_atomic_update(struct drm_plane *plane,
490 struct drm_plane_state *old_state)
491{
492 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
493 struct drm_plane_state *state = plane->state;
494 enum ipu_color_space ics;
495
496 if (old_state->fb) {
497 ipu_plane_atomic_set_base(ipu_plane, old_state);
498 return;
499 }
500
501 switch (ipu_plane->dp_flow) {
502 case IPU_DP_FLOW_SYNC_BG:
503 ipu_dp_setup_channel(ipu_plane->dp,
504 IPUV3_COLORSPACE_RGB,
505 IPUV3_COLORSPACE_RGB);
506 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
507 break;
508 case IPU_DP_FLOW_SYNC_FG:
509 ics = ipu_drm_fourcc_to_colorspace(state->fb->pixel_format);
510 ipu_dp_setup_channel(ipu_plane->dp, ics,
511 IPUV3_COLORSPACE_UNKNOWN);
512 ipu_dp_set_window_pos(ipu_plane->dp, state->crtc_x,
513 state->crtc_y);
514 /* Enable local alpha on partial plane */
515 switch (state->fb->pixel_format) {
516 case DRM_FORMAT_ARGB1555:
517 case DRM_FORMAT_ABGR1555:
518 case DRM_FORMAT_RGBA5551:
519 case DRM_FORMAT_BGRA5551:
520 case DRM_FORMAT_ARGB4444:
521 case DRM_FORMAT_ARGB8888:
522 case DRM_FORMAT_ABGR8888:
523 case DRM_FORMAT_RGBA8888:
524 case DRM_FORMAT_BGRA8888:
525 ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
526 break;
527 default:
528 break;
529 }
530 }
531
532 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, state->crtc_w);
533
534 ipu_cpmem_zero(ipu_plane->ipu_ch);
535 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, state->src_w >> 16,
536 state->src_h >> 16);
537 ipu_cpmem_set_fmt(ipu_plane->ipu_ch, state->fb->pixel_format);
538 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
539 ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
540 ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
541 ipu_plane_atomic_set_base(ipu_plane, old_state);
542 ipu_plane_enable(ipu_plane);
543}
544
545static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
546 .atomic_check = ipu_plane_atomic_check,
547 .atomic_disable = ipu_plane_atomic_disable,
548 .atomic_update = ipu_plane_atomic_update,
549};
550
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200551struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
552 int dma, int dp, unsigned int possible_crtcs,
Philipp Zabel43895592015-11-06 11:08:02 +0100553 enum drm_plane_type type)
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200554{
555 struct ipu_plane *ipu_plane;
556 int ret;
557
558 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
559 dma, dp, possible_crtcs);
560
561 ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
562 if (!ipu_plane) {
563 DRM_ERROR("failed to allocate plane\n");
564 return ERR_PTR(-ENOMEM);
565 }
566
567 ipu_plane->ipu = ipu;
568 ipu_plane->dma = dma;
569 ipu_plane->dp_flow = dp;
570
Philipp Zabel43895592015-11-06 11:08:02 +0100571 ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
572 &ipu_plane_funcs, ipu_plane_formats,
Ville Syrjäläb0b3b792015-12-09 16:19:55 +0200573 ARRAY_SIZE(ipu_plane_formats), type,
574 NULL);
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200575 if (ret) {
576 DRM_ERROR("failed to initialize plane\n");
577 kfree(ipu_plane);
578 return ERR_PTR(ret);
579 }
580
Liu Ying33f14232016-07-08 17:40:55 +0800581 drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
582
Philipp Zabelb8d181e2013-10-10 16:18:45 +0200583 return ipu_plane;
584}