1
2
3
4
5
6
7
8
9
10
11
12#include <drm/drm_atomic.h>
13#include <drm/drm_atomic_helper.h>
14#include <drm/drm_atomic_uapi.h>
15#include <drm/drm_crtc.h>
16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_fb_cma_helper.h>
18#include <drm/drm_fourcc.h>
19#include <drm/drm_plane_helper.h>
20#include <drm/drm_vblank.h>
21
22#include <linux/clk.h>
23#include <linux/delay.h>
24#include <linux/device.h>
25#include <linux/dma-mapping.h>
26#include <linux/dmaengine.h>
27#include <linux/interrupt.h>
28#include <linux/irqreturn.h>
29#include <linux/list.h>
30#include <linux/module.h>
31#include <linux/mutex.h>
32#include <linux/of.h>
33#include <linux/of_dma.h>
34#include <linux/platform_device.h>
35#include <linux/pm_runtime.h>
36#include <linux/spinlock.h>
37#include <linux/uaccess.h>
38#include <video/videomode.h>
39#include <linux/mfd/syscon.h>
40#include <linux/regmap.h>
41
42#include "xlnx_bridge.h"
43#include "xlnx_crtc.h"
44#include "xlnx_fb.h"
45#include "zynqmp_disp.h"
46#include "zynqmp_disp_regs.h"
47#include "zynqmp_dp.h"
48#include "zynqmp_dpsub.h"
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73static uint zynqmp_disp_gfx_init_fmt;
74module_param_named(gfx_init_fmt, zynqmp_disp_gfx_init_fmt, uint, 0444);
75MODULE_PARM_DESC(gfx_init_fmt, "The initial format of the graphics layer\n"
76 "\t\t0 = rgb565 (default)\n"
77 "\t\t1 = rgb888\n"
78 "\t\t2 = argb8888\n");
79
80#define ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565 10
81#define ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB888 5
82#define ZYNQMP_DISP_AV_BUF_GFX_FMT_ARGB8888 1
83static const u32 zynqmp_disp_gfx_init_fmts[] = {
84 ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565,
85 ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB888,
86 ZYNQMP_DISP_AV_BUF_GFX_FMT_ARGB8888,
87};
88
89#define ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS 4
90#define ZYNQMP_DISP_AV_BUF_NUM_BUFFERS 6
91
92#define ZYNQMP_DISP_NUM_LAYERS 2
93#define ZYNQMP_DISP_MAX_NUM_SUB_PLANES 3
94
95
96
97
98#define ZYNQMP_DISP_MAX_WIDTH 4096
99#define ZYNQMP_DISP_MAX_HEIGHT 4096
100
101#define ZYNQMP_DISP_MAX_DMA_BIT 44
102
103static struct regmap_config dpaud_regmap_config = {
104 .name = "regmap",
105 .reg_bits = 32,
106 .val_bits = 32,
107 .reg_stride = 4,
108 .max_register = 0xfff,
109 .cache_type = REGCACHE_NONE,
110};
111
112
113
114
115
116
117enum zynqmp_disp_layer_type {
118 ZYNQMP_DISP_LAYER_VID,
119 ZYNQMP_DISP_LAYER_GFX
120};
121
122
123
124
125
126
127enum zynqmp_disp_layer_mode {
128 ZYNQMP_DISP_LAYER_NONLIVE,
129 ZYNQMP_DISP_LAYER_LIVE
130};
131
132
133
134
135
136
137
138
139struct zynqmp_disp_layer_dma {
140 struct dma_chan *chan;
141 bool is_active;
142 struct dma_interleaved_template xt;
143 struct data_chunk sgl[1];
144};
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166struct zynqmp_disp_layer {
167 struct drm_plane plane;
168 struct xlnx_bridge bridge;
169 struct zynqmp_disp_layer_dma dma[ZYNQMP_DISP_MAX_NUM_SUB_PLANES];
170 unsigned int num_chan;
171 enum zynqmp_disp_layer_type id;
172 u32 offset;
173 u8 enabled;
174 const struct zynqmp_disp_fmt *fmt;
175 u32 *drm_fmts;
176 unsigned int num_fmts;
177 u32 *bus_fmts;
178 unsigned int num_bus_fmts;
179 u32 w;
180 u32 h;
181 enum zynqmp_disp_layer_mode mode;
182 struct zynqmp_disp_layer *other;
183 struct zynqmp_disp *disp;
184};
185
186
187
188
189
190struct zynqmp_disp_blend {
191 void __iomem *base;
192};
193
194
195
196
197
198struct zynqmp_disp_av_buf {
199 void __iomem *base;
200};
201
202
203
204
205
206struct zynqmp_disp_aud {
207 struct regmap *base;
208};
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248struct zynqmp_disp {
249 struct xlnx_crtc xlnx_crtc;
250 struct device *dev;
251 struct zynqmp_dpsub *dpsub;
252 struct drm_device *drm;
253 bool enabled;
254 struct zynqmp_disp_blend blend;
255 struct zynqmp_disp_av_buf av_buf;
256 struct zynqmp_disp_aud aud;
257 struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
258 struct drm_property *g_alpha_prop;
259 u32 alpha;
260 struct drm_property *g_alpha_en_prop;
261 bool alpha_en;
262 struct drm_property *color_prop;
263 unsigned int color;
264 struct drm_property *bg_c0_prop;
265 u32 bg_c0;
266 struct drm_property *bg_c1_prop;
267 u32 bg_c1;
268 struct drm_property *bg_c2_prop;
269 u32 bg_c2;
270 struct drm_property *tpg_prop;
271 bool tpg_on;
272 struct drm_pending_vblank_event *event;
273
274 struct clk *_ps_pclk;
275 struct clk *_pl_pclk;
276 struct clk *pclk;
277 bool pclk_en;
278 struct clk *_ps_audclk;
279 struct clk *_pl_audclk;
280 struct clk *audclk;
281 bool audclk_en;
282 struct clk *aclk;
283 bool aclk_en;
284 struct xlnx_bridge *vtc_bridge;
285};
286
287
288
289
290
291
292
293
294
295
296
297struct zynqmp_disp_fmt {
298 u32 drm_fmt;
299 u32 disp_fmt;
300 u32 bus_fmt;
301 bool rgb;
302 bool swap;
303 bool chroma_sub;
304 u32 sf[3];
305};
306
307static void zynqmp_disp_write(void __iomem *base, int offset, u32 val)
308{
309 writel(val, base + offset);
310}
311
312static u32 zynqmp_disp_read(void __iomem *base, int offset)
313{
314 return readl(base + offset);
315}
316
317static void zynqmp_disp_clr(void __iomem *base, int offset, u32 clr)
318{
319 zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) & ~clr);
320}
321
322static void zynqmp_disp_set(void __iomem *base, int offset, u32 set)
323{
324 zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) | set);
325}
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340static int zynqmp_disp_clk_enable(struct clk *clk, bool *flag)
341{
342 int ret = 0;
343
344 if (!*flag) {
345 ret = clk_prepare_enable(clk);
346 if (!ret)
347 *flag = true;
348 }
349
350 return ret;
351}
352
353
354
355
356
357
358
359
360static void zynqmp_disp_clk_disable(struct clk *clk, bool *flag)
361{
362 if (*flag) {
363 clk_disable_unprepare(clk);
364 *flag = false;
365 }
366}
367
368
369
370
371
372
373
374
375
376
377
378static int zynqmp_disp_clk_enable_disable(struct clk *clk, bool *flag)
379{
380 int ret = 0;
381
382 if (!*flag) {
383 ret = clk_prepare_enable(clk);
384 clk_disable_unprepare(clk);
385 }
386
387 return ret;
388}
389
390
391
392
393
394
395
396
397
398
399
400
401static void
402zynqmp_disp_blend_set_output_fmt(struct zynqmp_disp_blend *blend, u32 fmt)
403{
404 u16 reset_coeffs[] = { 0x1000, 0x0, 0x0,
405 0x0, 0x1000, 0x0,
406 0x0, 0x0, 0x1000 };
407 u32 reset_offsets[] = { 0x0, 0x0, 0x0 };
408 u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
409 0x7d4d, 0x7ab3, 0x800,
410 0x800, 0x794d, 0x7eb3 };
411 u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
412 u16 *coeffs;
413 u32 *offsets;
414 u32 offset, i;
415
416 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt);
417 if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) {
418 coeffs = reset_coeffs;
419 offsets = reset_offsets;
420 } else {
421
422 coeffs = sdtv_coeffs;
423 offsets = full_range_offsets;
424 }
425
426 offset = ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0;
427 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
428 zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
429
430 offset = ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET;
431 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
432 zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
433}
434
435
436
437
438
439
440
441
442
443
444static void zynqmp_disp_blend_layer_coeff(struct zynqmp_disp_blend *blend,
445 struct zynqmp_disp_layer *layer,
446 bool on)
447{
448 u32 offset, i, s0, s1;
449 u16 sdtv_coeffs[] = { 0x1000, 0x166f, 0x0,
450 0x1000, 0x7483, 0x7a7f,
451 0x1000, 0x0, 0x1c5a };
452 u16 sdtv_coeffs_yonly[] = { 0x0, 0x0, 0x1000,
453 0x0, 0x0, 0x1000,
454 0x0, 0x0, 0x1000 };
455 u16 swap_coeffs[] = { 0x1000, 0x0, 0x0,
456 0x0, 0x1000, 0x0,
457 0x0, 0x0, 0x1000 };
458 u16 null_coeffs[] = { 0x0, 0x0, 0x0,
459 0x0, 0x0, 0x0,
460 0x0, 0x0, 0x0 };
461 u16 *coeffs;
462 u32 sdtv_offsets[] = { 0x0, 0x1800, 0x1800 };
463 u32 sdtv_offsets_yonly[] = { 0x1800, 0x1800, 0x0 };
464 u32 null_offsets[] = { 0x0, 0x0, 0x0 };
465 u32 *offsets;
466 struct zynqmp_disp *display = layer->disp;
467
468 if (layer->id == ZYNQMP_DISP_LAYER_VID)
469 offset = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0;
470 else
471 offset = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0;
472
473 if (!on) {
474 coeffs = null_coeffs;
475 offsets = null_offsets;
476 } else {
477 if ((!layer->fmt->rgb) && (!display->tpg_on)) {
478
479
480
481
482 if (layer->fmt->drm_fmt == DRM_FORMAT_Y8 ||
483 layer->fmt->drm_fmt == DRM_FORMAT_Y10) {
484 coeffs = sdtv_coeffs_yonly;
485 offsets = sdtv_offsets_yonly;
486 } else {
487 coeffs = sdtv_coeffs;
488 offsets = sdtv_offsets;
489 }
490
491 s0 = 1;
492 s1 = 2;
493 } else {
494 coeffs = swap_coeffs;
495 s0 = 0;
496 s1 = 2;
497
498
499 offsets = null_offsets;
500 }
501
502 if (layer->fmt->swap) {
503 for (i = 0; i < 3; i++) {
504 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
505 coeffs[i * 3 + s1] ^= coeffs[i * 3 + s0];
506 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
507 }
508 }
509 }
510
511
512 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
513 zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
514
515 if (layer->id == ZYNQMP_DISP_LAYER_VID)
516 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET;
517 else
518 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET;
519
520
521 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
522 zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
523}
524
525
526
527
528
529
530
531
532static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
533 struct zynqmp_disp_layer *layer)
534{
535 u32 reg;
536
537 reg = layer->fmt->rgb ? ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB : 0;
538 reg |= layer->fmt->chroma_sub ?
539 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0;
540
541 zynqmp_disp_write(blend->base,
542 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset,
543 reg);
544
545 zynqmp_disp_blend_layer_coeff(blend, layer, true);
546}
547
548
549
550
551
552
553
554
555static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
556 struct zynqmp_disp_layer *layer)
557{
558 zynqmp_disp_write(blend->base,
559 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset, 0);
560
561 zynqmp_disp_blend_layer_coeff(blend, layer, false);
562}
563
564
565
566
567
568
569
570
571
572
573static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp_blend *blend,
574 u32 c0, u32 c1, u32 c2)
575{
576 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_0, c0);
577 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_1, c1);
578 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_2, c2);
579}
580
581
582
583
584
585
586
587
588static void
589zynqmp_disp_blend_set_alpha(struct zynqmp_disp_blend *blend, u32 alpha)
590{
591 u32 reg;
592
593 reg = zynqmp_disp_read(blend->base,
594 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA);
595 reg &= ~ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK;
596 reg |= alpha << 1;
597 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
598 reg);
599}
600
601
602
603
604
605
606
607
608static void
609zynqmp_disp_blend_enable_alpha(struct zynqmp_disp_blend *blend, bool enable)
610{
611 if (enable)
612 zynqmp_disp_set(blend->base,
613 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
614 else
615 zynqmp_disp_clr(blend->base,
616 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
617}
618
619
620
621static const struct zynqmp_disp_fmt blend_output_fmts[] = {
622 {
623 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB,
624 }, {
625 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444,
626 }, {
627 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422,
628 }, {
629 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY,
630 }
631};
632
633
634
635
636
637
638#define ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV 2
639static const struct zynqmp_disp_fmt av_buf_vid_fmts[] = {
640 {
641 .drm_fmt = DRM_FORMAT_VYUY,
642 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
643 .rgb = false,
644 .swap = true,
645 .chroma_sub = true,
646 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
647 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
648 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
649 }, {
650 .drm_fmt = DRM_FORMAT_UYVY,
651 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
652 .rgb = false,
653 .swap = false,
654 .chroma_sub = true,
655 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
656 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
657 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
658 }, {
659 .drm_fmt = DRM_FORMAT_YUYV,
660 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
661 .rgb = false,
662 .swap = false,
663 .chroma_sub = true,
664 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
665 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
666 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
667 }, {
668 .drm_fmt = DRM_FORMAT_YVYU,
669 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
670 .rgb = false,
671 .swap = true,
672 .chroma_sub = true,
673 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
674 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
675 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
676 }, {
677 .drm_fmt = DRM_FORMAT_YUV422,
678 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
679 .rgb = false,
680 .swap = false,
681 .chroma_sub = true,
682 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
683 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
684 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
685 }, {
686 .drm_fmt = DRM_FORMAT_YVU422,
687 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
688 .rgb = false,
689 .swap = true,
690 .chroma_sub = true,
691 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
692 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
693 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
694 }, {
695 .drm_fmt = DRM_FORMAT_YUV444,
696 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
697 .rgb = false,
698 .swap = false,
699 .chroma_sub = false,
700 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
701 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
702 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
703 }, {
704 .drm_fmt = DRM_FORMAT_YVU444,
705 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
706 .rgb = false,
707 .swap = true,
708 .chroma_sub = false,
709 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
710 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
711 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
712 }, {
713 .drm_fmt = DRM_FORMAT_NV16,
714 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
715 .rgb = false,
716 .swap = false,
717 .chroma_sub = true,
718 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
719 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
720 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
721 }, {
722 .drm_fmt = DRM_FORMAT_NV61,
723 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
724 .rgb = false,
725 .swap = true,
726 .chroma_sub = true,
727 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
728 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
729 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
730 }, {
731 .drm_fmt = DRM_FORMAT_Y8,
732 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO,
733 .rgb = false,
734 .swap = false,
735 .chroma_sub = false,
736 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
737 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
738 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
739 }, {
740 .drm_fmt = DRM_FORMAT_Y10,
741 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10,
742 .rgb = false,
743 .swap = false,
744 .chroma_sub = false,
745 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
746 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
747 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
748 }, {
749 .drm_fmt = DRM_FORMAT_BGR888,
750 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
751 .rgb = true,
752 .swap = false,
753 .chroma_sub = false,
754 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
755 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
756 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
757 }, {
758 .drm_fmt = DRM_FORMAT_RGB888,
759 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
760 .rgb = true,
761 .swap = true,
762 .chroma_sub = false,
763 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
764 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
765 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
766 }, {
767 .drm_fmt = DRM_FORMAT_XBGR8888,
768 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
769 .rgb = true,
770 .swap = false,
771 .chroma_sub = false,
772 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
773 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
774 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
775 }, {
776 .drm_fmt = DRM_FORMAT_XRGB8888,
777 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
778 .rgb = true,
779 .swap = true,
780 .chroma_sub = false,
781 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
782 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
783 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
784 }, {
785 .drm_fmt = DRM_FORMAT_XBGR2101010,
786 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
787 .rgb = true,
788 .swap = false,
789 .chroma_sub = false,
790 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
791 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
792 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
793 }, {
794 .drm_fmt = DRM_FORMAT_XRGB2101010,
795 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
796 .rgb = true,
797 .swap = true,
798 .chroma_sub = false,
799 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
800 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
801 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
802 }, {
803 .drm_fmt = DRM_FORMAT_YUV420,
804 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
805 .rgb = false,
806 .swap = false,
807 .chroma_sub = true,
808 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
809 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
810 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
811 }, {
812 .drm_fmt = DRM_FORMAT_YVU420,
813 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
814 .rgb = false,
815 .swap = true,
816 .chroma_sub = true,
817 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
818 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
819 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
820 }, {
821 .drm_fmt = DRM_FORMAT_NV12,
822 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
823 .rgb = false,
824 .swap = false,
825 .chroma_sub = true,
826 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
827 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
828 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
829 }, {
830 .drm_fmt = DRM_FORMAT_NV21,
831 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
832 .rgb = false,
833 .swap = true,
834 .chroma_sub = true,
835 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
836 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
837 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
838 }, {
839 .drm_fmt = DRM_FORMAT_XV15,
840 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10,
841 .rgb = false,
842 .swap = false,
843 .chroma_sub = true,
844 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
845 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
846 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
847 }, {
848 .drm_fmt = DRM_FORMAT_XV20,
849 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10,
850 .rgb = false,
851 .swap = false,
852 .chroma_sub = true,
853 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
854 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
855 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
856 }, {
857 .drm_fmt = DRM_FORMAT_X403,
858 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24_10,
859 .rgb = false,
860 .swap = false,
861 .chroma_sub = false,
862 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
863 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
864 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
865 }
866};
867
868
869static const struct zynqmp_disp_fmt av_buf_gfx_fmts[] = {
870 {
871 .drm_fmt = DRM_FORMAT_ABGR8888,
872 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
873 .rgb = true,
874 .swap = false,
875 .chroma_sub = false,
876 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
877 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
878 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
879 }, {
880 .drm_fmt = DRM_FORMAT_ARGB8888,
881 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
882 .rgb = true,
883 .swap = true,
884 .chroma_sub = false,
885 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
886 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
887 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
888 }, {
889 .drm_fmt = DRM_FORMAT_RGBA8888,
890 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
891 .rgb = true,
892 .swap = false,
893 .chroma_sub = false,
894 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
895 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
896 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
897 }, {
898 .drm_fmt = DRM_FORMAT_BGRA8888,
899 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
900 .rgb = true,
901 .swap = true,
902 .chroma_sub = false,
903 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
904 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
905 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
906 }, {
907 .drm_fmt = DRM_FORMAT_BGR888,
908 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888,
909 .rgb = true,
910 .swap = false,
911 .chroma_sub = false,
912 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
913 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
914 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
915 }, {
916 .drm_fmt = DRM_FORMAT_RGB888,
917 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888,
918 .rgb = true,
919 .swap = false,
920 .chroma_sub = false,
921 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
922 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
923 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
924 }, {
925 .drm_fmt = DRM_FORMAT_RGBA5551,
926 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
927 .rgb = true,
928 .swap = false,
929 .chroma_sub = false,
930 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
931 .sf[1] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
932 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
933 }, {
934 .drm_fmt = DRM_FORMAT_BGRA5551,
935 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
936 .rgb = true,
937 .swap = true,
938 .chroma_sub = false,
939 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
940 .sf[1] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
941 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
942 }, {
943 .drm_fmt = DRM_FORMAT_RGBA4444,
944 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
945 .rgb = true,
946 .swap = false,
947 .chroma_sub = false,
948 .sf[0] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
949 .sf[1] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
950 .sf[2] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
951 }, {
952 .drm_fmt = DRM_FORMAT_BGRA4444,
953 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
954 .rgb = true,
955 .swap = true,
956 .chroma_sub = false,
957 .sf[0] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
958 .sf[1] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
959 .sf[2] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
960 }, {
961 .drm_fmt = DRM_FORMAT_RGB565,
962 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
963 .rgb = true,
964 .swap = false,
965 .chroma_sub = false,
966 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
967 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
968 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
969 }, {
970 .drm_fmt = DRM_FORMAT_BGR565,
971 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
972 .rgb = true,
973 .swap = true,
974 .chroma_sub = false,
975 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
976 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
977 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
978 }
979};
980
981
982
983
984
985
986
987
988static const struct zynqmp_disp_fmt av_buf_live_fmts[] = {
989 {
990 .bus_fmt = MEDIA_BUS_FMT_RGB666_1X18,
991 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 |
992 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
993 .rgb = true,
994 .swap = false,
995 .chroma_sub = false,
996 .sf[0] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
997 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
998 .sf[2] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
999 }, {
1000 .bus_fmt = MEDIA_BUS_FMT_RBG888_1X24,
1001 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
1002 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
1003 .rgb = true,
1004 .swap = false,
1005 .chroma_sub = false,
1006 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1007 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1008 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1009 }, {
1010 .bus_fmt = MEDIA_BUS_FMT_UYVY8_1X16,
1011 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
1012 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1013 .rgb = false,
1014 .swap = false,
1015 .chroma_sub = true,
1016 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1017 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1018 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1019 }, {
1020 .bus_fmt = MEDIA_BUS_FMT_VUY8_1X24,
1021 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
1022 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444,
1023 .rgb = false,
1024 .swap = false,
1025 .chroma_sub = false,
1026 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1027 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1028 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1029 }, {
1030 .bus_fmt = MEDIA_BUS_FMT_UYVY10_1X20,
1031 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 |
1032 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1033 .rgb = false,
1034 .swap = false,
1035 .chroma_sub = true,
1036 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1037 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1038 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1039 }
1040};
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050static void
1051zynqmp_disp_av_buf_set_fmt(struct zynqmp_disp_av_buf *av_buf, u32 fmt)
1052{
1053 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT, fmt);
1054}
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065static u32
1066zynqmp_disp_av_buf_get_fmt(struct zynqmp_disp_av_buf *av_buf)
1067{
1068 return zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT);
1069}
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081static void zynqmp_disp_av_buf_set_live_fmt(struct zynqmp_disp_av_buf *av_buf,
1082 u32 fmt, bool is_vid)
1083{
1084 u32 offset;
1085
1086 if (is_vid)
1087 offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG;
1088 else
1089 offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
1090
1091 zynqmp_disp_write(av_buf->base, offset, fmt);
1092}
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102static void
1103zynqmp_disp_av_buf_set_vid_clock_src(struct zynqmp_disp_av_buf *av_buf,
1104 bool from_ps)
1105{
1106 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1107
1108 if (from_ps)
1109 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1110 else
1111 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1112 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1113}
1114
1115
1116
1117
1118
1119
1120
1121static bool
1122zynqmp_disp_av_buf_vid_clock_src_is_ps(struct zynqmp_disp_av_buf *av_buf)
1123{
1124 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1125
1126 return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS);
1127}
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137static void
1138zynqmp_disp_av_buf_set_vid_timing_src(struct zynqmp_disp_av_buf *av_buf,
1139 bool internal)
1140{
1141 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1142
1143 if (internal)
1144 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1145 else
1146 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1147 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1148}
1149
1150
1151
1152
1153
1154
1155
1156static bool
1157zynqmp_disp_av_buf_vid_timing_src_is_int(struct zynqmp_disp_av_buf *av_buf)
1158{
1159 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1160
1161 return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING);
1162}
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172static void
1173zynqmp_disp_av_buf_set_aud_clock_src(struct zynqmp_disp_av_buf *av_buf,
1174 bool from_ps)
1175{
1176 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1177
1178 if (from_ps)
1179 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1180 else
1181 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1182 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1183}
1184
1185
1186
1187
1188
1189
1190
1191static void
1192zynqmp_disp_av_buf_enable_buf(struct zynqmp_disp_av_buf *av_buf)
1193{
1194 u32 reg, i;
1195
1196 reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1197 reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX <<
1198 ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1199
1200 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
1201 zynqmp_disp_write(av_buf->base,
1202 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1203
1204 reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1205 reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX <<
1206 ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1207
1208 for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1209 zynqmp_disp_write(av_buf->base,
1210 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1211}
1212
1213
1214
1215
1216
1217
1218
1219static void
1220zynqmp_disp_av_buf_disable_buf(struct zynqmp_disp_av_buf *av_buf)
1221{
1222 u32 reg, i;
1223
1224 reg = ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH & ~ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1225 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1226 zynqmp_disp_write(av_buf->base,
1227 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1228}
1229
1230
1231
1232
1233
1234
1235
1236static void
1237zynqmp_disp_av_buf_enable_aud(struct zynqmp_disp_av_buf *av_buf)
1238{
1239 u32 reg;
1240
1241 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1242 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1243 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM;
1244 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1245 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1246}
1247
1248
1249
1250
1251
1252
1253
1254static void
1255zynqmp_disp_av_buf_enable(struct zynqmp_disp_av_buf *av_buf)
1256{
1257 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG, 0);
1258}
1259
1260
1261
1262
1263
1264
1265
1266static void
1267zynqmp_disp_av_buf_disable(struct zynqmp_disp_av_buf *av_buf)
1268{
1269 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG,
1270 ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST);
1271}
1272
1273
1274
1275
1276
1277
1278
1279static void
1280zynqmp_disp_av_buf_disable_aud(struct zynqmp_disp_av_buf *av_buf)
1281{
1282 u32 reg;
1283
1284 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1285 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1286 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE;
1287 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1288 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1289}
1290
1291
1292
1293
1294
1295
1296
1297
1298static void zynqmp_disp_av_buf_set_tpg(struct zynqmp_disp_av_buf *av_buf,
1299 bool tpg_on)
1300{
1301 u32 reg;
1302
1303 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1304 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1305 if (tpg_on)
1306 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1307 else
1308 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1309 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1310}
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320static void zynqmp_disp_av_buf_enable_vid(struct zynqmp_disp_av_buf *av_buf,
1321 struct zynqmp_disp_layer *layer,
1322 enum zynqmp_disp_layer_mode mode)
1323{
1324 u32 reg;
1325
1326 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1327 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1328 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1329 if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1330 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
1331 else
1332 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE;
1333 } else {
1334 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1335 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1336 if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1337 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1338 else
1339 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE;
1340 }
1341 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1342}
1343
1344
1345
1346
1347
1348
1349
1350
1351static void
1352zynqmp_disp_av_buf_disable_vid(struct zynqmp_disp_av_buf *av_buf,
1353 struct zynqmp_disp_layer *layer)
1354{
1355 u32 reg;
1356
1357 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1358 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1359 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1360 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE;
1361 } else {
1362 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1363 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE;
1364 }
1365 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1366}
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377static void zynqmp_disp_av_buf_init_sf(struct zynqmp_disp_av_buf *av_buf,
1378 const struct zynqmp_disp_fmt *vid_fmt,
1379 const struct zynqmp_disp_fmt *gfx_fmt)
1380{
1381 unsigned int i;
1382 u32 offset;
1383
1384 if (gfx_fmt) {
1385 offset = ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF;
1386 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1387 zynqmp_disp_write(av_buf->base, offset + i * 4,
1388 gfx_fmt->sf[i]);
1389 }
1390
1391 if (vid_fmt) {
1392 offset = ZYNQMP_DISP_AV_BUF_VID_COMP0_SF;
1393 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1394 zynqmp_disp_write(av_buf->base, offset + i * 4,
1395 vid_fmt->sf[i]);
1396 }
1397}
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407static void zynqmp_disp_av_buf_init_live_sf(struct zynqmp_disp_av_buf *av_buf,
1408 const struct zynqmp_disp_fmt *fmt,
1409 bool is_vid)
1410{
1411 unsigned int i;
1412 u32 offset;
1413
1414 if (is_vid)
1415 offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF;
1416 else
1417 offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF;
1418
1419 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1420 zynqmp_disp_write(av_buf->base, offset + i * 4,
1421 fmt->sf[i]);
1422}
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435static void zynqmp_disp_aud_init(struct zynqmp_disp_aud *aud)
1436{
1437
1438 regmap_write(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
1439 regmap_write(aud->base, ZYNQMP_DISP_AUD_MIXER_VOLUME,
1440 ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
1441}
1442
1443
1444
1445
1446
1447
1448
1449static void zynqmp_disp_aud_deinit(struct zynqmp_disp_aud *aud)
1450{
1451 regmap_write_bits(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET,
1452 ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST,
1453 ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
1454}
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473static int zynqmp_disp_layer_check_size(struct zynqmp_disp *disp,
1474 struct zynqmp_disp_layer *layer,
1475 u32 width, u32 height)
1476{
1477 struct zynqmp_disp_layer *other = layer->other;
1478
1479 if (other->enabled && (other->w != width || other->h != height)) {
1480 dev_err(disp->dev, "Layer width:height must be %d:%d\n",
1481 other->w, other->h);
1482 return -EINVAL;
1483 }
1484
1485 layer->w = width;
1486 layer->h = height;
1487
1488 return 0;
1489}
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503static const struct zynqmp_disp_fmt *
1504zynqmp_disp_map_fmt(const struct zynqmp_disp_fmt fmts[],
1505 unsigned int size, uint32_t drm_fmt)
1506{
1507 unsigned int i;
1508
1509 for (i = 0; i < size; i++)
1510 if (fmts[i].drm_fmt == drm_fmt)
1511 return &fmts[i];
1512
1513 return NULL;
1514}
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526static int zynqmp_disp_layer_set_fmt(struct zynqmp_disp *disp,
1527 struct zynqmp_disp_layer *layer,
1528 uint32_t drm_fmt)
1529{
1530 const struct zynqmp_disp_fmt *fmt;
1531 const struct zynqmp_disp_fmt *vid_fmt = NULL, *gfx_fmt = NULL;
1532 u32 size, fmts, mask;
1533
1534 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1535 size = ARRAY_SIZE(av_buf_vid_fmts);
1536 mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK;
1537 fmt = zynqmp_disp_map_fmt(av_buf_vid_fmts, size, drm_fmt);
1538 vid_fmt = fmt;
1539 } else {
1540 size = ARRAY_SIZE(av_buf_gfx_fmts);
1541 mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
1542 fmt = zynqmp_disp_map_fmt(av_buf_gfx_fmts, size, drm_fmt);
1543 gfx_fmt = fmt;
1544 }
1545
1546 if (!fmt)
1547 return -EINVAL;
1548
1549 fmts = zynqmp_disp_av_buf_get_fmt(&disp->av_buf);
1550 fmts &= mask;
1551 fmts |= fmt->disp_fmt;
1552 zynqmp_disp_av_buf_set_fmt(&disp->av_buf, fmts);
1553 zynqmp_disp_av_buf_init_sf(&disp->av_buf, vid_fmt, gfx_fmt);
1554 layer->fmt = fmt;
1555
1556 return 0;
1557}
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571static const struct zynqmp_disp_fmt *
1572zynqmp_disp_map_live_fmt(const struct zynqmp_disp_fmt fmts[],
1573 unsigned int size, uint32_t bus_fmt)
1574{
1575 unsigned int i;
1576
1577 for (i = 0; i < size; i++)
1578 if (fmts[i].bus_fmt == bus_fmt)
1579 return &fmts[i];
1580
1581 return NULL;
1582}
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594static int zynqmp_disp_layer_set_live_fmt(struct zynqmp_disp *disp,
1595 struct zynqmp_disp_layer *layer,
1596 uint32_t bus_fmt)
1597{
1598 const struct zynqmp_disp_fmt *fmt;
1599 u32 size;
1600 bool is_vid = layer->id == ZYNQMP_DISP_LAYER_VID;
1601
1602 size = ARRAY_SIZE(av_buf_live_fmts);
1603 fmt = zynqmp_disp_map_live_fmt(av_buf_live_fmts, size, bus_fmt);
1604 if (!fmt)
1605 return -EINVAL;
1606
1607 zynqmp_disp_av_buf_set_live_fmt(&disp->av_buf, fmt->disp_fmt, is_vid);
1608 zynqmp_disp_av_buf_init_live_sf(&disp->av_buf, fmt, is_vid);
1609 layer->fmt = fmt;
1610
1611 return 0;
1612}
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626static int zynqmp_disp_layer_set_tpg(struct zynqmp_disp *disp,
1627 struct zynqmp_disp_layer *layer,
1628 bool tpg_on)
1629{
1630 if (layer->id != ZYNQMP_DISP_LAYER_VID) {
1631 dev_err(disp->dev,
1632 "only the video layer has the tpg mode\n");
1633 return -ENODEV;
1634 }
1635
1636 if (layer->enabled) {
1637 dev_err(disp->dev,
1638 "the video layer should be disabled for tpg mode\n");
1639 return -EIO;
1640 }
1641
1642 disp->tpg_on = tpg_on;
1643 zynqmp_disp_av_buf_set_tpg(&disp->av_buf, tpg_on);
1644
1645 return 0;
1646}
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657static bool zynqmp_disp_layer_get_tpg(struct zynqmp_disp *disp,
1658 struct zynqmp_disp_layer *layer)
1659{
1660 return disp->tpg_on;
1661}
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672static void zynqmp_disp_layer_get_fmts(struct zynqmp_disp *disp,
1673 struct zynqmp_disp_layer *layer,
1674 u32 **drm_fmts, unsigned int *num_fmts)
1675{
1676 *drm_fmts = layer->drm_fmts;
1677 *num_fmts = layer->num_fmts;
1678}
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690static int zynqmp_disp_layer_enable(struct zynqmp_disp *disp,
1691 struct zynqmp_disp_layer *layer,
1692 enum zynqmp_disp_layer_mode mode)
1693{
1694 struct device *dev = disp->dev;
1695 struct dma_async_tx_descriptor *desc;
1696 unsigned long flags;
1697 unsigned int i;
1698
1699 if (layer->enabled && layer->mode != mode) {
1700 dev_err(dev, "layer is already enabled in different mode\n");
1701 return -EBUSY;
1702 }
1703
1704 zynqmp_disp_av_buf_enable_vid(&disp->av_buf, layer, mode);
1705 zynqmp_disp_blend_layer_enable(&disp->blend, layer);
1706
1707 layer->enabled = true;
1708 layer->mode = mode;
1709
1710 if (mode == ZYNQMP_DISP_LAYER_LIVE)
1711 return 0;
1712
1713 for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++) {
1714 struct zynqmp_disp_layer_dma *dma = &layer->dma[i];
1715
1716 if (dma->chan && dma->is_active) {
1717 flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_PREP_REPEAT |
1718 DMA_PREP_LOAD_EOT;
1719 desc = dmaengine_prep_interleaved_dma(dma->chan,
1720 &dma->xt, flags);
1721 if (!desc) {
1722 dev_err(dev, "failed to prep DMA descriptor\n");
1723 return -ENOMEM;
1724 }
1725
1726 dmaengine_submit(desc);
1727 dma_async_issue_pending(dma->chan);
1728 }
1729 }
1730
1731 return 0;
1732}
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744static int zynqmp_disp_layer_disable(struct zynqmp_disp *disp,
1745 struct zynqmp_disp_layer *layer,
1746 enum zynqmp_disp_layer_mode mode)
1747{
1748 struct device *dev = disp->dev;
1749 unsigned int i;
1750
1751 if (layer->mode != mode) {
1752 dev_err(dev, "the layer is operating in different mode\n");
1753 return -EBUSY;
1754 }
1755
1756 for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
1757 if (layer->dma[i].chan && layer->dma[i].is_active)
1758 dmaengine_terminate_sync(layer->dma[i].chan);
1759
1760 zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
1761 zynqmp_disp_blend_layer_disable(&disp->blend, layer);
1762 layer->enabled = false;
1763
1764 return 0;
1765}
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777static int
1778zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
1779 struct zynqmp_disp_layer *layer, const char *name)
1780{
1781 struct zynqmp_disp_layer_dma *dma;
1782 unsigned int i;
1783 int ret;
1784
1785 for (i = 0; i < layer->num_chan; i++) {
1786 char temp[16];
1787
1788 dma = &layer->dma[i];
1789 snprintf(temp, sizeof(temp), "%s%d", name, i);
1790 dma->chan = of_dma_request_slave_channel(disp->dev->of_node,
1791 temp);
1792 if (IS_ERR(dma->chan)) {
1793 dev_err(disp->dev, "failed to request dma channel\n");
1794 ret = PTR_ERR(dma->chan);
1795 dma->chan = NULL;
1796 return ret;
1797 }
1798 }
1799
1800 return 0;
1801}
1802
1803
1804
1805
1806
1807
1808
1809
1810static void zynqmp_disp_layer_release_dma(struct zynqmp_disp *disp,
1811 struct zynqmp_disp_layer *layer)
1812{
1813 unsigned int i;
1814
1815 for (i = 0; i < layer->num_chan; i++) {
1816 if (layer->dma[i].chan) {
1817
1818 dmaengine_terminate_all(layer->dma[i].chan);
1819 dma_release_channel(layer->dma[i].chan);
1820 }
1821 }
1822}
1823
1824
1825
1826
1827
1828
1829
1830static bool zynqmp_disp_layer_is_live(struct zynqmp_disp *disp)
1831{
1832 unsigned int i;
1833
1834 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
1835 if (disp->layers[i].enabled &&
1836 disp->layers[i].mode == ZYNQMP_DISP_LAYER_LIVE)
1837 return true;
1838 }
1839
1840 return false;
1841}
1842
1843
1844
1845
1846
1847
1848
1849static bool zynqmp_disp_layer_is_enabled(struct zynqmp_disp *disp)
1850{
1851 unsigned int i;
1852
1853 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
1854 if (disp->layers[i].enabled)
1855 return true;
1856
1857 return false;
1858}
1859
1860
1861
1862
1863
1864
1865
1866static void zynqmp_disp_layer_destroy(struct zynqmp_disp *disp)
1867{
1868 unsigned int i;
1869
1870 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
1871 zynqmp_disp_layer_release_dma(disp, &disp->layers[i]);
1872}
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882static int zynqmp_disp_layer_create(struct zynqmp_disp *disp)
1883{
1884 struct zynqmp_disp_layer *layer;
1885 unsigned int i;
1886 int num_chans[ZYNQMP_DISP_NUM_LAYERS] = { 3, 1 };
1887 const char * const dma_name[] = { "vid", "gfx" };
1888 int ret = -EINVAL;
1889
1890 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
1891 layer = &disp->layers[i];
1892 layer->id = (enum zynqmp_disp_layer_type)i;
1893 layer->offset = i * 4;
1894 layer->other = &disp->layers[!i];
1895 layer->num_chan = num_chans[i];
1896 ret = zynqmp_disp_layer_request_dma(disp, layer, dma_name[i]);
1897 if (ret)
1898 goto err;
1899 layer->disp = disp;
1900 }
1901
1902 return 0;
1903
1904err:
1905 zynqmp_disp_layer_destroy(disp);
1906 return ret;
1907}
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918static struct drm_prop_enum_list zynqmp_disp_color_enum[] = {
1919 { 0, "rgb" },
1920 { 1, "ycrcb444" },
1921 { 2, "ycrcb422" },
1922 { 3, "yonly" },
1923};
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934static void
1935zynqmp_disp_set_output_fmt(struct zynqmp_disp *disp, unsigned int id)
1936{
1937 const struct zynqmp_disp_fmt *fmt = &blend_output_fmts[id];
1938
1939 zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[id].name);
1940 zynqmp_disp_blend_set_output_fmt(&disp->blend, fmt->disp_fmt);
1941}
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952static void zynqmp_disp_set_bg_color(struct zynqmp_disp *disp,
1953 u32 c0, u32 c1, u32 c2)
1954{
1955 zynqmp_disp_blend_set_bg_color(&disp->blend, c0, c1, c2);
1956}
1957
1958
1959
1960
1961
1962
1963
1964
1965static void zynqmp_disp_set_alpha(struct zynqmp_disp *disp, u32 alpha)
1966{
1967 disp->alpha = alpha;
1968 zynqmp_disp_blend_set_alpha(&disp->blend, alpha);
1969}
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979static u32 zynqmp_disp_get_alpha(struct zynqmp_disp *disp)
1980{
1981 return disp->alpha;
1982}
1983
1984
1985
1986
1987
1988
1989
1990
1991static void zynqmp_disp_set_g_alpha(struct zynqmp_disp *disp, bool enable)
1992{
1993 disp->alpha_en = enable;
1994 zynqmp_disp_blend_enable_alpha(&disp->blend, enable);
1995}
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005static bool zynqmp_disp_get_g_alpha(struct zynqmp_disp *disp)
2006{
2007 return disp->alpha_en;
2008}
2009
2010
2011
2012
2013
2014
2015
2016static void zynqmp_disp_enable(struct zynqmp_disp *disp)
2017{
2018 bool live;
2019
2020 if (disp->enabled)
2021 return;
2022
2023 zynqmp_disp_av_buf_enable(&disp->av_buf);
2024
2025 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, !!disp->_ps_pclk);
2026 zynqmp_disp_av_buf_set_aud_clock_src(&disp->av_buf, !!disp->_ps_audclk);
2027 live = zynqmp_disp_layer_is_live(disp);
2028 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, !live);
2029 zynqmp_disp_av_buf_enable_buf(&disp->av_buf);
2030 zynqmp_disp_av_buf_enable_aud(&disp->av_buf);
2031 zynqmp_disp_aud_init(&disp->aud);
2032 disp->enabled = true;
2033}
2034
2035
2036
2037
2038
2039
2040
2041
2042static void zynqmp_disp_disable(struct zynqmp_disp *disp, bool force)
2043{
2044 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2045
2046 if (!force && (!disp->enabled || zynqmp_disp_layer_is_enabled(disp)))
2047 return;
2048
2049 zynqmp_disp_aud_deinit(&disp->aud);
2050 zynqmp_disp_av_buf_disable_aud(&disp->av_buf);
2051 zynqmp_disp_av_buf_disable_buf(&disp->av_buf);
2052 zynqmp_disp_av_buf_disable(&disp->av_buf);
2053
2054
2055 if (crtc->state->event) {
2056 complete_all(crtc->state->event->base.completion);
2057 crtc->state->event = NULL;
2058 }
2059
2060 disp->enabled = false;
2061}
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071static void zynqmp_disp_init(struct zynqmp_disp *disp)
2072{
2073 struct zynqmp_disp_layer *layer;
2074 unsigned int i;
2075
2076 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2077 layer = &disp->layers[i];
2078 zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
2079 }
2080}
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
2094{
2095 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2096
2097 drm_crtc_handle_vblank(crtc);
2098}
2099
2100
2101
2102
2103
2104
2105
2106unsigned int zynqmp_disp_get_apb_clk_rate(struct zynqmp_disp *disp)
2107{
2108 return clk_get_rate(disp->aclk);
2109}
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119bool zynqmp_disp_aud_enabled(struct zynqmp_disp *disp)
2120{
2121 return !!disp->audclk;
2122}
2123
2124
2125
2126
2127
2128
2129
2130unsigned int zynqmp_disp_get_aud_clk_rate(struct zynqmp_disp *disp)
2131{
2132 if (zynqmp_disp_aud_enabled(disp))
2133 return 0;
2134 return clk_get_rate(disp->aclk);
2135}
2136
2137
2138
2139
2140
2141
2142
2143uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp)
2144{
2145 return drm_crtc_mask(&disp->xlnx_crtc.crtc);
2146}
2147
2148
2149
2150
2151
2152static inline struct zynqmp_disp_layer *plane_to_layer(struct drm_plane *plane)
2153{
2154 return container_of(plane, struct zynqmp_disp_layer, plane);
2155}
2156
2157static int zynqmp_disp_plane_enable(struct drm_plane *plane)
2158{
2159 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2160 struct zynqmp_disp *disp = layer->disp;
2161 int ret;
2162
2163 zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2164 zynqmp_disp_set_alpha(disp, disp->alpha);
2165 ret = zynqmp_disp_layer_enable(layer->disp, layer,
2166 ZYNQMP_DISP_LAYER_NONLIVE);
2167 if (ret)
2168 return ret;
2169
2170 if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2171 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2172 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2173 }
2174
2175 return 0;
2176}
2177
2178static int zynqmp_disp_plane_disable(struct drm_plane *plane)
2179{
2180 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2181 struct zynqmp_disp *disp = layer->disp;
2182
2183 zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_NONLIVE);
2184 if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2185 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2186
2187 return 0;
2188}
2189
2190static int zynqmp_disp_plane_mode_set(struct drm_plane *plane,
2191 struct drm_framebuffer *fb,
2192 int crtc_x, int crtc_y,
2193 unsigned int crtc_w, unsigned int crtc_h,
2194 u32 src_x, u32 src_y,
2195 u32 src_w, u32 src_h)
2196{
2197 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2198 const struct drm_format_info *info = fb->format;
2199 struct device *dev = layer->disp->dev;
2200 dma_addr_t paddr;
2201 unsigned int i;
2202 int ret;
2203
2204 if (!info) {
2205 dev_err(dev, "No format info found\n");
2206 return -EINVAL;
2207 }
2208
2209 ret = zynqmp_disp_layer_check_size(layer->disp, layer, src_w, src_h);
2210 if (ret)
2211 return ret;
2212
2213 for (i = 0; i < info->num_planes; i++) {
2214 unsigned int width = src_w / (i ? info->hsub : 1);
2215 unsigned int height = src_h / (i ? info->vsub : 1);
2216 int width_bytes;
2217
2218 paddr = drm_fb_cma_get_gem_addr(fb, plane->state, i);
2219 if (!paddr) {
2220 dev_err(dev, "failed to get a paddr\n");
2221 return -EINVAL;
2222 }
2223
2224 layer->dma[i].xt.numf = height;
2225 width_bytes = drm_format_plane_width_bytes(info, i, width);
2226 layer->dma[i].sgl[0].size = width_bytes;
2227 layer->dma[i].sgl[0].icg = fb->pitches[i] -
2228 layer->dma[i].sgl[0].size;
2229 layer->dma[i].xt.src_start = paddr;
2230 layer->dma[i].xt.frame_size = 1;
2231 layer->dma[i].xt.dir = DMA_MEM_TO_DEV;
2232 layer->dma[i].xt.src_sgl = true;
2233 layer->dma[i].xt.dst_sgl = false;
2234 layer->dma[i].is_active = true;
2235 }
2236
2237 for (; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
2238 layer->dma[i].is_active = false;
2239
2240 ret = zynqmp_disp_layer_set_fmt(layer->disp, layer, info->format);
2241 if (ret)
2242 dev_err(dev, "failed to set dp_sub layer fmt\n");
2243
2244 return ret;
2245}
2246
2247static void zynqmp_disp_plane_destroy(struct drm_plane *plane)
2248{
2249 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2250
2251 xlnx_bridge_unregister(&layer->bridge);
2252 drm_plane_cleanup(plane);
2253}
2254
2255static int
2256zynqmp_disp_plane_atomic_set_property(struct drm_plane *plane,
2257 struct drm_plane_state *state,
2258 struct drm_property *property, u64 val)
2259{
2260 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2261 struct zynqmp_disp *disp = layer->disp;
2262 int ret = 0;
2263
2264 if (property == disp->g_alpha_prop)
2265 zynqmp_disp_set_alpha(disp, val);
2266 else if (property == disp->g_alpha_en_prop)
2267 zynqmp_disp_set_g_alpha(disp, val);
2268 else if (property == disp->tpg_prop)
2269 ret = zynqmp_disp_layer_set_tpg(disp, layer, val);
2270 else
2271 return -EINVAL;
2272
2273 return ret;
2274}
2275
2276static int
2277zynqmp_disp_plane_atomic_get_property(struct drm_plane *plane,
2278 const struct drm_plane_state *state,
2279 struct drm_property *property,
2280 uint64_t *val)
2281{
2282 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2283 struct zynqmp_disp *disp = layer->disp;
2284 int ret = 0;
2285
2286 if (property == disp->g_alpha_prop)
2287 *val = zynqmp_disp_get_alpha(disp);
2288 else if (property == disp->g_alpha_en_prop)
2289 *val = zynqmp_disp_get_g_alpha(disp);
2290 else if (property == disp->tpg_prop)
2291 *val = zynqmp_disp_layer_get_tpg(disp, layer);
2292 else
2293 return -EINVAL;
2294
2295 return ret;
2296}
2297
2298static int
2299zynqmp_disp_plane_atomic_update_plane(struct drm_plane *plane,
2300 struct drm_crtc *crtc,
2301 struct drm_framebuffer *fb,
2302 int crtc_x, int crtc_y,
2303 unsigned int crtc_w, unsigned int crtc_h,
2304 u32 src_x, u32 src_y,
2305 u32 src_w, u32 src_h,
2306 struct drm_modeset_acquire_ctx *ctx)
2307{
2308 struct drm_atomic_state *state;
2309 struct drm_plane_state *plane_state;
2310 int ret;
2311
2312 state = drm_atomic_state_alloc(plane->dev);
2313 if (!state)
2314 return -ENOMEM;
2315
2316 state->acquire_ctx = ctx;
2317 plane_state = drm_atomic_get_plane_state(state, plane);
2318 if (IS_ERR(plane_state)) {
2319 ret = PTR_ERR(plane_state);
2320 goto fail;
2321 }
2322
2323 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
2324 if (ret)
2325 goto fail;
2326 drm_atomic_set_fb_for_plane(plane_state, fb);
2327 plane_state->crtc_x = crtc_x;
2328 plane_state->crtc_y = crtc_y;
2329 plane_state->crtc_w = crtc_w;
2330 plane_state->crtc_h = crtc_h;
2331 plane_state->src_x = src_x;
2332 plane_state->src_y = src_y;
2333 plane_state->src_w = src_w;
2334 plane_state->src_h = src_h;
2335
2336 if (plane == crtc->cursor)
2337 state->legacy_cursor_update = true;
2338
2339
2340 state->async_update = !drm_atomic_helper_async_check(plane->dev, state);
2341 ret = drm_atomic_commit(state);
2342fail:
2343 drm_atomic_state_put(state);
2344 return ret;
2345}
2346
2347static struct drm_plane_funcs zynqmp_disp_plane_funcs = {
2348 .update_plane = zynqmp_disp_plane_atomic_update_plane,
2349 .disable_plane = drm_atomic_helper_disable_plane,
2350 .atomic_set_property = zynqmp_disp_plane_atomic_set_property,
2351 .atomic_get_property = zynqmp_disp_plane_atomic_get_property,
2352 .destroy = zynqmp_disp_plane_destroy,
2353 .reset = drm_atomic_helper_plane_reset,
2354 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
2355 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
2356};
2357
2358static void
2359zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
2360 struct drm_atomic_state *state)
2361{
2362 int ret;
2363 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
2364
2365 if (!plane->state->crtc || !plane->state->fb)
2366 return;
2367
2368 if (plane->state->fb == old_state->fb &&
2369 plane->state->crtc_x == old_state->crtc_x &&
2370 plane->state->crtc_y == old_state->crtc_y &&
2371 plane->state->crtc_w == old_state->crtc_w &&
2372 plane->state->crtc_h == old_state->crtc_h &&
2373 plane->state->src_x == old_state->src_x &&
2374 plane->state->src_y == old_state->src_y &&
2375 plane->state->src_w == old_state->src_w &&
2376 plane->state->src_h == old_state->src_h)
2377 return;
2378
2379 if (old_state->fb &&
2380 old_state->fb->format->format != plane->state->fb->format->format)
2381 zynqmp_disp_plane_disable(plane);
2382
2383 ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
2384 plane->state->crtc_x,
2385 plane->state->crtc_y,
2386 plane->state->crtc_w,
2387 plane->state->crtc_h,
2388 plane->state->src_x >> 16,
2389 plane->state->src_y >> 16,
2390 plane->state->src_w >> 16,
2391 plane->state->src_h >> 16);
2392 if (ret)
2393 return;
2394
2395 zynqmp_disp_plane_enable(plane);
2396}
2397
2398static void
2399zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
2400 struct drm_atomic_state *state)
2401{
2402 zynqmp_disp_plane_disable(plane);
2403}
2404
2405static int zynqmp_disp_plane_atomic_async_check(struct drm_plane *plane,
2406 struct drm_atomic_state *state)
2407{
2408 return 0;
2409}
2410
2411static void
2412zynqmp_disp_plane_atomic_async_update(struct drm_plane *plane,
2413 struct drm_atomic_state *state)
2414{
2415 int ret;
2416 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
2417
2418 if (plane->state->fb == new_state->fb)
2419 return;
2420
2421 if (plane->state->fb &&
2422 plane->state->fb->format->format != new_state->fb->format->format)
2423 zynqmp_disp_plane_disable(plane);
2424
2425
2426 swap(plane->state->fb, new_state->fb);
2427 plane->state->crtc = new_state->crtc;
2428 plane->state->crtc_x = new_state->crtc_x;
2429 plane->state->crtc_y = new_state->crtc_y;
2430 plane->state->crtc_w = new_state->crtc_w;
2431 plane->state->crtc_h = new_state->crtc_h;
2432 plane->state->src_x = new_state->src_x;
2433 plane->state->src_y = new_state->src_y;
2434 plane->state->src_w = new_state->src_w;
2435 plane->state->src_h = new_state->src_h;
2436 plane->state->state = new_state->state;
2437
2438 ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
2439 plane->state->crtc_x,
2440 plane->state->crtc_y,
2441 plane->state->crtc_w,
2442 plane->state->crtc_h,
2443 plane->state->src_x >> 16,
2444 plane->state->src_y >> 16,
2445 plane->state->src_w >> 16,
2446 plane->state->src_h >> 16);
2447 if (ret)
2448 return;
2449
2450 zynqmp_disp_plane_enable(plane);
2451}
2452
2453static const struct drm_plane_helper_funcs zynqmp_disp_plane_helper_funcs = {
2454 .atomic_update = zynqmp_disp_plane_atomic_update,
2455 .atomic_disable = zynqmp_disp_plane_atomic_disable,
2456 .atomic_async_check = zynqmp_disp_plane_atomic_async_check,
2457 .atomic_async_update = zynqmp_disp_plane_atomic_async_update,
2458};
2459
2460static int zynqmp_disp_create_plane(struct zynqmp_disp *disp)
2461{
2462 struct zynqmp_disp_layer *layer;
2463 unsigned int i;
2464 u32 *fmts = NULL;
2465 unsigned int num_fmts = 0;
2466 enum drm_plane_type type;
2467 int ret;
2468
2469
2470 type = DRM_PLANE_TYPE_OVERLAY;
2471 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2472 layer = &disp->layers[i];
2473 zynqmp_disp_layer_get_fmts(disp, layer, &fmts, &num_fmts);
2474 ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
2475 &zynqmp_disp_plane_funcs, fmts,
2476 num_fmts, NULL, type, NULL);
2477 if (ret)
2478 goto err_plane;
2479 drm_plane_helper_add(&layer->plane,
2480 &zynqmp_disp_plane_helper_funcs);
2481 type = DRM_PLANE_TYPE_PRIMARY;
2482 }
2483
2484
2485 drm_object_attach_property(&layer->plane.base, disp->g_alpha_prop,
2486 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX);
2487 disp->alpha = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
2488
2489 drm_object_attach_property(&layer->plane.base, disp->g_alpha_en_prop,
2490 true);
2491 disp->alpha_en = true;
2492
2493 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2494 drm_object_attach_property(&layer->plane.base, disp->tpg_prop, false);
2495
2496 return ret;
2497
2498err_plane:
2499 if (i)
2500 drm_plane_cleanup(&disp->layers[0].plane);
2501 return ret;
2502}
2503
2504static void zynqmp_disp_destroy_plane(struct zynqmp_disp *disp)
2505{
2506 unsigned int i;
2507
2508 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2509 zynqmp_disp_plane_destroy(&disp->layers[i].plane);
2510}
2511
2512
2513
2514
2515
2516static inline struct zynqmp_disp *xlnx_crtc_to_disp(struct xlnx_crtc *xlnx_crtc)
2517{
2518 return container_of(xlnx_crtc, struct zynqmp_disp, xlnx_crtc);
2519}
2520
2521static int zynqmp_disp_get_max_width(struct xlnx_crtc *xlnx_crtc)
2522{
2523 return ZYNQMP_DISP_MAX_WIDTH;
2524}
2525
2526static int zynqmp_disp_get_max_height(struct xlnx_crtc *xlnx_crtc)
2527{
2528 return ZYNQMP_DISP_MAX_HEIGHT;
2529}
2530
2531static uint32_t zynqmp_disp_get_format(struct xlnx_crtc *xlnx_crtc)
2532{
2533 struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2534
2535 return disp->layers[ZYNQMP_DISP_LAYER_GFX].fmt->drm_fmt;
2536}
2537
2538static unsigned int zynqmp_disp_get_align(struct xlnx_crtc *xlnx_crtc)
2539{
2540 struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2541 struct zynqmp_disp_layer *layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2542
2543 return 1 << layer->dma->chan->device->copy_align;
2544}
2545
2546static u64 zynqmp_disp_get_dma_mask(struct xlnx_crtc *xlnx_crtc)
2547{
2548 return DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT);
2549}
2550
2551
2552
2553
2554
2555static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
2556{
2557 struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
2558
2559 return xlnx_crtc_to_disp(xlnx_crtc);
2560}
2561
2562static int zynqmp_disp_crtc_mode_set(struct drm_crtc *crtc,
2563 struct drm_display_mode *mode,
2564 struct drm_display_mode *adjusted_mode,
2565 int x, int y,
2566 struct drm_framebuffer *old_fb)
2567{
2568 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2569 unsigned long rate;
2570 long diff;
2571 int ret;
2572
2573 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2574 ret = clk_set_rate(disp->pclk,
2575 (unsigned long)adjusted_mode->clock * 1000);
2576 if (ret) {
2577 dev_err(disp->dev, "failed to set a pixel clock\n");
2578 return ret;
2579 }
2580
2581 rate = clk_get_rate(disp->pclk);
2582 diff = rate - (unsigned long)adjusted_mode->clock * 1000;
2583 if (abs(diff) > ((long)adjusted_mode->clock * 1000) / 20) {
2584 dev_info(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2585 adjusted_mode->clock, rate);
2586 } else {
2587 dev_dbg(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2588 adjusted_mode->clock, rate);
2589 }
2590
2591
2592 zynqmp_dp_encoder_mode_set_stream(disp->dpsub->dp, adjusted_mode);
2593
2594 return 0;
2595}
2596
2597static void
2598zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
2599 struct drm_atomic_state *state)
2600{
2601 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2602 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2603 int ret, vrefresh;
2604
2605 zynqmp_disp_crtc_mode_set(crtc, &crtc->state->mode,
2606 adjusted_mode, crtc->x, crtc->y, NULL);
2607
2608 ret = pm_runtime_get_sync(disp->dev);
2609 if (ret < 0) {
2610 dev_err(disp->dev, "IRQ sync failed to resume: %d\n", ret);
2611 return;
2612 }
2613
2614 ret = zynqmp_disp_clk_enable(disp->pclk, &disp->pclk_en);
2615 if (ret) {
2616 dev_err(disp->dev, "failed to enable a pixel clock\n");
2617 return;
2618 }
2619 zynqmp_disp_set_output_fmt(disp, disp->color);
2620 zynqmp_disp_set_bg_color(disp, disp->bg_c0, disp->bg_c1, disp->bg_c2);
2621 zynqmp_disp_enable(disp);
2622
2623 vrefresh = (adjusted_mode->clock * 1000) /
2624 (adjusted_mode->vtotal * adjusted_mode->htotal);
2625 msleep(3 * 1000 / vrefresh);
2626}
2627
2628static void
2629zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
2630 struct drm_atomic_state *state)
2631{
2632 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2633
2634 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2635 zynqmp_disp_plane_disable(crtc->primary);
2636 zynqmp_disp_disable(disp, true);
2637 if (!disp->dpsub->external_crtc_attached)
2638 drm_crtc_vblank_off(crtc);
2639 pm_runtime_put_sync(disp->dev);
2640}
2641
2642static int zynqmp_disp_crtc_atomic_check(struct drm_crtc *crtc,
2643 struct drm_atomic_state *state)
2644{
2645 return drm_atomic_add_affected_planes(state, crtc);
2646}
2647
2648static void
2649zynqmp_disp_crtc_atomic_begin(struct drm_crtc *crtc,
2650 struct drm_atomic_state *state)
2651{
2652 drm_crtc_vblank_on(crtc);
2653
2654 spin_lock_irq(&crtc->dev->event_lock);
2655 if (crtc->state->event) {
2656
2657 crtc->state->event->pipe = drm_crtc_index(crtc);
2658 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
2659 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
2660 crtc->state->event = NULL;
2661 }
2662 spin_unlock_irq(&crtc->dev->event_lock);
2663}
2664
2665static struct drm_crtc_helper_funcs zynqmp_disp_crtc_helper_funcs = {
2666 .atomic_enable = zynqmp_disp_crtc_atomic_enable,
2667 .atomic_disable = zynqmp_disp_crtc_atomic_disable,
2668 .atomic_check = zynqmp_disp_crtc_atomic_check,
2669 .atomic_begin = zynqmp_disp_crtc_atomic_begin,
2670};
2671
2672static void zynqmp_disp_crtc_destroy(struct drm_crtc *crtc)
2673{
2674 zynqmp_disp_crtc_atomic_disable(crtc, NULL);
2675 drm_crtc_cleanup(crtc);
2676}
2677
2678static int zynqmp_disp_crtc_enable_vblank(struct drm_crtc *crtc)
2679{
2680 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2681
2682 zynqmp_dp_enable_vblank(disp->dpsub->dp);
2683
2684 return 0;
2685}
2686
2687static void zynqmp_disp_crtc_disable_vblank(struct drm_crtc *crtc)
2688{
2689 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2690
2691 zynqmp_dp_disable_vblank(disp->dpsub->dp);
2692}
2693
2694static int
2695zynqmp_disp_crtc_atomic_set_property(struct drm_crtc *crtc,
2696 struct drm_crtc_state *state,
2697 struct drm_property *property,
2698 uint64_t val)
2699{
2700 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2701
2702
2703
2704
2705
2706 if (property == disp->color_prop)
2707 disp->color = val;
2708 else if (property == disp->bg_c0_prop)
2709 disp->bg_c0 = val;
2710 else if (property == disp->bg_c1_prop)
2711 disp->bg_c1 = val;
2712 else if (property == disp->bg_c2_prop)
2713 disp->bg_c2 = val;
2714 else
2715 return -EINVAL;
2716
2717 return 0;
2718}
2719
2720static int
2721zynqmp_disp_crtc_atomic_get_property(struct drm_crtc *crtc,
2722 const struct drm_crtc_state *state,
2723 struct drm_property *property,
2724 uint64_t *val)
2725{
2726 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2727
2728 if (property == disp->color_prop)
2729 *val = disp->color;
2730 else if (property == disp->bg_c0_prop)
2731 *val = disp->bg_c0;
2732 else if (property == disp->bg_c1_prop)
2733 *val = disp->bg_c1;
2734 else if (property == disp->bg_c2_prop)
2735 *val = disp->bg_c2;
2736 else
2737 return -EINVAL;
2738
2739 return 0;
2740}
2741
2742static struct drm_crtc_funcs zynqmp_disp_crtc_funcs = {
2743 .destroy = zynqmp_disp_crtc_destroy,
2744 .set_config = drm_atomic_helper_set_config,
2745 .page_flip = drm_atomic_helper_page_flip,
2746 .atomic_set_property = zynqmp_disp_crtc_atomic_set_property,
2747 .atomic_get_property = zynqmp_disp_crtc_atomic_get_property,
2748 .reset = drm_atomic_helper_crtc_reset,
2749 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
2750 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
2751 .enable_vblank = zynqmp_disp_crtc_enable_vblank,
2752 .disable_vblank = zynqmp_disp_crtc_disable_vblank,
2753};
2754
2755static int zynqmp_disp_create_crtc(struct zynqmp_disp *disp)
2756{
2757 struct drm_plane *plane = &disp->layers[ZYNQMP_DISP_LAYER_GFX].plane;
2758 struct drm_mode_object *obj = &disp->xlnx_crtc.crtc.base;
2759 int ret;
2760
2761 ret = drm_crtc_init_with_planes(disp->drm, &disp->xlnx_crtc.crtc,
2762 plane, NULL, &zynqmp_disp_crtc_funcs,
2763 NULL);
2764 if (ret < 0) {
2765 dev_err(disp->dev, "failed to initialize disp CRTC: %d\n",
2766 ret);
2767 return ret;
2768 }
2769
2770 drm_crtc_helper_add(&disp->xlnx_crtc.crtc,
2771 &zynqmp_disp_crtc_helper_funcs);
2772 drm_object_attach_property(obj, disp->color_prop, 0);
2773 zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[0].name);
2774 drm_object_attach_property(obj, disp->bg_c0_prop, 0);
2775 drm_object_attach_property(obj, disp->bg_c1_prop, 0);
2776 drm_object_attach_property(obj, disp->bg_c2_prop, 0);
2777
2778 disp->xlnx_crtc.get_max_width = &zynqmp_disp_get_max_width;
2779 disp->xlnx_crtc.get_max_height = &zynqmp_disp_get_max_height;
2780 disp->xlnx_crtc.get_format = &zynqmp_disp_get_format;
2781 disp->xlnx_crtc.get_align = &zynqmp_disp_get_align;
2782 disp->xlnx_crtc.get_dma_mask = &zynqmp_disp_get_dma_mask;
2783
2784 if (!disp->dpsub->external_crtc_attached)
2785 xlnx_crtc_register(disp->drm, &disp->xlnx_crtc);
2786
2787 return 0;
2788}
2789
2790static void zynqmp_disp_destroy_crtc(struct zynqmp_disp *disp)
2791{
2792 if (!disp->dpsub->external_crtc_attached)
2793 xlnx_crtc_unregister(disp->drm, &disp->xlnx_crtc);
2794 zynqmp_disp_crtc_destroy(&disp->xlnx_crtc.crtc);
2795}
2796
2797static void zynqmp_disp_map_crtc_to_plane(struct zynqmp_disp *disp)
2798{
2799 u32 possible_crtcs = drm_crtc_mask(&disp->xlnx_crtc.crtc);
2800 unsigned int i;
2801
2802 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2803 disp->layers[i].plane.possible_crtcs = possible_crtcs;
2804}
2805
2806
2807
2808
2809
2810static inline struct zynqmp_disp_layer
2811*bridge_to_layer(struct xlnx_bridge *bridge)
2812{
2813 return container_of(bridge, struct zynqmp_disp_layer, bridge);
2814}
2815
2816static int zynqmp_disp_bridge_enable(struct xlnx_bridge *bridge)
2817{
2818 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2819 struct zynqmp_disp *disp = layer->disp;
2820 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2821 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2822 struct videomode vm;
2823 int ret;
2824
2825 if (!disp->_pl_pclk) {
2826 dev_err(disp->dev, "PL clock is required for live\n");
2827 return -ENODEV;
2828 }
2829
2830 ret = zynqmp_disp_layer_check_size(disp, layer, layer->w, layer->h);
2831 if (ret)
2832 return ret;
2833
2834
2835 if (disp->dpsub->external_crtc_attached)
2836 zynqmp_disp_crtc_atomic_enable(crtc, NULL);
2837
2838 if (disp->vtc_bridge) {
2839 drm_display_mode_to_videomode(adjusted_mode, &vm);
2840 xlnx_bridge_set_timing(disp->vtc_bridge, &vm);
2841 xlnx_bridge_enable(disp->vtc_bridge);
2842 }
2843
2844
2845 if (disp->dpsub->external_crtc_attached && layer->id == ZYNQMP_DISP_LAYER_VID)
2846 disp->alpha = 0;
2847
2848 zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2849 zynqmp_disp_set_alpha(disp, disp->alpha);
2850 ret = zynqmp_disp_layer_enable(layer->disp, layer,
2851 ZYNQMP_DISP_LAYER_LIVE);
2852 if (ret)
2853 return ret;
2854
2855 if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2856 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2857 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2858 }
2859
2860 if (zynqmp_disp_av_buf_vid_timing_src_is_int(&disp->av_buf) ||
2861 zynqmp_disp_av_buf_vid_clock_src_is_ps(&disp->av_buf)) {
2862 dev_info(disp->dev,
2863 "Disabling the pipeline to change the clk/timing src");
2864 zynqmp_disp_disable(disp, true);
2865 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, false);
2866 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, false);
2867 }
2868
2869 zynqmp_disp_enable(disp);
2870
2871 return 0;
2872}
2873
2874static void zynqmp_disp_bridge_disable(struct xlnx_bridge *bridge)
2875{
2876 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2877 struct zynqmp_disp *disp = layer->disp;
2878
2879 zynqmp_disp_disable(disp, false);
2880
2881 zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_LIVE);
2882 if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2883 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2884
2885 if (!zynqmp_disp_layer_is_live(disp)) {
2886 dev_info(disp->dev,
2887 "Disabling the pipeline to change the clk/timing src");
2888 zynqmp_disp_disable(disp, true);
2889 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, true);
2890 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, true);
2891 if (zynqmp_disp_layer_is_enabled(disp))
2892 zynqmp_disp_enable(disp);
2893 }
2894}
2895
2896static int zynqmp_disp_bridge_set_input(struct xlnx_bridge *bridge,
2897 u32 width, u32 height, u32 bus_fmt)
2898{
2899 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2900 int ret;
2901
2902 ret = zynqmp_disp_layer_check_size(layer->disp, layer, width, height);
2903 if (ret)
2904 return ret;
2905
2906 ret = zynqmp_disp_layer_set_live_fmt(layer->disp, layer, bus_fmt);
2907 if (ret)
2908 dev_err(layer->disp->dev, "failed to set live fmt\n");
2909
2910 return ret;
2911}
2912
2913static int zynqmp_disp_bridge_get_input_fmts(struct xlnx_bridge *bridge,
2914 const u32 **fmts, u32 *count)
2915{
2916 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2917
2918 *fmts = layer->bus_fmts;
2919 *count = layer->num_bus_fmts;
2920
2921 return 0;
2922}
2923
2924static int zynqmp_disp_bridge_set_timing(struct xlnx_bridge *bridge,
2925 struct videomode *vm)
2926{
2927 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2928 struct zynqmp_disp *disp = layer->disp;
2929 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2930 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2931
2932 drm_display_mode_from_videomode(vm, adjusted_mode);
2933
2934 return 0;
2935}
2936
2937
2938
2939
2940
2941int zynqmp_disp_bind(struct device *dev, struct device *master, void *data)
2942{
2943 struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
2944 struct zynqmp_disp *disp = dpsub->disp;
2945 struct drm_device *drm = data;
2946 int num;
2947 u64 max;
2948 int ret;
2949
2950 disp->drm = drm;
2951
2952 max = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
2953 disp->g_alpha_prop = drm_property_create_range(drm, 0, "alpha", 0, max);
2954 disp->g_alpha_en_prop = drm_property_create_bool(drm, 0,
2955 "g_alpha_en");
2956 num = ARRAY_SIZE(zynqmp_disp_color_enum);
2957 disp->color_prop = drm_property_create_enum(drm, 0,
2958 "output_color",
2959 zynqmp_disp_color_enum,
2960 num);
2961 max = ZYNQMP_DISP_V_BLEND_BG_MAX;
2962 disp->bg_c0_prop = drm_property_create_range(drm, 0, "bg_c0", 0, max);
2963 disp->bg_c1_prop = drm_property_create_range(drm, 0, "bg_c1", 0, max);
2964 disp->bg_c2_prop = drm_property_create_range(drm, 0, "bg_c2", 0, max);
2965 disp->tpg_prop = drm_property_create_bool(drm, 0, "tpg");
2966
2967 ret = zynqmp_disp_create_plane(disp);
2968 if (ret)
2969 return ret;
2970 ret = zynqmp_disp_create_crtc(disp);
2971 if (ret)
2972 return ret;
2973 zynqmp_disp_map_crtc_to_plane(disp);
2974
2975 return 0;
2976}
2977
2978void zynqmp_disp_unbind(struct device *dev, struct device *master, void *data)
2979{
2980 struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
2981 struct zynqmp_disp *disp = dpsub->disp;
2982
2983 zynqmp_disp_destroy_crtc(disp);
2984 zynqmp_disp_destroy_plane(disp);
2985 drm_property_destroy(disp->drm, disp->bg_c2_prop);
2986 drm_property_destroy(disp->drm, disp->bg_c1_prop);
2987 drm_property_destroy(disp->drm, disp->bg_c0_prop);
2988 drm_property_destroy(disp->drm, disp->color_prop);
2989 drm_property_destroy(disp->drm, disp->g_alpha_en_prop);
2990 drm_property_destroy(disp->drm, disp->g_alpha_prop);
2991}
2992
2993
2994
2995
2996
2997static int zynqmp_disp_enumerate_fmts(struct zynqmp_disp *disp)
2998{
2999 struct zynqmp_disp_layer *layer;
3000 u32 *bus_fmts;
3001 u32 i, size, num_bus_fmts;
3002 u32 gfx_fmt = ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565;
3003
3004 num_bus_fmts = ARRAY_SIZE(av_buf_live_fmts);
3005 bus_fmts = devm_kzalloc(disp->dev, sizeof(*bus_fmts) * num_bus_fmts,
3006 GFP_KERNEL);
3007 if (!bus_fmts)
3008 return -ENOMEM;
3009 for (i = 0; i < num_bus_fmts; i++)
3010 bus_fmts[i] = av_buf_live_fmts[i].bus_fmt;
3011
3012 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
3013 layer->num_bus_fmts = num_bus_fmts;
3014 layer->bus_fmts = bus_fmts;
3015 size = ARRAY_SIZE(av_buf_vid_fmts);
3016 layer->num_fmts = size;
3017 layer->drm_fmts = devm_kzalloc(disp->dev,
3018 sizeof(*layer->drm_fmts) * size,
3019 GFP_KERNEL);
3020 if (!layer->drm_fmts)
3021 return -ENOMEM;
3022 for (i = 0; i < layer->num_fmts; i++)
3023 layer->drm_fmts[i] = av_buf_vid_fmts[i].drm_fmt;
3024 layer->fmt = &av_buf_vid_fmts[ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV];
3025
3026 layer = &disp->layers[ZYNQMP_DISP_LAYER_GFX];
3027 layer->num_bus_fmts = num_bus_fmts;
3028 layer->bus_fmts = bus_fmts;
3029 size = ARRAY_SIZE(av_buf_gfx_fmts);
3030 layer->num_fmts = size;
3031 layer->drm_fmts = devm_kzalloc(disp->dev,
3032 sizeof(*layer->drm_fmts) * size,
3033 GFP_KERNEL);
3034 if (!layer->drm_fmts)
3035 return -ENOMEM;
3036
3037 for (i = 0; i < layer->num_fmts; i++)
3038 layer->drm_fmts[i] = av_buf_gfx_fmts[i].drm_fmt;
3039 if (zynqmp_disp_gfx_init_fmt < ARRAY_SIZE(zynqmp_disp_gfx_init_fmts))
3040 gfx_fmt = zynqmp_disp_gfx_init_fmts[zynqmp_disp_gfx_init_fmt];
3041 layer->fmt = &av_buf_gfx_fmts[gfx_fmt];
3042
3043 return 0;
3044}
3045
3046int zynqmp_disp_probe(struct platform_device *pdev)
3047{
3048 struct zynqmp_dpsub *dpsub;
3049 struct zynqmp_disp *disp;
3050 struct resource *res;
3051 void __iomem *regs;
3052 int ret;
3053 struct zynqmp_disp_layer *layer;
3054 unsigned int i, j;
3055 struct device_node *vtc_node;
3056
3057 disp = devm_kzalloc(&pdev->dev, sizeof(*disp), GFP_KERNEL);
3058 if (!disp)
3059 return -ENOMEM;
3060 disp->dev = &pdev->dev;
3061
3062 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
3063 disp->blend.base = devm_ioremap_resource(&pdev->dev, res);
3064 if (IS_ERR(disp->blend.base))
3065 return PTR_ERR(disp->blend.base);
3066
3067 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
3068 disp->av_buf.base = devm_ioremap_resource(&pdev->dev, res);
3069 if (IS_ERR(disp->av_buf.base))
3070 return PTR_ERR(disp->av_buf.base);
3071
3072 disp->aud.base = syscon_regmap_lookup_by_phandle(disp->dev->of_node,
3073 "xlnx,dpaud-reg");
3074 if (IS_ERR(disp->aud.base)) {
3075 dev_info(&pdev->dev, "could not find xlnx,dpaud-reg, trying direct register access. DisplayPort audio will not work\n");
3076
3077 regs = devm_platform_ioremap_resource_byname(pdev, "aud");
3078 if (IS_ERR(regs)) {
3079 dev_err(&pdev->dev, "get aud memory resource failed.\n");
3080 return PTR_ERR(regs);
3081 }
3082 disp->aud.base =
3083 devm_regmap_init_mmio(&pdev->dev, regs,
3084 &dpaud_regmap_config);
3085 if (IS_ERR(disp->aud.base)) {
3086 dev_err(&pdev->dev, "failed to init regmap\n");
3087 return PTR_ERR(disp->aud.base);
3088 }
3089 }
3090
3091 dpsub = platform_get_drvdata(pdev);
3092 dpsub->disp = disp;
3093 disp->dpsub = dpsub;
3094
3095 ret = zynqmp_disp_enumerate_fmts(disp);
3096 if (ret)
3097 return ret;
3098
3099
3100 disp->_pl_pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk");
3101 if (!IS_ERR(disp->_pl_pclk)) {
3102 disp->pclk = disp->_pl_pclk;
3103 ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3104 &disp->pclk_en);
3105 if (ret)
3106 disp->pclk = NULL;
3107 } else if (PTR_ERR(disp->_pl_pclk) == -EPROBE_DEFER) {
3108 return PTR_ERR(disp->_pl_pclk);
3109 }
3110
3111
3112 if (!disp->pclk) {
3113 disp->_ps_pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in");
3114 if (IS_ERR(disp->_ps_pclk)) {
3115 dev_err(disp->dev, "failed to init any video clock\n");
3116 return PTR_ERR(disp->_ps_pclk);
3117 }
3118 disp->pclk = disp->_ps_pclk;
3119 ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3120 &disp->pclk_en);
3121 if (ret) {
3122 dev_err(disp->dev, "failed to init any video clock\n");
3123 return ret;
3124 }
3125 }
3126
3127 disp->aclk = devm_clk_get(disp->dev, "dp_apb_clk");
3128 if (IS_ERR(disp->aclk))
3129 return PTR_ERR(disp->aclk);
3130 ret = zynqmp_disp_clk_enable(disp->aclk, &disp->aclk_en);
3131 if (ret) {
3132 dev_err(disp->dev, "failed to enable the APB clk\n");
3133 return ret;
3134 }
3135
3136
3137 disp->_pl_audclk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
3138 if (!IS_ERR(disp->_pl_audclk)) {
3139 disp->audclk = disp->_pl_audclk;
3140 ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3141 &disp->audclk_en);
3142 if (ret)
3143 disp->audclk = NULL;
3144 }
3145
3146
3147 if (!disp->audclk) {
3148 disp->_ps_audclk = devm_clk_get(disp->dev, "dp_aud_clk");
3149 if (!IS_ERR(disp->_ps_audclk)) {
3150 disp->audclk = disp->_ps_audclk;
3151 ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3152 &disp->audclk_en);
3153 if (ret)
3154 disp->audclk = NULL;
3155 }
3156
3157 if (!disp->audclk) {
3158 dev_err(disp->dev,
3159 "audio is disabled due to clock failure\n");
3160 }
3161 }
3162
3163
3164 vtc_node = of_parse_phandle(disp->dev->of_node, "xlnx,bridge", 0);
3165 if (vtc_node) {
3166 disp->vtc_bridge = of_xlnx_bridge_get(vtc_node);
3167 if (!disp->vtc_bridge) {
3168 dev_info(disp->dev, "Didn't get vtc bridge instance\n");
3169 return -EPROBE_DEFER;
3170 }
3171 } else {
3172 dev_info(disp->dev, "vtc bridge property not present\n");
3173 }
3174
3175 ret = zynqmp_disp_layer_create(disp);
3176 if (ret)
3177 goto error_aclk;
3178
3179 zynqmp_disp_init(disp);
3180
3181
3182
3183
3184
3185 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
3186 layer = &disp->layers[i];
3187 layer->bridge.enable = &zynqmp_disp_bridge_enable;
3188 layer->bridge.disable = &zynqmp_disp_bridge_disable;
3189 layer->bridge.set_input = &zynqmp_disp_bridge_set_input;
3190 layer->bridge.get_input_fmts =
3191 &zynqmp_disp_bridge_get_input_fmts;
3192 layer->bridge.set_timing = &zynqmp_disp_bridge_set_timing;
3193 layer->bridge.of_node = disp->dev->of_node;
3194 layer->bridge.extra_name = ((i == 0) ? ".vid" : ".gfx");
3195 ret = xlnx_bridge_register(&layer->bridge);
3196 if (ret) {
3197 dev_info(disp->dev, "Bridge registration failed\n");
3198 for (j = 0; j < i; j++)
3199 xlnx_bridge_unregister(&disp->layers[j].bridge);
3200 goto error_aclk;
3201 }
3202 }
3203
3204 return 0;
3205
3206error_aclk:
3207 zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3208 return ret;
3209}
3210
3211int zynqmp_disp_remove(struct platform_device *pdev)
3212{
3213 struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
3214 struct zynqmp_disp *disp = dpsub->disp;
3215
3216 zynqmp_disp_layer_destroy(disp);
3217 if (disp->audclk)
3218 zynqmp_disp_clk_disable(disp->audclk, &disp->audclk_en);
3219 if (disp->vtc_bridge)
3220 of_xlnx_bridge_put(disp->vtc_bridge);
3221 zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3222 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
3223 dpsub->disp = NULL;
3224
3225 return 0;
3226}
3227