1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <drm/drmP.h>
19#include <drm/drm_crtc.h>
20#include <drm/drm_fb_cma_helper.h>
21#include <drm/drm_gem_cma_helper.h>
22
23#include <linux/device.h>
24#include <linux/dmaengine.h>
25#include <linux/of_dma.h>
26#include <linux/platform_device.h>
27
28#include "xilinx_drm_dp_sub.h"
29#include "xilinx_drm_drv.h"
30#include "xilinx_drm_fb.h"
31#include "xilinx_drm_plane.h"
32
33#include "xilinx_cresample.h"
34#include "xilinx_osd.h"
35#include "xilinx_rgb2yuv.h"
36
37#define MAX_NUM_SUB_PLANES 4
38
39
40
41
42
43
44
45
46
47struct xilinx_drm_plane_dma {
48 struct dma_chan *chan;
49 struct dma_interleaved_template xt;
50 struct data_chunk sgl[1];
51 bool is_active;
52};
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73struct xilinx_drm_plane {
74 struct drm_plane base;
75 int id;
76 int dpms;
77 unsigned int zpos;
78 unsigned int prio;
79 unsigned int alpha;
80 unsigned int alpha_enable;
81 bool primary;
82 uint32_t format;
83 struct xilinx_drm_plane_dma dma[MAX_NUM_SUB_PLANES];
84 struct xilinx_rgb2yuv *rgb2yuv;
85 struct xilinx_cresample *cresample;
86 struct xilinx_osd_layer *osd_layer;
87 struct xilinx_drm_dp_sub_layer *dp_layer;
88 struct xilinx_drm_plane_manager *manager;
89};
90
91#define MAX_PLANES 8
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109struct xilinx_drm_plane_manager {
110 struct drm_device *drm;
111 struct device_node *node;
112 struct xilinx_osd *osd;
113 struct xilinx_drm_dp_sub *dp_sub;
114 int num_planes;
115 uint32_t format;
116 int max_width;
117 struct drm_property *zpos_prop;
118 struct drm_property *alpha_prop;
119 struct drm_property *alpha_enable_prop;
120 unsigned int default_alpha;
121 struct xilinx_drm_plane *planes[MAX_PLANES];
122};
123
124#define to_xilinx_plane(x) container_of(x, struct xilinx_drm_plane, base)
125
126
127void xilinx_drm_plane_dpms(struct drm_plane *base_plane, int dpms)
128{
129 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
130 struct xilinx_drm_plane_manager *manager = plane->manager;
131 unsigned int i;
132
133 DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
134 DRM_DEBUG_KMS("dpms: %d -> %d\n", plane->dpms, dpms);
135
136 if (plane->dpms == dpms)
137 return;
138
139 plane->dpms = dpms;
140 switch (dpms) {
141 case DRM_MODE_DPMS_ON:
142 if (manager->dp_sub) {
143 if (plane->primary) {
144 xilinx_drm_dp_sub_enable_alpha(manager->dp_sub,
145 plane->alpha_enable);
146 xilinx_drm_dp_sub_set_alpha(manager->dp_sub,
147 plane->alpha);
148 }
149 xilinx_drm_dp_sub_layer_enable(manager->dp_sub,
150 plane->dp_layer);
151 }
152
153
154 for (i = 0; i < MAX_NUM_SUB_PLANES; i++)
155 if (plane->dma[i].chan && plane->dma[i].is_active)
156 dma_async_issue_pending(plane->dma[i].chan);
157
158 if (plane->rgb2yuv)
159 xilinx_rgb2yuv_enable(plane->rgb2yuv);
160
161 if (plane->cresample)
162 xilinx_cresample_enable(plane->cresample);
163
164
165 if (manager->osd) {
166 xilinx_osd_disable_rue(manager->osd);
167
168 xilinx_osd_layer_set_priority(plane->osd_layer,
169 plane->prio);
170 xilinx_osd_layer_enable_alpha(plane->osd_layer,
171 plane->alpha_enable);
172 xilinx_osd_layer_set_alpha(plane->osd_layer,
173 plane->alpha);
174 xilinx_osd_layer_enable(plane->osd_layer);
175
176 xilinx_osd_enable_rue(manager->osd);
177 }
178
179 break;
180 default:
181
182 if (manager->osd) {
183 xilinx_osd_disable_rue(manager->osd);
184
185 xilinx_osd_layer_set_dimension(plane->osd_layer,
186 0, 0, 0, 0);
187 xilinx_osd_layer_disable(plane->osd_layer);
188
189 xilinx_osd_enable_rue(manager->osd);
190 }
191
192 if (plane->cresample) {
193 xilinx_cresample_disable(plane->cresample);
194 xilinx_cresample_reset(plane->cresample);
195 }
196
197 if (plane->rgb2yuv) {
198 xilinx_rgb2yuv_disable(plane->rgb2yuv);
199 xilinx_rgb2yuv_reset(plane->rgb2yuv);
200 }
201
202
203 for (i = 0; i < MAX_NUM_SUB_PLANES; i++) {
204 if (plane->dma[i].chan && plane->dma[i].is_active) {
205 dmaengine_terminate_all(plane->dma[i].chan);
206 plane->dma[i].is_active = false;
207 }
208 }
209
210 if (manager->dp_sub)
211 xilinx_drm_dp_sub_layer_disable(manager->dp_sub,
212 plane->dp_layer);
213
214 break;
215 }
216}
217
218
219void xilinx_drm_plane_commit(struct drm_plane *base_plane)
220{
221 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
222 struct dma_async_tx_descriptor *desc;
223 enum dma_ctrl_flags flags;
224 unsigned int i;
225
226 DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
227
228 for (i = 0; i < MAX_NUM_SUB_PLANES; i++) {
229 struct xilinx_drm_plane_dma *dma = &plane->dma[i];
230
231 if (dma->chan && dma->is_active) {
232 flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
233 desc = dmaengine_prep_interleaved_dma(dma->chan,
234 &dma->xt,
235 flags);
236 if (!desc) {
237 DRM_ERROR("failed to prepare DMA descriptor\n");
238 return;
239 }
240
241 dmaengine_submit(desc);
242
243 dma_async_issue_pending(dma->chan);
244 }
245 }
246}
247
248
249int xilinx_drm_plane_mode_set(struct drm_plane *base_plane,
250 struct drm_framebuffer *fb,
251 int crtc_x, int crtc_y,
252 unsigned int crtc_w, unsigned int crtc_h,
253 uint32_t src_x, uint32_t src_y,
254 uint32_t src_w, uint32_t src_h)
255{
256 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
257 struct drm_gem_cma_object *obj;
258 size_t offset;
259 unsigned int hsub, vsub, i;
260
261 DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
262
263
264 if (plane->cresample)
265 xilinx_cresample_configure(plane->cresample, crtc_w, crtc_h);
266
267
268 if (plane->rgb2yuv)
269 xilinx_rgb2yuv_configure(plane->rgb2yuv, crtc_w, crtc_h);
270
271 DRM_DEBUG_KMS("h: %d(%d), v: %d(%d)\n",
272 src_w, crtc_x, src_h, crtc_y);
273 DRM_DEBUG_KMS("bpp: %d\n", fb->bits_per_pixel / 8);
274
275 hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
276 vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
277
278 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
279 unsigned int width = src_w / (i ? hsub : 1);
280 unsigned int height = src_h / (i ? vsub : 1);
281 unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, i);
282
283 if (!cpp)
284 cpp = xilinx_drm_format_bpp(fb->pixel_format) >> 3;
285
286 obj = xilinx_drm_fb_get_gem_obj(fb, i);
287 if (!obj) {
288 DRM_ERROR("failed to get a gem obj for fb\n");
289 return -EINVAL;
290 }
291
292 plane->dma[i].xt.numf = height;
293 plane->dma[i].sgl[0].size = width * cpp;
294 plane->dma[i].sgl[0].icg = fb->pitches[i] -
295 plane->dma[i].sgl[0].size;
296 offset = src_x * cpp + src_y * fb->pitches[i];
297 offset += fb->offsets[i];
298 plane->dma[i].xt.src_start = obj->paddr + offset;
299 plane->dma[i].xt.frame_size = 1;
300 plane->dma[i].xt.dir = DMA_MEM_TO_DEV;
301 plane->dma[i].xt.src_sgl = true;
302 plane->dma[i].xt.dst_sgl = false;
303 plane->dma[i].is_active = true;
304 }
305
306 for (; i < MAX_NUM_SUB_PLANES; i++)
307 plane->dma[i].is_active = false;
308
309
310 if (plane->manager->osd) {
311 xilinx_osd_disable_rue(plane->manager->osd);
312
313 xilinx_osd_layer_set_dimension(plane->osd_layer, crtc_x, crtc_y,
314 src_w, src_h);
315
316 xilinx_osd_enable_rue(plane->manager->osd);
317 }
318
319 if (plane->manager->dp_sub) {
320 int ret;
321
322 ret = xilinx_drm_dp_sub_layer_check_size(plane->manager->dp_sub,
323 plane->dp_layer,
324 src_w, src_h);
325 if (ret)
326 return ret;
327
328 ret = xilinx_drm_dp_sub_layer_set_fmt(plane->manager->dp_sub,
329 plane->dp_layer,
330 fb->pixel_format);
331 if (ret) {
332 DRM_ERROR("failed to set dp_sub layer fmt\n");
333 return ret;
334 }
335 }
336
337 return 0;
338}
339
340
341static int xilinx_drm_plane_update(struct drm_plane *base_plane,
342 struct drm_crtc *crtc,
343 struct drm_framebuffer *fb,
344 int crtc_x, int crtc_y,
345 unsigned int crtc_w, unsigned int crtc_h,
346 uint32_t src_x, uint32_t src_y,
347 uint32_t src_w, uint32_t src_h)
348{
349 int ret;
350
351 ret = xilinx_drm_plane_mode_set(base_plane, fb,
352 crtc_x, crtc_y, crtc_w, crtc_h,
353 src_x >> 16, src_y >> 16,
354 src_w >> 16, src_h >> 16);
355 if (ret) {
356 DRM_ERROR("failed to mode-set a plane\n");
357 return ret;
358 }
359
360
361 xilinx_drm_plane_dpms(base_plane, DRM_MODE_DPMS_ON);
362
363 xilinx_drm_plane_commit(base_plane);
364
365 return 0;
366}
367
368
369static int xilinx_drm_plane_disable(struct drm_plane *base_plane)
370{
371 xilinx_drm_plane_dpms(base_plane, DRM_MODE_DPMS_OFF);
372
373 return 0;
374}
375
376
377static void xilinx_drm_plane_destroy(struct drm_plane *base_plane)
378{
379 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
380 unsigned int i;
381
382 xilinx_drm_plane_dpms(base_plane, DRM_MODE_DPMS_OFF);
383
384 plane->manager->planes[plane->id] = NULL;
385
386 drm_plane_cleanup(base_plane);
387
388 for (i = 0; i < MAX_NUM_SUB_PLANES; i++)
389 if (plane->dma[i].chan)
390 dma_release_channel(plane->dma[i].chan);
391
392 if (plane->manager->osd) {
393 xilinx_osd_layer_disable(plane->osd_layer);
394 xilinx_osd_layer_put(plane->osd_layer);
395 }
396
397 if (plane->manager->dp_sub) {
398 xilinx_drm_dp_sub_layer_disable(plane->manager->dp_sub,
399 plane->dp_layer);
400 xilinx_drm_dp_sub_layer_put(plane->manager->dp_sub,
401 plane->dp_layer);
402 }
403}
404
405
406
407
408
409
410
411
412
413
414
415
416static void
417xilinx_drm_plane_update_prio(struct xilinx_drm_plane_manager *manager)
418{
419 struct xilinx_drm_plane *planes[MAX_PLANES];
420 struct xilinx_drm_plane *plane;
421 unsigned int i, j;
422
423
424 for (i = 0; i < manager->num_planes; i++) {
425 plane = manager->planes[i];
426
427 for (j = i; j > 0; --j) {
428 if (planes[j - 1]->zpos <= plane->zpos)
429 break;
430 planes[j] = planes[j - 1];
431 }
432
433 planes[j] = plane;
434 }
435
436 xilinx_osd_disable_rue(manager->osd);
437
438
439 for (i = 0; i < manager->num_planes; i++) {
440 planes[i]->prio = i;
441 xilinx_osd_layer_set_priority(planes[i]->osd_layer,
442 planes[i]->prio);
443 }
444
445 xilinx_osd_enable_rue(manager->osd);
446}
447
448static void xilinx_drm_plane_set_zpos(struct drm_plane *base_plane,
449 unsigned int zpos)
450{
451 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
452 struct xilinx_drm_plane_manager *manager = plane->manager;
453 bool update = false;
454 int i;
455
456 if (plane->zpos == zpos)
457 return;
458
459 for (i = 0; i < manager->num_planes; i++) {
460 if (manager->planes[i] != plane &&
461 manager->planes[i]->prio == zpos) {
462 update = true;
463 break;
464 }
465 }
466
467 plane->zpos = zpos;
468
469 if (update) {
470 xilinx_drm_plane_update_prio(manager);
471 } else {
472 plane->prio = zpos;
473 xilinx_osd_layer_set_priority(plane->osd_layer, plane->prio);
474 }
475}
476
477static void xilinx_drm_plane_set_alpha(struct drm_plane *base_plane,
478 unsigned int alpha)
479{
480 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
481 struct xilinx_drm_plane_manager *manager = plane->manager;
482
483 if (plane->alpha == alpha)
484 return;
485
486 plane->alpha = alpha;
487
488 if (plane->osd_layer)
489 xilinx_osd_layer_set_alpha(plane->osd_layer, plane->alpha);
490 else if (manager->dp_sub)
491 xilinx_drm_dp_sub_set_alpha(manager->dp_sub, plane->alpha);
492}
493
494static void xilinx_drm_plane_enable_alpha(struct drm_plane *base_plane,
495 bool enable)
496{
497 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
498 struct xilinx_drm_plane_manager *manager = plane->manager;
499
500 if (plane->alpha_enable == enable)
501 return;
502
503 plane->alpha_enable = enable;
504
505 if (plane->osd_layer)
506 xilinx_osd_layer_enable_alpha(plane->osd_layer, enable);
507 else if (manager->dp_sub)
508 xilinx_drm_dp_sub_enable_alpha(manager->dp_sub, enable);
509}
510
511
512static int xilinx_drm_plane_set_property(struct drm_plane *base_plane,
513 struct drm_property *property,
514 uint64_t val)
515{
516 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
517 struct xilinx_drm_plane_manager *manager = plane->manager;
518
519 if (property == manager->zpos_prop)
520 xilinx_drm_plane_set_zpos(base_plane, val);
521 else if (property == manager->alpha_prop)
522 xilinx_drm_plane_set_alpha(base_plane, val);
523 else if (property == manager->alpha_enable_prop)
524 xilinx_drm_plane_enable_alpha(base_plane, val);
525 else
526 return -EINVAL;
527
528 drm_object_property_set_value(&base_plane->base, property, val);
529
530 return 0;
531}
532
533static struct drm_plane_funcs xilinx_drm_plane_funcs = {
534 .update_plane = xilinx_drm_plane_update,
535 .disable_plane = xilinx_drm_plane_disable,
536 .destroy = xilinx_drm_plane_destroy,
537 .set_property = xilinx_drm_plane_set_property,
538};
539
540
541int xilinx_drm_plane_get_max_width(struct drm_plane *base_plane)
542{
543 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
544
545 return plane->manager->max_width;
546}
547
548
549bool xilinx_drm_plane_check_format(struct xilinx_drm_plane_manager *manager,
550 uint32_t format)
551{
552 int i;
553
554 for (i = 0; i < MAX_PLANES; i++)
555 if (manager->planes[i] &&
556 (manager->planes[i]->format == format))
557 return true;
558
559 return false;
560}
561
562
563int xilinx_drm_plane_get_num_planes(struct xilinx_drm_plane_manager *manager)
564{
565 return manager->num_planes;
566}
567
568
569
570
571
572
573
574
575
576
577void xilinx_drm_plane_restore(struct xilinx_drm_plane_manager *manager)
578{
579 struct xilinx_drm_plane *plane;
580 unsigned int i;
581
582
583
584
585
586
587 for (i = 0; i < manager->num_planes; i++) {
588 plane = manager->planes[i];
589
590 plane->prio = plane->zpos = plane->id;
591 if (manager->zpos_prop)
592 drm_object_property_set_value(&plane->base.base,
593 manager->zpos_prop,
594 plane->prio);
595
596 plane->alpha = manager->default_alpha;
597 if (manager->alpha_prop)
598 drm_object_property_set_value(&plane->base.base,
599 manager->alpha_prop,
600 plane->alpha);
601
602 plane->alpha_enable = true;
603 if (manager->alpha_enable_prop)
604 drm_object_property_set_value(&plane->base.base,
605 manager->alpha_enable_prop, true);
606 }
607}
608
609
610uint32_t xilinx_drm_plane_get_format(struct drm_plane *base_plane)
611{
612 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
613 return plane->format;
614}
615
616
617
618
619
620
621
622
623
624unsigned int xilinx_drm_plane_get_align(struct drm_plane *base_plane)
625{
626 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
627
628 return 1 << plane->dma[0].chan->device->copy_align;
629}
630
631
632static void
633xilinx_drm_plane_create_property(struct xilinx_drm_plane_manager *manager)
634{
635 if (manager->osd)
636 manager->zpos_prop = drm_property_create_range(manager->drm, 0,
637 "zpos", 0, manager->num_planes - 1);
638
639 if (manager->osd || manager->dp_sub) {
640 manager->alpha_prop = drm_property_create_range(manager->drm, 0,
641 "alpha", 0, manager->default_alpha);
642 manager->alpha_enable_prop =
643 drm_property_create_bool(manager->drm, 0,
644 "global alpha enable");
645 }
646}
647
648
649static void xilinx_drm_plane_attach_property(struct drm_plane *base_plane)
650{
651 struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
652 struct xilinx_drm_plane_manager *manager = plane->manager;
653
654 if (manager->zpos_prop)
655 drm_object_attach_property(&base_plane->base,
656 manager->zpos_prop,
657 plane->id);
658
659 if (manager->alpha_prop) {
660 if (manager->dp_sub && !plane->primary)
661 return;
662
663 drm_object_attach_property(&base_plane->base,
664 manager->alpha_prop,
665 manager->default_alpha);
666 drm_object_attach_property(&base_plane->base,
667 manager->alpha_enable_prop, false);
668 }
669
670 plane->alpha_enable = true;
671}
672
673
674
675
676
677
678
679
680
681void xilinx_drm_plane_manager_dpms(struct xilinx_drm_plane_manager *manager,
682 int dpms)
683{
684 switch (dpms) {
685 case DRM_MODE_DPMS_ON:
686 if (manager->dp_sub) {
687 xilinx_drm_dp_sub_set_bg_color(manager->dp_sub,
688 0, 0, 0);
689 xilinx_drm_dp_sub_enable(manager->dp_sub);
690 }
691
692 if (manager->osd) {
693 xilinx_osd_disable_rue(manager->osd);
694 xilinx_osd_enable(manager->osd);
695 xilinx_osd_enable_rue(manager->osd);
696 }
697
698 break;
699 default:
700 if (manager->osd)
701 xilinx_osd_reset(manager->osd);
702
703 if (manager->dp_sub)
704 xilinx_drm_dp_sub_disable(manager->dp_sub);
705
706 break;
707 }
708}
709
710
711
712
713
714
715
716
717
718
719void xilinx_drm_plane_manager_mode_set(struct xilinx_drm_plane_manager *manager,
720 unsigned int crtc_w, unsigned int crtc_h)
721{
722 if (manager->osd)
723 xilinx_osd_set_dimension(manager->osd, crtc_w, crtc_h);
724}
725
726
727static struct xilinx_drm_plane *
728xilinx_drm_plane_create(struct xilinx_drm_plane_manager *manager,
729 unsigned int possible_crtcs, bool primary)
730{
731 struct xilinx_drm_plane *plane;
732 struct device *dev = manager->drm->dev;
733 char name[16];
734 struct device_node *plane_node;
735 struct device_node *sub_node;
736 enum drm_plane_type type;
737 uint32_t fmt_in = -1;
738 uint32_t fmt_out = -1;
739 const char *fmt;
740 int i;
741 int ret;
742 uint32_t *fmts = NULL;
743 unsigned int num_fmts = 0;
744
745 for (i = 0; i < manager->num_planes; i++)
746 if (!manager->planes[i])
747 break;
748
749 if (i >= manager->num_planes) {
750 DRM_ERROR("failed to allocate plane\n");
751 return ERR_PTR(-ENODEV);
752 }
753
754 snprintf(name, sizeof(name), "plane%d", i);
755 plane_node = of_get_child_by_name(manager->node, name);
756 if (!plane_node) {
757 DRM_ERROR("failed to find a plane node\n");
758 return ERR_PTR(-ENODEV);
759 }
760
761 plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);
762 if (!plane) {
763 ret = -ENOMEM;
764 goto err_out;
765 }
766
767 plane->primary = primary;
768 plane->id = i;
769 plane->prio = i;
770 plane->zpos = i;
771 plane->alpha = manager->default_alpha;
772 plane->dpms = DRM_MODE_DPMS_OFF;
773 plane->format = -1;
774 DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
775
776 for (i = 0; i < MAX_NUM_SUB_PLANES; i++) {
777 snprintf(name, sizeof(name), "dma%d", i);
778 plane->dma[i].chan = of_dma_request_slave_channel(plane_node,
779 name);
780 if (PTR_ERR(plane->dma[i].chan) == -ENODEV) {
781 plane->dma[i].chan = NULL;
782 continue;
783 }
784
785 if (IS_ERR(plane->dma[i].chan)) {
786 DRM_ERROR("failed to request dma channel\n");
787 ret = PTR_ERR(plane->dma[i].chan);
788 plane->dma[i].chan = NULL;
789 goto err_dma;
790 }
791 }
792
793
794 sub_node = of_parse_phandle(plane_node, "xlnx,rgb2yuv", i);
795 if (sub_node) {
796 plane->rgb2yuv = xilinx_rgb2yuv_probe(dev, sub_node);
797 of_node_put(sub_node);
798 if (IS_ERR(plane->rgb2yuv)) {
799 DRM_ERROR("failed to probe a rgb2yuv\n");
800 ret = PTR_ERR(plane->rgb2yuv);
801 goto err_dma;
802 }
803
804
805 plane->format = DRM_FORMAT_XRGB8888;
806
807
808 fmt_out = DRM_FORMAT_YUV444;
809 }
810
811
812 sub_node = of_parse_phandle(plane_node, "xlnx,cresample", i);
813 if (sub_node) {
814 plane->cresample = xilinx_cresample_probe(dev, sub_node);
815 of_node_put(sub_node);
816 if (IS_ERR(plane->cresample)) {
817 DRM_ERROR("failed to probe a cresample\n");
818 ret = PTR_ERR(plane->cresample);
819 goto err_dma;
820 }
821
822
823 fmt = xilinx_cresample_get_input_format_name(plane->cresample);
824 ret = xilinx_drm_format_by_name(fmt, &fmt_in);
825 if (ret)
826 goto err_dma;
827
828
829 if ((fmt_out != -1) && (fmt_out != fmt_in)) {
830 DRM_ERROR("input/output format mismatch\n");
831 ret = -EINVAL;
832 goto err_dma;
833 }
834
835 if (plane->format == -1)
836 plane->format = fmt_in;
837
838
839 fmt = xilinx_cresample_get_output_format_name(plane->cresample);
840 ret = xilinx_drm_format_by_name(fmt, &fmt_out);
841 if (ret)
842 goto err_dma;
843 }
844
845
846 if (manager->osd) {
847
848 if ((fmt_out != -1) && (fmt_out != manager->format)) {
849 DRM_ERROR("input/output format mismatch\n");
850 ret = -EINVAL;
851 goto err_dma;
852 }
853
854
855 plane->osd_layer = xilinx_osd_layer_get(manager->osd);
856 if (IS_ERR(plane->osd_layer)) {
857 DRM_ERROR("failed to create a osd layer\n");
858 ret = PTR_ERR(plane->osd_layer);
859 plane->osd_layer = NULL;
860 goto err_dma;
861 }
862
863 if (plane->format == -1)
864 plane->format = manager->format;
865 }
866
867 if (manager->dp_sub) {
868 plane->dp_layer = xilinx_drm_dp_sub_layer_get(manager->dp_sub,
869 primary);
870 if (IS_ERR(plane->dp_layer)) {
871 DRM_ERROR("failed to create a dp_sub layer\n");
872 ret = PTR_ERR(plane->dp_layer);
873 plane->dp_layer = NULL;
874 goto err_dma;
875 }
876
877 if (primary) {
878 ret = xilinx_drm_dp_sub_layer_set_fmt(manager->dp_sub,
879 plane->dp_layer,
880 manager->format);
881 if (ret) {
882 DRM_ERROR("failed to set dp_sub layer fmt\n");
883 goto err_dma;
884 }
885 }
886
887 plane->format =
888 xilinx_drm_dp_sub_layer_get_fmt(manager->dp_sub,
889 plane->dp_layer);
890 xilinx_drm_dp_sub_layer_get_fmts(manager->dp_sub,
891 plane->dp_layer, &fmts,
892 &num_fmts);
893 }
894
895
896 if (plane->format == -1)
897 plane->format = manager->format;
898
899
900 type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
901 ret = drm_universal_plane_init(manager->drm, &plane->base,
902 possible_crtcs, &xilinx_drm_plane_funcs,
903 fmts ? fmts : &plane->format,
904 num_fmts ? num_fmts : 1, type, NULL);
905 if (ret) {
906 DRM_ERROR("failed to initialize plane\n");
907 goto err_init;
908 }
909 plane->manager = manager;
910 manager->planes[plane->id] = plane;
911
912 xilinx_drm_plane_attach_property(&plane->base);
913
914 of_node_put(plane_node);
915
916 return plane;
917
918err_init:
919 if (manager->dp_sub) {
920 xilinx_drm_dp_sub_layer_disable(manager->dp_sub,
921 plane->dp_layer);
922 xilinx_drm_dp_sub_layer_put(plane->manager->dp_sub,
923 plane->dp_layer);
924 }
925 if (manager->osd) {
926 xilinx_osd_layer_disable(plane->osd_layer);
927 xilinx_osd_layer_put(plane->osd_layer);
928 }
929err_dma:
930 for (i = 0; i < MAX_NUM_SUB_PLANES; i++)
931 if (plane->dma[i].chan)
932 dma_release_channel(plane->dma[i].chan);
933err_out:
934 of_node_put(plane_node);
935 return ERR_PTR(ret);
936}
937
938
939struct drm_plane *
940xilinx_drm_plane_create_primary(struct xilinx_drm_plane_manager *manager,
941 unsigned int possible_crtcs)
942{
943 struct xilinx_drm_plane *plane;
944
945 plane = xilinx_drm_plane_create(manager, possible_crtcs, true);
946 if (IS_ERR(plane)) {
947 DRM_ERROR("failed to allocate a primary plane\n");
948 return ERR_CAST(plane);
949 }
950
951 return &plane->base;
952}
953
954
955int xilinx_drm_plane_create_planes(struct xilinx_drm_plane_manager *manager,
956 unsigned int possible_crtcs)
957{
958 struct xilinx_drm_plane *plane;
959 int i;
960
961
962 for (i = 0; i < manager->num_planes; i++) {
963 if (manager->planes[i])
964 continue;
965
966 plane = xilinx_drm_plane_create(manager, possible_crtcs, false);
967 if (IS_ERR(plane)) {
968 DRM_ERROR("failed to allocate a plane\n");
969 return PTR_ERR(plane);
970 }
971
972 manager->planes[i] = plane;
973 }
974
975 return 0;
976}
977
978
979static int
980xilinx_drm_plane_init_manager(struct xilinx_drm_plane_manager *manager)
981{
982 unsigned int format;
983 uint32_t drm_format;
984 int ret = 0;
985
986 if (manager->osd) {
987 manager->num_planes = xilinx_osd_get_num_layers(manager->osd);
988 manager->max_width = xilinx_osd_get_max_width(manager->osd);
989
990 format = xilinx_osd_get_format(manager->osd);
991 ret = xilinx_drm_format_by_code(format, &drm_format);
992 if (drm_format != manager->format)
993 ret = -EINVAL;
994 } else if (manager->dp_sub) {
995 manager->num_planes = XILINX_DRM_DP_SUB_NUM_LAYERS;
996 manager->max_width = XILINX_DRM_DP_SUB_MAX_WIDTH;
997 } else {
998
999 manager->num_planes = 1;
1000 manager->max_width = 4096;
1001 }
1002
1003 return ret;
1004}
1005
1006struct xilinx_drm_plane_manager *
1007xilinx_drm_plane_probe_manager(struct drm_device *drm)
1008{
1009 struct xilinx_drm_plane_manager *manager;
1010 struct device *dev = drm->dev;
1011 struct device_node *sub_node;
1012 const char *format;
1013 int ret;
1014
1015 manager = devm_kzalloc(dev, sizeof(*manager), GFP_KERNEL);
1016 if (!manager)
1017 return ERR_PTR(-ENOMEM);
1018
1019
1020 manager->node = of_get_child_by_name(dev->of_node, "planes");
1021 if (!manager->node) {
1022 DRM_ERROR("failed to get a planes node\n");
1023 return ERR_PTR(-EINVAL);
1024 }
1025
1026
1027 ret = of_property_read_string(manager->node, "xlnx,pixel-format",
1028 &format);
1029 if (ret < 0) {
1030 DRM_ERROR("failed to get a plane manager format\n");
1031 return ERR_PTR(ret);
1032 }
1033
1034 ret = xilinx_drm_format_by_name(format, &manager->format);
1035 if (ret < 0) {
1036 DRM_ERROR("invalid plane manager format\n");
1037 return ERR_PTR(ret);
1038 }
1039
1040 manager->drm = drm;
1041
1042
1043 sub_node = of_parse_phandle(dev->of_node, "xlnx,osd", 0);
1044 if (sub_node) {
1045 manager->osd = xilinx_osd_probe(dev, sub_node);
1046 of_node_put(sub_node);
1047 if (IS_ERR(manager->osd)) {
1048 of_node_put(manager->node);
1049 DRM_ERROR("failed to probe an osd\n");
1050 return ERR_CAST(manager->osd);
1051 }
1052 manager->default_alpha = OSD_MAX_ALPHA;
1053 }
1054
1055 manager->dp_sub = xilinx_drm_dp_sub_of_get(drm->dev->of_node);
1056 if (IS_ERR(manager->dp_sub)) {
1057 DRM_DEBUG_KMS("failed to get a dp_sub\n");
1058 return ERR_CAST(manager->dp_sub);
1059 } else if (manager->dp_sub != NULL) {
1060 manager->default_alpha = XILINX_DRM_DP_SUB_MAX_ALPHA;
1061 }
1062
1063 ret = xilinx_drm_plane_init_manager(manager);
1064 if (ret) {
1065 DRM_ERROR("failed to init a plane manager\n");
1066 return ERR_PTR(ret);
1067 }
1068
1069 xilinx_drm_plane_create_property(manager);
1070
1071 return manager;
1072}
1073
1074void xilinx_drm_plane_remove_manager(struct xilinx_drm_plane_manager *manager)
1075{
1076 xilinx_drm_dp_sub_put(manager->dp_sub);
1077 of_node_put(manager->node);
1078}
1079