drm/imx: atomic phase 1: Use transitional atomic CRTC and plane helpers
[linux-2.6-block.git] / drivers / gpu / drm / imx / ipuv3-plane.c
1 /*
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>
19 #include <drm/drm_plane_helper.h>
20
21 #include "video/imx-ipu-v3.h"
22 #include "ipuv3-plane.h"
23
24 #define to_ipu_plane(x) container_of(x, struct ipu_plane, base)
25
26 static const uint32_t ipu_plane_formats[] = {
27         DRM_FORMAT_ARGB1555,
28         DRM_FORMAT_XRGB1555,
29         DRM_FORMAT_ABGR1555,
30         DRM_FORMAT_XBGR1555,
31         DRM_FORMAT_RGBA5551,
32         DRM_FORMAT_BGRA5551,
33         DRM_FORMAT_ARGB4444,
34         DRM_FORMAT_ARGB8888,
35         DRM_FORMAT_XRGB8888,
36         DRM_FORMAT_ABGR8888,
37         DRM_FORMAT_XBGR8888,
38         DRM_FORMAT_RGBA8888,
39         DRM_FORMAT_RGBX8888,
40         DRM_FORMAT_BGRA8888,
41         DRM_FORMAT_BGRA8888,
42         DRM_FORMAT_UYVY,
43         DRM_FORMAT_VYUY,
44         DRM_FORMAT_YUYV,
45         DRM_FORMAT_YVYU,
46         DRM_FORMAT_YUV420,
47         DRM_FORMAT_YVU420,
48         DRM_FORMAT_RGB565,
49 };
50
51 int 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
57 int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb)
58 {
59         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;
63         int active, i;
64         int x = state->src_x >> 16;
65         int y = state->src_y >> 16;
66
67         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                 }
73         }
74
75         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
83         eba = cma_obj[0]->paddr + fb->offsets[0] +
84               fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
85
86         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
96         if (fb->pitches[0] != old_fb->pitches[0]) {
97                 DRM_DEBUG_KMS("pitches must not change while plane is enabled.\n");
98                 return -EINVAL;
99         }
100
101         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
117                 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
125                 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
135                 if (old_ubo != ubo || old_vbo != vbo) {
136                         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
150                 if (old_fb->pitches[1] != fb->pitches[1]) {
151                         DRM_DEBUG_KMS("U/V pitches must not change while plane is enabled.\n");
152                         return -EINVAL;
153                 }
154
155                 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
166         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
173 static inline unsigned long
174 drm_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
187 static inline unsigned long
188 drm_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
202 static inline unsigned long
203 drm_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
217 static 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) {
264                 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         }
271 }
272
273 void 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
283 int 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;
311 err_out:
312         ipu_plane_put_resources(ipu_plane);
313
314         return ret;
315 }
316
317 static void ipu_plane_enable(struct ipu_plane *ipu_plane)
318 {
319         if (ipu_plane->dp)
320                 ipu_dp_enable(ipu_plane->ipu);
321         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);
325 }
326
327 static void ipu_plane_disable(struct ipu_plane *ipu_plane)
328 {
329         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);
335         if (ipu_plane->dp)
336                 ipu_dp_disable(ipu_plane->ipu);
337 }
338
339 static 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
345         ipu_plane_disable(ipu_plane);
346
347         return 0;
348 }
349
350 static 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
361 static const struct drm_plane_funcs ipu_plane_funcs = {
362         .update_plane   = drm_plane_helper_update,
363         .disable_plane  = drm_plane_helper_disable,
364         .destroy        = ipu_plane_destroy,
365 };
366
367 static 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
483 static void ipu_plane_atomic_disable(struct drm_plane *plane,
484                                      struct drm_plane_state *old_state)
485 {
486         ipu_disable_plane(plane);
487 }
488
489 static 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
545 static 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
551 struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
552                                  int dma, int dp, unsigned int possible_crtcs,
553                                  enum drm_plane_type type)
554 {
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
571         ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
572                                        &ipu_plane_funcs, ipu_plane_formats,
573                                        ARRAY_SIZE(ipu_plane_formats), type,
574                                        NULL);
575         if (ret) {
576                 DRM_ERROR("failed to initialize plane\n");
577                 kfree(ipu_plane);
578                 return ERR_PTR(ret);
579         }
580
581         drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
582
583         return ipu_plane;
584 }