1 // SPDX-License-Identifier: GPL-2.0
3 * ZynqMP Display Controller Driver
5 * Copyright (C) 2017 - 2018 Xilinx, Inc.
7 * Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include <drm/drm_atomic.h>
21 #include <drm/drm_atomic_helper.h>
22 #include <drm/drm_crtc.h>
23 #include <drm/drm_crtc_helper.h>
24 #include <drm/drm_fb_cma_helper.h>
25 #include <drm/drm_fourcc.h>
26 #include <drm/drm_plane_helper.h>
28 #include <linux/clk.h>
29 #include <linux/device.h>
30 #include <linux/dmaengine.h>
31 #include <linux/interrupt.h>
32 #include <linux/irqreturn.h>
33 #include <linux/list.h>
34 #include <linux/module.h>
35 #include <linux/mutex.h>
37 #include <linux/of_dma.h>
38 #include <linux/platform_device.h>
39 #include <linux/pm_runtime.h>
40 #include <linux/spinlock.h>
41 #include <linux/uaccess.h>
43 #include "xlnx_bridge.h"
44 #include "xlnx_crtc.h"
46 #include "zynqmp_disp.h"
47 #include "zynqmp_dp.h"
48 #include "zynqmp_dpsub.h"
54 * The display part of ZynqMP DP subsystem. Internally, the device
55 * is partitioned into 3 blocks: AV buffer manager, Blender, Audio.
56 * The driver creates the DRM crtc and plane objectes and maps the DRM
57 * interface into those 3 blocks. In high level, the driver is layered
58 * in the following way:
60 * zynqmp_disp_crtc & zynqmp_disp_plane
63 * |->zynqmp_disp_blend
64 * |->zynqmp_disp_av_buf
66 * The driver APIs are used externally by
67 * - zynqmp_dpsub: Top level ZynqMP DP subsystem driver
68 * - zynqmp_dp: ZynqMP DP driver
69 * - xlnx_crtc: Xilinx DRM specific crtc functions
72 /* The default value is ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565 */
73 static uint zynqmp_disp_gfx_init_fmt;
74 module_param_named(gfx_init_fmt, zynqmp_disp_gfx_init_fmt, uint, 0444);
75 MODULE_PARM_DESC(gfx_init_fmt, "The initial format of the graphics layer\n"
76 "\t\t0 = rgb565 (default)\n"
78 "\t\t2 = argb8888\n");
79 /* These value should be mapped to index of av_buf_gfx_fmts[] */
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
83 static 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,
89 /* Blender registers */
90 #define ZYNQMP_DISP_V_BLEND_BG_CLR_0 0x0
91 #define ZYNQMP_DISP_V_BLEND_BG_CLR_1 0x4
92 #define ZYNQMP_DISP_V_BLEND_BG_CLR_2 0x8
93 #define ZYNQMP_DISP_V_BLEND_BG_MAX 0xfff
94 #define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA 0xc
95 #define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK 0x1fe
96 #define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX 0xff
97 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT 0x14
98 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB 0x0
99 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444 0x1
100 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422 0x2
101 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY 0x3
102 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_XVYCC 0x4
103 #define ZYNQMP_DISP_V_BLEND_OUTPUT_EN_DOWNSAMPLE BIT(4)
104 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL 0x18
105 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US BIT(0)
106 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB BIT(1)
107 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_BYPASS BIT(8)
108 #define ZYNQMP_DISP_V_BLEND_NUM_COEFF 9
109 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0 0x20
110 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF1 0x24
111 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF2 0x28
112 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF3 0x2c
113 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF4 0x30
114 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF5 0x34
115 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF6 0x38
116 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF7 0x3c
117 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF8 0x40
118 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0 0x44
119 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF1 0x48
120 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF2 0x4c
121 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF3 0x50
122 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF4 0x54
123 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF5 0x58
124 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF6 0x5c
125 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF7 0x60
126 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF8 0x64
127 #define ZYNQMP_DISP_V_BLEND_NUM_OFFSET 3
128 #define ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET 0x68
129 #define ZYNQMP_DISP_V_BLEND_CR_IN1CSC_OFFSET 0x6c
130 #define ZYNQMP_DISP_V_BLEND_CB_IN1CSC_OFFSET 0x70
131 #define ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET 0x74
132 #define ZYNQMP_DISP_V_BLEND_CR_OUTCSC_OFFSET 0x78
133 #define ZYNQMP_DISP_V_BLEND_CB_OUTCSC_OFFSET 0x7c
134 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0 0x80
135 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF1 0x84
136 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF2 0x88
137 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF3 0x8c
138 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF4 0x90
139 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF5 0x94
140 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF6 0x98
141 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF7 0x9c
142 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF8 0xa0
143 #define ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET 0xa4
144 #define ZYNQMP_DISP_V_BLEND_CR_IN2CSC_OFFSET 0xa8
145 #define ZYNQMP_DISP_V_BLEND_CB_IN2CSC_OFFSET 0xac
146 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_ENABLE 0x1d0
147 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP1 0x1d4
148 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP2 0x1d8
149 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP3 0x1dc
151 /* AV buffer manager registers */
152 #define ZYNQMP_DISP_AV_BUF_FMT 0x0
153 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_SHIFT 0
154 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK (0x1f << 0)
155 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_UYVY (0 << 0)
156 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY (1 << 0)
157 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YVYU (2 << 0)
158 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV (3 << 0)
159 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16 (4 << 0)
160 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24 (5 << 0)
161 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI (6 << 0)
162 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO (7 << 0)
163 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2 (8 << 0)
164 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444 (9 << 0)
165 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888 (10 << 0)
166 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880 (11 << 0)
167 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10 (12 << 0)
168 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444_10 (13 << 0)
169 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_10 (14 << 0)
170 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10 (15 << 0)
171 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_10 (16 << 0)
172 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24_10 (17 << 0)
173 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10 (18 << 0)
174 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420 (19 << 0)
175 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420 (20 << 0)
176 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420 (21 << 0)
177 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420_10 (22 << 0)
178 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10 (23 << 0)
179 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420_10 (24 << 0)
180 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_SHIFT 8
181 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK (0xf << 8)
182 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888 (0 << 8)
183 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888 (1 << 8)
184 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888 (2 << 8)
185 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888 (3 << 8)
186 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551 (4 << 8)
187 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444 (5 << 8)
188 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565 (6 << 8)
189 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_8BPP (7 << 8)
190 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_4BPP (8 << 8)
191 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_2BPP (9 << 8)
192 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_1BPP (10 << 8)
193 #define ZYNQMP_DISP_AV_BUF_NON_LIVE_LATENCY 0x8
194 #define ZYNQMP_DISP_AV_BUF_CHBUF 0x10
195 #define ZYNQMP_DISP_AV_BUF_CHBUF_EN BIT(0)
196 #define ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH BIT(1)
197 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT 2
198 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MASK (0xf << 2)
199 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX 0xf
200 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX 0x3
201 #define ZYNQMP_DISP_AV_BUF_STATUS 0x28
202 #define ZYNQMP_DISP_AV_BUF_STC_CTRL 0x2c
203 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EN BIT(0)
204 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_SHIFT 1
205 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VSYNC 0
206 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VID 1
207 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_AUD 2
208 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_INT_VSYNC 3
209 #define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE0 0x30
210 #define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE1 0x34
211 #define ZYNQMP_DISP_AV_BUF_STC_ADJ 0x38
212 #define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS0 0x3c
213 #define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS1 0x40
214 #define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS0 0x44
215 #define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS1 0x48
216 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS0 0x4c
217 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS1 0x50
218 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS0 0x54
219 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS1 0x58
220 #define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT0 0x60
221 #define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT1 0x64
222 #define ZYNQMP_DISP_AV_BUF_OUTPUT 0x70
223 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_SHIFT 0
224 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK (0x3 << 0)
225 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE (0 << 0)
226 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM (1 << 0)
227 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN (2 << 0)
228 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE (3 << 0)
229 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_SHIFT 2
230 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK (0x3 << 2)
231 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE (0 << 2)
232 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM (1 << 2)
233 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE (2 << 2)
234 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_NONE (3 << 2)
235 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_SHIFT 4
236 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK (0x3 << 4)
237 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PL (0 << 4)
238 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM (1 << 4)
239 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PATTERN (2 << 4)
240 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE (3 << 4)
241 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN BIT(6)
242 #define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT0 0x74
243 #define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT1 0x78
244 #define ZYNQMP_DISP_AV_BUF_PATTERN_GEN_SELECT 0x100
245 #define ZYNQMP_DISP_AV_BUF_CLK_SRC 0x120
246 #define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS BIT(0)
247 #define ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS BIT(1)
248 #define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING BIT(2)
249 #define ZYNQMP_DISP_AV_BUF_SRST_REG 0x124
250 #define ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST BIT(1)
251 #define ZYNQMP_DISP_AV_BUF_AUDIO_CH_CONFIG 0x12c
252 #define ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF 0x200
253 #define ZYNQMP_DISP_AV_BUF_GFX_COMP1_SF 0x204
254 #define ZYNQMP_DISP_AV_BUF_GFX_COMP2_SF 0x208
255 #define ZYNQMP_DISP_AV_BUF_VID_COMP0_SF 0x20c
256 #define ZYNQMP_DISP_AV_BUF_VID_COMP1_SF 0x210
257 #define ZYNQMP_DISP_AV_BUF_VID_COMP2_SF 0x214
258 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF 0x218
259 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP1_SF 0x21c
260 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP2_SF 0x220
261 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG 0x224
262 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF 0x228
263 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP1_SF 0x22c
264 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP2_SF 0x230
265 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG 0x234
266 #define ZYNQMP_DISP_AV_BUF_4BIT_SF 0x11111
267 #define ZYNQMP_DISP_AV_BUF_5BIT_SF 0x10842
268 #define ZYNQMP_DISP_AV_BUF_6BIT_SF 0x10410
269 #define ZYNQMP_DISP_AV_BUF_8BIT_SF 0x10101
270 #define ZYNQMP_DISP_AV_BUF_10BIT_SF 0x10040
271 #define ZYNQMP_DISP_AV_BUF_NULL_SF 0
272 #define ZYNQMP_DISP_AV_BUF_NUM_SF 3
273 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 0x0
274 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 0x1
275 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 0x2
276 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12 0x3
277 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASK GENMASK(2, 0)
278 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB 0x0
279 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444 0x1
280 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422 0x2
281 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY 0x3
282 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASK GENMASK(5, 4)
283 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_CB_FIRST BIT(8)
284 #define ZYNQMP_DISP_AV_BUF_PALETTE_MEMORY 0x400
286 /* Audio registers */
287 #define ZYNQMP_DISP_AUD_MIXER_VOLUME 0x0
288 #define ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE 0x20002000
289 #define ZYNQMP_DISP_AUD_MIXER_META_DATA 0x4
290 #define ZYNQMP_DISP_AUD_CH_STATUS0 0x8
291 #define ZYNQMP_DISP_AUD_CH_STATUS1 0xc
292 #define ZYNQMP_DISP_AUD_CH_STATUS2 0x10
293 #define ZYNQMP_DISP_AUD_CH_STATUS3 0x14
294 #define ZYNQMP_DISP_AUD_CH_STATUS4 0x18
295 #define ZYNQMP_DISP_AUD_CH_STATUS5 0x1c
296 #define ZYNQMP_DISP_AUD_CH_A_DATA0 0x20
297 #define ZYNQMP_DISP_AUD_CH_A_DATA1 0x24
298 #define ZYNQMP_DISP_AUD_CH_A_DATA2 0x28
299 #define ZYNQMP_DISP_AUD_CH_A_DATA3 0x2c
300 #define ZYNQMP_DISP_AUD_CH_A_DATA4 0x30
301 #define ZYNQMP_DISP_AUD_CH_A_DATA5 0x34
302 #define ZYNQMP_DISP_AUD_CH_B_DATA0 0x38
303 #define ZYNQMP_DISP_AUD_CH_B_DATA1 0x3c
304 #define ZYNQMP_DISP_AUD_CH_B_DATA2 0x40
305 #define ZYNQMP_DISP_AUD_CH_B_DATA3 0x44
306 #define ZYNQMP_DISP_AUD_CH_B_DATA4 0x48
307 #define ZYNQMP_DISP_AUD_CH_B_DATA5 0x4c
308 #define ZYNQMP_DISP_AUD_SOFT_RESET 0xc00
309 #define ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST BIT(0)
311 #define ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS 4
312 #define ZYNQMP_DISP_AV_BUF_NUM_BUFFERS 6
314 #define ZYNQMP_DISP_NUM_LAYERS 2
315 #define ZYNQMP_DISP_MAX_NUM_SUB_PLANES 3
317 * 3840x2160 is advertised max resolution, but almost any resolutions under
318 * 300Mhz pixel rate would work. Thus put 4096 as maximum width and height.
320 #define ZYNQMP_DISP_MAX_WIDTH 4096
321 #define ZYNQMP_DISP_MAX_HEIGHT 4096
322 /* 44 bit addressing. This is acutally DPDMA limitation */
323 #define ZYNQMP_DISP_MAX_DMA_BIT 44
326 * enum zynqmp_disp_layer_type - Layer type (can be used for hw ID)
327 * @ZYNQMP_DISP_LAYER_VID: Video layer
328 * @ZYNQMP_DISP_LAYER_GFX: Graphics layer
330 enum zynqmp_disp_layer_type {
331 ZYNQMP_DISP_LAYER_VID,
332 ZYNQMP_DISP_LAYER_GFX
336 * enum zynqmp_disp_layer_mode - Layer mode
337 * @ZYNQMP_DISP_LAYER_NONLIVE: non-live (memory) mode
338 * @ZYNQMP_DISP_LAYER_LIVE: live (stream) mode
340 enum zynqmp_disp_layer_mode {
341 ZYNQMP_DISP_LAYER_NONLIVE,
342 ZYNQMP_DISP_LAYER_LIVE
346 * struct zynqmp_disp_layer_dma - struct for DMA engine
348 * @is_active: flag if the DMA is active
349 * @xt: Interleaved desc config container
350 * @sgl: Data chunk for dma_interleaved_template
352 struct zynqmp_disp_layer_dma {
353 struct dma_chan *chan;
355 struct dma_interleaved_template xt;
356 struct data_chunk sgl[1];
360 * struct zynqmp_disp_layer - Display subsystem layer
362 * @bridge: Xlnx bridge
363 * @of_node: device node
364 * @dma: struct for DMA engine
365 * @num_chan: Number of DMA channel
367 * @offset: Layer offset in the register space
368 * @enabled: flag if enabled
369 * @fmt: Current format descriptor
370 * @drm_fmts: Array of supported DRM formats
371 * @num_fmts: Number of supported DRM formats
372 * @bus_fmts: Array of supported bus formats
373 * @num_bus_fmts: Number of supported bus formats
376 * @mode: the operation mode
377 * @other: other layer
378 * @disp: back pointer to struct zynqmp_disp
380 struct zynqmp_disp_layer {
381 struct drm_plane plane;
382 struct xlnx_bridge bridge;
383 struct device_node *of_node;
384 struct zynqmp_disp_layer_dma dma[ZYNQMP_DISP_MAX_NUM_SUB_PLANES];
385 unsigned int num_chan;
386 enum zynqmp_disp_layer_type id;
389 const struct zynqmp_disp_fmt *fmt;
391 unsigned int num_fmts;
393 unsigned int num_bus_fmts;
396 enum zynqmp_disp_layer_mode mode;
397 struct zynqmp_disp_layer *other;
398 struct zynqmp_disp *disp;
402 * struct zynqmp_disp_blend - Blender
403 * @base: Base address offset
405 struct zynqmp_disp_blend {
410 * struct zynqmp_disp_av_buf - AV buffer manager
411 * @base: Base address offset
413 struct zynqmp_disp_av_buf {
418 * struct zynqmp_disp_aud - Audio
419 * @base: Base address offset
421 struct zynqmp_disp_aud {
426 * struct zynqmp_disp - Display subsystem
427 * @xlnx_crtc: Xilinx DRM crtc
428 * @dev: device structure
429 * @dpsub: Display subsystem
431 * @enabled: flag if enabled
432 * @blend: Blender block
433 * @av_buf: AV buffer manager block
436 * @g_alpha_prop: global alpha property
437 * @alpha: current global alpha value
438 * @g_alpha_en_prop: the global alpha enable property
439 * @alpha_en: flag if the global alpha is enabled
440 * @color_prop: output color format property
441 * @color: current output color value
442 * @bg_c0_prop: 1st component of background color property
443 * @bg_c0: current value of 1st background color component
444 * @bg_c1_prop: 2nd component of background color property
445 * @bg_c1: current value of 2nd background color component
446 * @bg_c2_prop: 3rd component of background color property
447 * @bg_c2: current value of 3rd background color component
448 * @tpg_prop: Test Pattern Generation mode property
449 * @tpg_on: current TPG mode state
450 * @event: pending vblank event request
451 * @_ps_pclk: Pixel clock from PS
452 * @_pl_pclk: Pixel clock from PL
454 * @pclk_en: Flag if the pixel clock is enabled
455 * @_ps_audclk: Audio clock from PS
456 * @_pl_audclk: Audio clock from PL
457 * @audclk: Audio clock
458 * @audclk_en: Flag if the audio clock is enabled
460 * @aclk_en: Flag if the APB clock is enabled
463 struct xlnx_crtc xlnx_crtc;
465 struct zynqmp_dpsub *dpsub;
466 struct drm_device *drm;
468 struct zynqmp_disp_blend blend;
469 struct zynqmp_disp_av_buf av_buf;
470 struct zynqmp_disp_aud aud;
471 struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
472 struct drm_property *g_alpha_prop;
474 struct drm_property *g_alpha_en_prop;
476 struct drm_property *color_prop;
478 struct drm_property *bg_c0_prop;
480 struct drm_property *bg_c1_prop;
482 struct drm_property *bg_c2_prop;
484 struct drm_property *tpg_prop;
486 struct drm_pending_vblank_event *event;
487 /* Don't operate directly on _ps_ */
488 struct clk *_ps_pclk;
489 struct clk *_pl_pclk;
492 struct clk *_ps_audclk;
493 struct clk *_pl_audclk;
501 * struct zynqmp_disp_fmt - Display subsystem format mapping
502 * @drm_fmt: drm format
503 * @disp_fmt: Display subsystem format
504 * @bus_fmt: Bus formats (live formats)
505 * @rgb: flag for RGB formats
506 * @swap: flag to swap r & b for rgb formats, and u & v for yuv formats
507 * @chroma_sub: flag for chroma subsampled formats
508 * @sf: scaling factors for upto 3 color components
510 struct zynqmp_disp_fmt {
520 static void zynqmp_disp_write(void __iomem *base, int offset, u32 val)
522 writel(val, base + offset);
525 static u32 zynqmp_disp_read(void __iomem *base, int offset)
527 return readl(base + offset);
530 static void zynqmp_disp_clr(void __iomem *base, int offset, u32 clr)
532 zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) & ~clr);
535 static void zynqmp_disp_set(void __iomem *base, int offset, u32 set)
537 zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) | set);
545 * zynqmp_disp_clk_enable - Enable the clock if needed
547 * @flag: flag if the clock is enabled
549 * Enable the clock only if it's not enabled @flag.
551 * Return: value from clk_prepare_enable().
553 static int zynqmp_disp_clk_enable(struct clk *clk, bool *flag)
558 ret = clk_prepare_enable(clk);
567 * zynqmp_disp_clk_enable - Enable the clock if needed
569 * @flag: flag if the clock is enabled
571 * Disable the clock only if it's enabled @flag.
573 static void zynqmp_disp_clk_disable(struct clk *clk, bool *flag)
576 clk_disable_unprepare(clk);
582 * zynqmp_disp_clk_enable - Enable and disable the clock
584 * @flag: flag if the clock is enabled
586 * This is to ensure the clock is disabled. The initial hardware state is
587 * unknown, and this makes sure that the clock is disabled.
589 * Return: value from clk_prepare_enable().
591 static int zynqmp_disp_clk_enable_disable(struct clk *clk, bool *flag)
596 ret = clk_prepare_enable(clk);
597 clk_disable_unprepare(clk);
608 * zynqmp_disp_blend_set_output_fmt - Set the output format of the blend
609 * @blend: blend object
610 * @fmt: output format
612 * Set the output format to @fmt.
615 zynqmp_disp_blend_set_output_fmt(struct zynqmp_disp_blend *blend, u32 fmt)
617 u16 reset_coeffs[] = { 0x1000, 0x0, 0x0,
620 u32 reset_offsets[] = { 0x0, 0x0, 0x0 };
621 u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
622 0x7d4d, 0x7ab3, 0x800,
623 0x800, 0x794d, 0x7eb3 };
624 u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
629 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt);
630 if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) {
631 coeffs = reset_coeffs;
632 offsets = reset_offsets;
634 /* Hardcode Full-range SDTV values. Can be runtime config */
635 coeffs = sdtv_coeffs;
636 offsets = full_range_offsets;
639 offset = ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0;
640 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
641 zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
643 offset = ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET;
644 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
645 zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
649 * zynqmp_disp_blend_layer_coeff - Set the coefficients for @layer
650 * @blend: blend object
651 * @layer: layer to set the coefficients for
652 * @on: if layer is on / off
654 * Depending on the format (rgb / yuv and swap), and the status (on / off),
655 * this function sets the coefficients for the given layer @layer accordingly.
657 static void zynqmp_disp_blend_layer_coeff(struct zynqmp_disp_blend *blend,
658 struct zynqmp_disp_layer *layer,
661 u32 offset, i, s0, s1;
662 u16 sdtv_coeffs[] = { 0x1000, 0x166f, 0x0,
663 0x1000, 0x7483, 0x7a7f,
664 0x1000, 0x0, 0x1c5a };
665 u16 sdtv_coeffs_yonly[] = { 0x0, 0x0, 0x1000,
668 u16 swap_coeffs[] = { 0x1000, 0x0, 0x0,
671 u16 null_coeffs[] = { 0x0, 0x0, 0x0,
675 u32 sdtv_offsets[] = { 0x0, 0x1800, 0x1800 };
676 u32 sdtv_offsets_yonly[] = { 0x1800, 0x1800, 0x0 };
677 u32 null_offsets[] = { 0x0, 0x0, 0x0 };
680 if (layer->id == ZYNQMP_DISP_LAYER_VID)
681 offset = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0;
683 offset = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0;
686 coeffs = null_coeffs;
687 offsets = null_offsets;
689 if (!layer->fmt->rgb) {
691 * In case of Y_ONLY formats, pixels are unpacked
692 * differently compared to YCbCr
694 if (layer->fmt->drm_fmt == DRM_FORMAT_Y8 ||
695 layer->fmt->drm_fmt == DRM_FORMAT_Y10) {
696 coeffs = sdtv_coeffs_yonly;
697 offsets = sdtv_offsets_yonly;
699 coeffs = sdtv_coeffs;
700 offsets = sdtv_offsets;
706 coeffs = swap_coeffs;
710 /* No offset for RGB formats */
711 offsets = null_offsets;
714 if (layer->fmt->swap) {
715 for (i = 0; i < 3; i++) {
716 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
717 coeffs[i * 3 + s1] ^= coeffs[i * 3 + s0];
718 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
723 /* Program coefficients. Can be runtime configurable */
724 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
725 zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
727 if (layer->id == ZYNQMP_DISP_LAYER_VID)
728 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET;
730 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET;
732 /* Program offsets. Can be runtime configurable */
733 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
734 zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
738 * zynqmp_disp_blend_layer_enable - Enable a layer
739 * @blend: blend object
740 * @layer: layer to enable
742 * Enable a layer @layer.
744 static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
745 struct zynqmp_disp_layer *layer)
749 reg = layer->fmt->rgb ? ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB : 0;
750 reg |= layer->fmt->chroma_sub ?
751 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0;
753 zynqmp_disp_write(blend->base,
754 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset,
757 zynqmp_disp_blend_layer_coeff(blend, layer, true);
761 * zynqmp_disp_blend_layer_disable - Disable a layer
762 * @blend: blend object
763 * @layer: layer to disable
765 * Disable a layer @layer.
767 static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
768 struct zynqmp_disp_layer *layer)
770 zynqmp_disp_write(blend->base,
771 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset, 0);
773 zynqmp_disp_blend_layer_coeff(blend, layer, false);
777 * zynqmp_disp_blend_set_bg_color - Set the background color
778 * @blend: blend object
779 * @c0: color component 0
780 * @c1: color component 1
781 * @c2: color component 2
783 * Set the background color.
785 static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp_blend *blend,
786 u32 c0, u32 c1, u32 c2)
788 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_0, c0);
789 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_1, c1);
790 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_2, c2);
794 * zynqmp_disp_blend_set_alpha - Set the alpha for blending
795 * @blend: blend object
796 * @alpha: alpha value to be used
798 * Set the alpha for blending.
801 zynqmp_disp_blend_set_alpha(struct zynqmp_disp_blend *blend, u32 alpha)
805 reg = zynqmp_disp_read(blend->base,
806 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA);
807 reg &= ~ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK;
809 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
814 * zynqmp_disp_blend_enable_alpha - Enable/disable the global alpha
815 * @blend: blend object
816 * @enable: flag to enable or disable alpha blending
818 * Enable/disable the global alpha blending based on @enable.
821 zynqmp_disp_blend_enable_alpha(struct zynqmp_disp_blend *blend, bool enable)
824 zynqmp_disp_set(blend->base,
825 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
827 zynqmp_disp_clr(blend->base,
828 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
831 /* List of blend output formats */
832 /* The id / order should be aligned with zynqmp_disp_color_enum */
833 static const struct zynqmp_disp_fmt blend_output_fmts[] = {
835 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB,
837 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444,
839 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422,
841 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY,
846 * AV buffer manager functions
849 /* List of video layer formats */
850 #define ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV 2
851 static const struct zynqmp_disp_fmt av_buf_vid_fmts[] = {
853 .drm_fmt = DRM_FORMAT_VYUY,
854 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
858 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
859 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
860 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
862 .drm_fmt = DRM_FORMAT_UYVY,
863 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
867 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
868 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
869 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
871 .drm_fmt = DRM_FORMAT_YUYV,
872 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
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,
880 .drm_fmt = DRM_FORMAT_YVYU,
881 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
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,
889 .drm_fmt = DRM_FORMAT_YUV422,
890 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
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,
898 .drm_fmt = DRM_FORMAT_YVU422,
899 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
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,
907 .drm_fmt = DRM_FORMAT_YUV444,
908 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
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,
916 .drm_fmt = DRM_FORMAT_YVU444,
917 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
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,
925 .drm_fmt = DRM_FORMAT_NV16,
926 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
930 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
931 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
932 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
934 .drm_fmt = DRM_FORMAT_NV61,
935 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
939 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
940 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
941 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
943 .drm_fmt = DRM_FORMAT_Y8,
944 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO,
948 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
949 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
950 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
952 .drm_fmt = DRM_FORMAT_Y10,
953 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10,
957 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
958 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
959 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
961 .drm_fmt = DRM_FORMAT_BGR888,
962 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
966 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
967 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
968 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
970 .drm_fmt = DRM_FORMAT_RGB888,
971 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
975 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
976 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
977 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
979 .drm_fmt = DRM_FORMAT_XBGR8888,
980 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
984 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
985 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
986 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
988 .drm_fmt = DRM_FORMAT_XRGB8888,
989 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
993 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
994 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
995 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
997 .drm_fmt = DRM_FORMAT_XBGR2101010,
998 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
1001 .chroma_sub = false,
1002 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1003 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1004 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1006 .drm_fmt = DRM_FORMAT_XRGB2101010,
1007 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
1010 .chroma_sub = false,
1011 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1012 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1013 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1015 .drm_fmt = DRM_FORMAT_YUV420,
1016 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
1020 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1021 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1022 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1024 .drm_fmt = DRM_FORMAT_YVU420,
1025 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
1029 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1030 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1031 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1033 .drm_fmt = DRM_FORMAT_NV12,
1034 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
1038 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1039 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1040 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1042 .drm_fmt = DRM_FORMAT_NV21,
1043 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
1047 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1048 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1049 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1051 .drm_fmt = DRM_FORMAT_XV15,
1052 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10,
1056 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1057 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1058 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1060 .drm_fmt = DRM_FORMAT_XV20,
1061 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10,
1065 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1066 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1067 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1071 /* List of graphics layer formats */
1072 static const struct zynqmp_disp_fmt av_buf_gfx_fmts[] = {
1074 .drm_fmt = DRM_FORMAT_ABGR8888,
1075 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
1078 .chroma_sub = false,
1079 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1080 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1081 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1083 .drm_fmt = DRM_FORMAT_ARGB8888,
1084 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
1087 .chroma_sub = false,
1088 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1089 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1090 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1092 .drm_fmt = DRM_FORMAT_RGBA8888,
1093 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
1096 .chroma_sub = false,
1097 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1098 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1099 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1101 .drm_fmt = DRM_FORMAT_BGRA8888,
1102 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
1105 .chroma_sub = false,
1106 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1107 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1108 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1110 .drm_fmt = DRM_FORMAT_BGR888,
1111 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888,
1114 .chroma_sub = false,
1115 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1116 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1117 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1119 .drm_fmt = DRM_FORMAT_RGB888,
1120 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888,
1123 .chroma_sub = false,
1124 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1125 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1126 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1128 .drm_fmt = DRM_FORMAT_RGBA5551,
1129 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
1132 .chroma_sub = false,
1133 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1134 .sf[1] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1135 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1137 .drm_fmt = DRM_FORMAT_BGRA5551,
1138 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
1141 .chroma_sub = false,
1142 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1143 .sf[1] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1144 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1146 .drm_fmt = DRM_FORMAT_RGBA4444,
1147 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
1150 .chroma_sub = false,
1151 .sf[0] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1152 .sf[1] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1153 .sf[2] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1155 .drm_fmt = DRM_FORMAT_BGRA4444,
1156 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
1159 .chroma_sub = false,
1160 .sf[0] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1161 .sf[1] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1162 .sf[2] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1164 .drm_fmt = DRM_FORMAT_RGB565,
1165 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
1168 .chroma_sub = false,
1169 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1170 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1171 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1173 .drm_fmt = DRM_FORMAT_BGR565,
1174 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
1177 .chroma_sub = false,
1178 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1179 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1180 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1184 /* List of live formats */
1185 /* Format can be combination of color, bpc, and cb-cr order.
1186 * - Color: RGB / YUV444 / YUV422 / Y only
1187 * - BPC: 6, 8, 10, 12
1188 * - Swap: Cb and Cr swap
1189 * which can be 32 bus formats. Only list the subset of those for now.
1191 static const struct zynqmp_disp_fmt av_buf_live_fmts[] = {
1193 .bus_fmt = MEDIA_BUS_FMT_RGB666_1X18,
1194 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 ||
1195 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
1198 .chroma_sub = false,
1199 .sf[0] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1200 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1201 .sf[2] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1203 .bus_fmt = MEDIA_BUS_FMT_RBG888_1X24,
1204 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1205 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
1208 .chroma_sub = false,
1209 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1210 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1211 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1213 .bus_fmt = MEDIA_BUS_FMT_UYVY8_1X16,
1214 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1215 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1219 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1220 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1221 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1223 .bus_fmt = MEDIA_BUS_FMT_VUY8_1X24,
1224 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1225 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444,
1228 .chroma_sub = false,
1229 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1230 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1231 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1233 .bus_fmt = MEDIA_BUS_FMT_UYVY10_1X20,
1234 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 ||
1235 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1239 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1240 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1241 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1246 * zynqmp_disp_av_buf_set_fmt - Set the input formats
1247 * @av_buf: av buffer manager
1250 * Set the av buffer manager format to @fmt. @fmt should have valid values
1251 * for both video and graphics layer.
1254 zynqmp_disp_av_buf_set_fmt(struct zynqmp_disp_av_buf *av_buf, u32 fmt)
1256 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT, fmt);
1260 * zynqmp_disp_av_buf_get_fmt - Get the input formats
1261 * @av_buf: av buffer manager
1263 * Get the input formats (which include video and graphics) of
1264 * av buffer manager.
1266 * Return: value of ZYNQMP_DISP_AV_BUF_FMT register.
1269 zynqmp_disp_av_buf_get_fmt(struct zynqmp_disp_av_buf *av_buf)
1271 return zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT);
1275 * zynqmp_disp_av_buf_set_live_fmt - Set the live_input format
1276 * @av_buf: av buffer manager
1278 * @is_vid: if it's for video layer
1280 * Set the live input format to @fmt. @fmt should have valid values.
1281 * @vid will determine if it's for video layer or graphics layer
1282 * @fmt should be a valid hardware value.
1284 static void zynqmp_disp_av_buf_set_live_fmt(struct zynqmp_disp_av_buf *av_buf,
1285 u32 fmt, bool is_vid)
1290 offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG;
1292 offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
1294 zynqmp_disp_write(av_buf->base, offset, fmt);
1298 * zynqmp_disp_av_buf_set_vid_clock_src - Set the video clock source
1299 * @av_buf: av buffer manager
1300 * @from_ps: flag if the video clock is from ps
1302 * Set the video clock source based on @from_ps. It can come from either PS or
1306 zynqmp_disp_av_buf_set_vid_clock_src(struct zynqmp_disp_av_buf *av_buf,
1309 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1312 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1314 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1315 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1319 * zynqmp_disp_av_buf_vid_clock_src_is_ps - if ps clock is used
1320 * @av_buf: av buffer manager
1322 * Return: if ps clock is used
1325 zynqmp_disp_av_buf_vid_clock_src_is_ps(struct zynqmp_disp_av_buf *av_buf)
1327 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1329 return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS);
1333 * zynqmp_disp_av_buf_set_vid_timing_src - Set the video timing source
1334 * @av_buf: av buffer manager
1335 * @internal: flag if the video timing is generated internally
1337 * Set the video timing source based on @internal. It can come externally or
1338 * be generated internally.
1341 zynqmp_disp_av_buf_set_vid_timing_src(struct zynqmp_disp_av_buf *av_buf,
1344 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1347 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1349 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1350 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1354 * zynqmp_disp_av_buf_vid_timing_src_is_int - if internal timing is used
1355 * @av_buf: av buffer manager
1357 * Return: if the internal timing is used
1360 zynqmp_disp_av_buf_vid_timing_src_is_int(struct zynqmp_disp_av_buf *av_buf)
1362 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1364 return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING);
1368 * zynqmp_disp_av_buf_set_aud_clock_src - Set the audio clock source
1369 * @av_buf: av buffer manager
1370 * @from_ps: flag if the video clock is from ps
1372 * Set the audio clock source based on @from_ps. It can come from either PS or
1376 zynqmp_disp_av_buf_set_aud_clock_src(struct zynqmp_disp_av_buf *av_buf,
1379 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1382 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1384 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1385 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1389 * zynqmp_disp_av_buf_enable_buf - Enable buffers
1390 * @av_buf: av buffer manager
1392 * Enable all (video and audio) buffers.
1395 zynqmp_disp_av_buf_enable_buf(struct zynqmp_disp_av_buf *av_buf)
1399 reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1400 reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX <<
1401 ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1403 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
1404 zynqmp_disp_write(av_buf->base,
1405 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1407 reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1408 reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX <<
1409 ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1411 for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1412 zynqmp_disp_write(av_buf->base,
1413 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1417 * zynqmp_disp_av_buf_disable_buf - Disable buffers
1418 * @av_buf: av buffer manager
1420 * Disable all (video and audio) buffers.
1423 zynqmp_disp_av_buf_disable_buf(struct zynqmp_disp_av_buf *av_buf)
1427 reg = ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH & ~ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1428 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1429 zynqmp_disp_write(av_buf->base,
1430 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1434 * zynqmp_disp_av_buf_enable_aud - Enable audio
1435 * @av_buf: av buffer manager
1437 * Enable all audio buffers.
1440 zynqmp_disp_av_buf_enable_aud(struct zynqmp_disp_av_buf *av_buf)
1444 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1445 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1446 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM;
1447 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1448 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1452 * zynqmp_disp_av_buf_enable - Enable the video pipe
1453 * @av_buf: av buffer manager
1455 * De-assert the video pipe reset
1458 zynqmp_disp_av_buf_enable(struct zynqmp_disp_av_buf *av_buf)
1460 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG, 0);
1464 * zynqmp_disp_av_buf_disable - Disable the video pipe
1465 * @av_buf: av buffer manager
1467 * Assert the video pipe reset
1470 zynqmp_disp_av_buf_disable(struct zynqmp_disp_av_buf *av_buf)
1472 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG,
1473 ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST);
1477 * zynqmp_disp_av_buf_disable_aud - Disable audio
1478 * @av_buf: av buffer manager
1480 * Disable all audio buffers.
1483 zynqmp_disp_av_buf_disable_aud(struct zynqmp_disp_av_buf *av_buf)
1487 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1488 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1489 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE;
1490 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1491 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1495 * zynqmp_disp_av_buf_set_tpg - Set TPG mode
1496 * @av_buf: av buffer manager
1497 * @tpg_on: if TPG should be on
1499 * Set the TPG mode based on @tpg_on.
1501 static void zynqmp_disp_av_buf_set_tpg(struct zynqmp_disp_av_buf *av_buf,
1506 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1507 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1509 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1511 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1512 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1516 * zynqmp_disp_av_buf_enable_vid - Enable the video layer buffer
1517 * @av_buf: av buffer manager
1518 * @layer: layer to enable
1519 * @mode: operation mode of layer
1521 * Enable the video/graphics buffer for @layer.
1523 static void zynqmp_disp_av_buf_enable_vid(struct zynqmp_disp_av_buf *av_buf,
1524 struct zynqmp_disp_layer *layer,
1525 enum zynqmp_disp_layer_mode mode)
1529 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1530 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1531 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1532 if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1533 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
1535 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE;
1537 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1538 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1539 if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1540 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1542 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE;
1544 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1548 * zynqmp_disp_av_buf_disable_vid - Disable the video layer buffer
1549 * @av_buf: av buffer manager
1550 * @layer: layer to disable
1552 * Disable the video/graphics buffer for @layer.
1555 zynqmp_disp_av_buf_disable_vid(struct zynqmp_disp_av_buf *av_buf,
1556 struct zynqmp_disp_layer *layer)
1560 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1561 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1562 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1563 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE;
1565 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1566 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE;
1568 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1572 * zynqmp_disp_av_buf_init_sf - Initialize scaling factors
1573 * @av_buf: av buffer manager
1574 * @vid_fmt: video format descriptor
1575 * @gfx_fmt: graphics format descriptor
1577 * Initialize scaling factors for both video and graphics layers.
1578 * If the format descriptor is NULL, the function skips the programming.
1580 static void zynqmp_disp_av_buf_init_sf(struct zynqmp_disp_av_buf *av_buf,
1581 const struct zynqmp_disp_fmt *vid_fmt,
1582 const struct zynqmp_disp_fmt *gfx_fmt)
1588 offset = ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF;
1589 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1590 zynqmp_disp_write(av_buf->base, offset + i * 4,
1595 offset = ZYNQMP_DISP_AV_BUF_VID_COMP0_SF;
1596 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1597 zynqmp_disp_write(av_buf->base, offset + i * 4,
1603 * zynqmp_disp_av_buf_init_live_sf - Initialize scaling factors for live source
1604 * @av_buf: av buffer manager
1605 * @fmt: format descriptor
1606 * @is_vid: flag if this is for video layer
1608 * Initialize scaling factors for live source.
1610 static void zynqmp_disp_av_buf_init_live_sf(struct zynqmp_disp_av_buf *av_buf,
1611 const struct zynqmp_disp_fmt *fmt,
1618 offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF;
1620 offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF;
1622 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1623 zynqmp_disp_write(av_buf->base, offset + i * 4,
1632 * zynqmp_disp_aud_init - Initialize the audio
1635 * Initialize the audio with default mixer volume. The de-assertion will
1636 * initialize the audio states.
1638 static void zynqmp_disp_aud_init(struct zynqmp_disp_aud *aud)
1640 /* Clear the audio soft reset register as it's an non-reset flop */
1641 zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
1642 zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_MIXER_VOLUME,
1643 ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
1647 * zynqmp_disp_aud_deinit - De-initialize the audio
1650 * Put the audio in reset.
1652 static void zynqmp_disp_aud_deinit(struct zynqmp_disp_aud *aud)
1654 zynqmp_disp_set(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET,
1655 ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
1659 * ZynqMP Display layer functions
1663 * zynqmp_disp_layer_check_size - Verify width and height for the layer
1664 * @disp: Display subsystem
1669 * The Display subsystem has the limitation that both layers should have
1670 * identical size. This function stores width and height of @layer, and verifies
1671 * if the size (width and height) is valid.
1673 * Return: 0 on success, or -EINVAL if width or/and height is invalid.
1675 static int zynqmp_disp_layer_check_size(struct zynqmp_disp *disp,
1676 struct zynqmp_disp_layer *layer,
1677 u32 width, u32 height)
1679 struct zynqmp_disp_layer *other = layer->other;
1681 if (other->enabled && (other->w != width || other->h != height)) {
1682 dev_err(disp->dev, "Layer width:height must be %d:%d\n",
1683 other->w, other->h);
1694 * zynqmp_disp_map_fmt - Find the Display subsystem format for given drm format
1695 * @fmts: format table to look up
1696 * @size: size of the table @fmts
1697 * @drm_fmt: DRM format to search
1699 * Search a Display subsystem format corresponding to the given DRM format
1700 * @drm_fmt, and return the format descriptor which contains the Display
1701 * subsystem format value.
1703 * Return: a Display subsystem format descriptor on success, or NULL.
1705 static const struct zynqmp_disp_fmt *
1706 zynqmp_disp_map_fmt(const struct zynqmp_disp_fmt fmts[],
1707 unsigned int size, uint32_t drm_fmt)
1711 for (i = 0; i < size; i++)
1712 if (fmts[i].drm_fmt == drm_fmt)
1719 * zynqmp_disp_set_fmt - Set the format of the layer
1720 * @disp: Display subsystem
1721 * @layer: layer to set the format
1722 * @drm_fmt: DRM format to set
1724 * Set the format of the given layer to @drm_fmt.
1726 * Return: 0 on success. -EINVAL if @drm_fmt is not supported by the layer.
1728 static int zynqmp_disp_layer_set_fmt(struct zynqmp_disp *disp,
1729 struct zynqmp_disp_layer *layer,
1732 const struct zynqmp_disp_fmt *fmt;
1733 const struct zynqmp_disp_fmt *vid_fmt = NULL, *gfx_fmt = NULL;
1734 u32 size, fmts, mask;
1736 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1737 size = ARRAY_SIZE(av_buf_vid_fmts);
1738 mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK;
1739 fmt = zynqmp_disp_map_fmt(av_buf_vid_fmts, size, drm_fmt);
1742 size = ARRAY_SIZE(av_buf_gfx_fmts);
1743 mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
1744 fmt = zynqmp_disp_map_fmt(av_buf_gfx_fmts, size, drm_fmt);
1751 fmts = zynqmp_disp_av_buf_get_fmt(&disp->av_buf);
1753 fmts |= fmt->disp_fmt;
1754 zynqmp_disp_av_buf_set_fmt(&disp->av_buf, fmts);
1755 zynqmp_disp_av_buf_init_sf(&disp->av_buf, vid_fmt, gfx_fmt);
1762 * zynqmp_disp_map_live_fmt - Find the hardware format for given bus format
1763 * @fmts: format table to look up
1764 * @size: size of the table @fmts
1765 * @bus_fmt: bus format to search
1767 * Search a Display subsystem format corresponding to the given bus format
1768 * @bus_fmt, and return the format descriptor which contains the Display
1769 * subsystem format value.
1771 * Return: a Display subsystem format descriptor on success, or NULL.
1773 static const struct zynqmp_disp_fmt *
1774 zynqmp_disp_map_live_fmt(const struct zynqmp_disp_fmt fmts[],
1775 unsigned int size, uint32_t bus_fmt)
1779 for (i = 0; i < size; i++)
1780 if (fmts[i].bus_fmt == bus_fmt)
1787 * zynqmp_disp_set_live_fmt - Set the live format of the layer
1788 * @disp: Display subsystem
1789 * @layer: layer to set the format
1790 * @bus_fmt: bus format to set
1792 * Set the live format of the given layer to @live_fmt.
1794 * Return: 0 on success. -EINVAL if @bus_fmt is not supported by the layer.
1796 static int zynqmp_disp_layer_set_live_fmt(struct zynqmp_disp *disp,
1797 struct zynqmp_disp_layer *layer,
1800 const struct zynqmp_disp_fmt *fmt;
1802 bool is_vid = layer->id == ZYNQMP_DISP_LAYER_VID;
1804 size = ARRAY_SIZE(av_buf_live_fmts);
1805 fmt = zynqmp_disp_map_live_fmt(av_buf_live_fmts, size, bus_fmt);
1809 zynqmp_disp_av_buf_set_live_fmt(&disp->av_buf, fmt->disp_fmt, is_vid);
1810 zynqmp_disp_av_buf_init_live_sf(&disp->av_buf, fmt, is_vid);
1817 * zynqmp_disp_set_tpg - Enable or disable TPG
1818 * @disp: Display subsystem
1819 * @layer: Video layer
1820 * @tpg_on: flag if TPG needs to be enabled or disabled
1822 * Enable / disable the TPG mode on the video layer @layer depending on
1823 * @tpg_on. The video layer should be disabled prior to enable request.
1825 * Return: 0 on success. -ENODEV if it's not video layer. -EIO if
1826 * the video layer is enabled.
1828 static int zynqmp_disp_layer_set_tpg(struct zynqmp_disp *disp,
1829 struct zynqmp_disp_layer *layer,
1832 if (layer->id != ZYNQMP_DISP_LAYER_VID) {
1834 "only the video layer has the tpg mode\n");
1838 if (layer->enabled) {
1840 "the video layer should be disabled for tpg mode\n");
1844 zynqmp_disp_blend_layer_coeff(&disp->blend, layer, tpg_on);
1845 zynqmp_disp_av_buf_set_tpg(&disp->av_buf, tpg_on);
1846 disp->tpg_on = tpg_on;
1852 * zynqmp_disp_get_tpg - Get the TPG mode status
1853 * @disp: Display subsystem
1854 * @layer: Video layer
1856 * Return if the TPG is enabled or not.
1858 * Return: true if TPG is on, otherwise false
1860 static bool zynqmp_disp_layer_get_tpg(struct zynqmp_disp *disp,
1861 struct zynqmp_disp_layer *layer)
1863 return disp->tpg_on;
1867 * zynqmp_disp_get_fmt - Get the supported DRM formats of the layer
1868 * @disp: Display subsystem
1869 * @layer: layer to get the formats
1870 * @drm_fmts: pointer to array of DRM format strings
1871 * @num_fmts: pointer to number of returned DRM formats
1873 * Get the supported DRM formats of the given layer.
1875 static void zynqmp_disp_layer_get_fmts(struct zynqmp_disp *disp,
1876 struct zynqmp_disp_layer *layer,
1877 u32 **drm_fmts, unsigned int *num_fmts)
1879 *drm_fmts = layer->drm_fmts;
1880 *num_fmts = layer->num_fmts;
1884 * zynqmp_disp_layer_enable - Enable the layer
1885 * @disp: Display subsystem
1886 * @layer: layer to esable
1887 * @mode: operation mode
1889 * Enable the layer @layer.
1891 * Return: 0 on success, otherwise error code.
1893 static int zynqmp_disp_layer_enable(struct zynqmp_disp *disp,
1894 struct zynqmp_disp_layer *layer,
1895 enum zynqmp_disp_layer_mode mode)
1897 struct device *dev = disp->dev;
1898 struct dma_async_tx_descriptor *desc;
1899 enum dma_ctrl_flags flags;
1902 if (layer->enabled && layer->mode != mode) {
1903 dev_err(dev, "layer is already enabled in different mode\n");
1907 zynqmp_disp_av_buf_enable_vid(&disp->av_buf, layer, mode);
1908 zynqmp_disp_blend_layer_enable(&disp->blend, layer);
1910 layer->enabled = true;
1913 if (mode == ZYNQMP_DISP_LAYER_LIVE)
1916 for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++) {
1917 struct zynqmp_disp_layer_dma *dma = &layer->dma[i];
1919 if (dma->chan && dma->is_active) {
1920 flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
1921 desc = dmaengine_prep_interleaved_dma(dma->chan,
1924 dev_err(dev, "failed to prep DMA descriptor\n");
1928 dmaengine_submit(desc);
1929 dma_async_issue_pending(dma->chan);
1937 * zynqmp_disp_layer_disable - Disable the layer
1938 * @disp: Display subsystem
1939 * @layer: layer to disable
1940 * @mode: operation mode
1942 * Disable the layer @layer.
1944 * Return: 0 on success, or -EBUSY if the layer is in different mode.
1946 static int zynqmp_disp_layer_disable(struct zynqmp_disp *disp,
1947 struct zynqmp_disp_layer *layer,
1948 enum zynqmp_disp_layer_mode mode)
1950 struct device *dev = disp->dev;
1953 if (layer->mode != mode) {
1954 dev_err(dev, "the layer is operating in different mode\n");
1958 for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
1959 if (layer->dma[i].chan && layer->dma[i].is_active)
1960 dmaengine_terminate_sync(layer->dma[i].chan);
1962 zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
1963 zynqmp_disp_blend_layer_disable(&disp->blend, layer);
1964 layer->enabled = false;
1970 * zynqmp_disp_layer_request_dma - Request DMA channels for a layer
1971 * @disp: Display subsystem
1972 * @layer: layer to request DMA channels
1973 * @name: identifier string for layer type
1975 * Request DMA engine channels for corresponding layer.
1977 * Return: 0 on success, or err value from of_dma_request_slave_channel().
1980 zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
1981 struct zynqmp_disp_layer *layer, const char *name)
1983 struct zynqmp_disp_layer_dma *dma;
1987 for (i = 0; i < layer->num_chan; i++) {
1990 dma = &layer->dma[i];
1991 snprintf(temp, sizeof(temp), "%s%d", name, i);
1992 dma->chan = of_dma_request_slave_channel(layer->of_node,
1994 if (IS_ERR(dma->chan)) {
1995 dev_err(disp->dev, "failed to request dma channel\n");
1996 ret = PTR_ERR(dma->chan);
2006 * zynqmp_disp_layer_release_dma - Release DMA channels for a layer
2007 * @disp: Display subsystem
2008 * @layer: layer to release DMA channels
2010 * Release the dma channels associated with @layer.
2012 static void zynqmp_disp_layer_release_dma(struct zynqmp_disp *disp,
2013 struct zynqmp_disp_layer *layer)
2017 for (i = 0; i < layer->num_chan; i++) {
2018 if (layer->dma[i].chan) {
2019 /* Make sure the channel is terminated before release */
2020 dmaengine_terminate_all(layer->dma[i].chan);
2021 dma_release_channel(layer->dma[i].chan);
2027 * zynqmp_disp_layer_is_live - if any layer is live
2028 * @disp: Display subsystem
2030 * Return: true if any layer is live
2032 static bool zynqmp_disp_layer_is_live(struct zynqmp_disp *disp)
2036 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2037 if (disp->layers[i].enabled &&
2038 disp->layers[i].mode == ZYNQMP_DISP_LAYER_LIVE)
2046 * zynqmp_disp_layer_is_enabled - if any layer is enabled
2047 * @disp: Display subsystem
2049 * Return: true if any layer is enabled
2051 static bool zynqmp_disp_layer_is_enabled(struct zynqmp_disp *disp)
2055 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2056 if (disp->layers[i].enabled)
2063 * zynqmp_disp_layer_destroy - Destroy all layers
2064 * @disp: Display subsystem
2066 * Destroy all layers.
2068 static void zynqmp_disp_layer_destroy(struct zynqmp_disp *disp)
2072 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2073 zynqmp_disp_layer_release_dma(disp, &disp->layers[i]);
2074 if (disp->layers[i].of_node)
2075 of_node_put(disp->layers[i].of_node);
2080 * zynqmp_disp_layer_create - Create all layers
2081 * @disp: Display subsystem
2083 * Create all layers.
2085 * Return: 0 on success, otherwise error code from failed function
2087 static int zynqmp_disp_layer_create(struct zynqmp_disp *disp)
2089 struct zynqmp_disp_layer *layer;
2091 int num_chans[ZYNQMP_DISP_NUM_LAYERS] = { 3, 1 };
2092 const char * const dma_name[] = { "vid", "gfx" };
2095 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2098 layer = &disp->layers[i];
2100 layer->offset = i * 4;
2101 layer->other = &disp->layers[!i];
2102 layer->num_chan = num_chans[i];
2103 snprintf(temp, sizeof(temp), "%s-layer", dma_name[i]);
2104 layer->of_node = of_get_child_by_name(disp->dev->of_node, temp);
2105 if (!layer->of_node)
2107 ret = zynqmp_disp_layer_request_dma(disp, layer, dma_name[i]);
2116 zynqmp_disp_layer_destroy(disp);
2121 * ZynqMP Display internal functions
2125 * Output format enumeration.
2126 * The ID should be aligned with blend_output_fmts.
2127 * The string should be aligned with how zynqmp_dp_set_color() decodes.
2129 static struct drm_prop_enum_list zynqmp_disp_color_enum[] = {
2137 * zynqmp_disp_set_output_fmt - Set the output format
2138 * @disp: Display subsystem
2139 * @id: the format ID. Refer to zynqmp_disp_color_enum[].
2141 * This function sets the output format of the display / blender as well as
2142 * the format of DP controller. The @id should be aligned with
2143 * zynqmp_disp_color_enum.
2146 zynqmp_disp_set_output_fmt(struct zynqmp_disp *disp, unsigned int id)
2148 const struct zynqmp_disp_fmt *fmt = &blend_output_fmts[id];
2150 zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[id].name);
2151 zynqmp_disp_blend_set_output_fmt(&disp->blend, fmt->disp_fmt);
2155 * zynqmp_disp_set_bg_color - Set the background color
2156 * @disp: Display subsystem
2157 * @c0: color component 0
2158 * @c1: color component 1
2159 * @c2: color component 2
2161 * Set the background color with given color components (@c0, @c1, @c2).
2163 static void zynqmp_disp_set_bg_color(struct zynqmp_disp *disp,
2164 u32 c0, u32 c1, u32 c2)
2166 zynqmp_disp_blend_set_bg_color(&disp->blend, c0, c1, c2);
2170 * zynqmp_disp_set_alpha - Set the alpha value
2171 * @disp: Display subsystem
2172 * @alpha: alpha value to set
2174 * Set the alpha value for blending.
2176 static void zynqmp_disp_set_alpha(struct zynqmp_disp *disp, u32 alpha)
2178 disp->alpha = alpha;
2179 zynqmp_disp_blend_set_alpha(&disp->blend, alpha);
2183 * zynqmp_disp_get_alpha - Get the alpha value
2184 * @disp: Display subsystem
2186 * Get the alpha value for blending.
2188 * Return: current alpha value.
2190 static u32 zynqmp_disp_get_alpha(struct zynqmp_disp *disp)
2196 * zynqmp_disp_set_g_alpha - Enable/disable the global alpha blending
2197 * @disp: Display subsystem
2198 * @enable: flag to enable or disable alpha blending
2200 * Set the alpha value for blending.
2202 static void zynqmp_disp_set_g_alpha(struct zynqmp_disp *disp, bool enable)
2204 disp->alpha_en = enable;
2205 zynqmp_disp_blend_enable_alpha(&disp->blend, enable);
2209 * zynqmp_disp_get_g_alpha - Get the global alpha status
2210 * @disp: Display subsystem
2212 * Get the global alpha statue.
2214 * Return: true if global alpha is enabled, or false.
2216 static bool zynqmp_disp_get_g_alpha(struct zynqmp_disp *disp)
2218 return disp->alpha_en;
2222 * zynqmp_disp_enable - Enable the Display subsystem
2223 * @disp: Display subsystem
2225 * Enable the Display subsystem.
2227 static void zynqmp_disp_enable(struct zynqmp_disp *disp)
2234 zynqmp_disp_av_buf_enable(&disp->av_buf);
2235 /* Choose clock source based on the DT clock handle */
2236 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, !!disp->_ps_pclk);
2237 zynqmp_disp_av_buf_set_aud_clock_src(&disp->av_buf, !!disp->_ps_audclk);
2238 live = zynqmp_disp_layer_is_live(disp);
2239 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, !live);
2240 zynqmp_disp_av_buf_enable_buf(&disp->av_buf);
2241 zynqmp_disp_av_buf_enable_aud(&disp->av_buf);
2242 zynqmp_disp_aud_init(&disp->aud);
2243 disp->enabled = true;
2247 * zynqmp_disp_disable - Disable the Display subsystem
2248 * @disp: Display subsystem
2249 * @force: flag to disable forcefully
2251 * Disable the Display subsystem.
2253 static void zynqmp_disp_disable(struct zynqmp_disp *disp, bool force)
2255 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2257 if (!force && (!disp->enabled || zynqmp_disp_layer_is_enabled(disp)))
2260 zynqmp_disp_aud_deinit(&disp->aud);
2261 zynqmp_disp_av_buf_disable_aud(&disp->av_buf);
2262 zynqmp_disp_av_buf_disable_buf(&disp->av_buf);
2263 zynqmp_disp_av_buf_disable(&disp->av_buf);
2265 /* Mark the flip is done as crtc is disabled anyway */
2266 if (crtc->state->event) {
2267 complete_all(crtc->state->event->base.completion);
2268 crtc->state->event = NULL;
2271 disp->enabled = false;
2275 * zynqmp_disp_init - Initialize the Display subsystem states
2276 * @disp: Display subsystem
2278 * Some states are not initialized as desired. For example, the output select
2279 * register resets to the live source. This function is to initialize
2280 * some register states as desired.
2282 static void zynqmp_disp_init(struct zynqmp_disp *disp)
2284 struct zynqmp_disp_layer *layer;
2287 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2288 layer = &disp->layers[i];
2289 zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
2294 * ZynqMP Display external functions for zynqmp_dp
2298 * zynqmp_disp_handle_vblank - Handle the vblank event
2299 * @disp: Display subsystem
2301 * This function handles the vblank interrupt, and sends an event to
2302 * CRTC object. This will be called by the DP vblank interrupt handler.
2304 void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
2306 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2308 drm_crtc_handle_vblank(crtc);
2312 * zynqmp_disp_get_apb_clk_rate - Get the current APB clock rate
2313 * @disp: Display subsystem
2315 * Return: the current APB clock rate.
2317 unsigned int zynqmp_disp_get_apb_clk_rate(struct zynqmp_disp *disp)
2319 return clk_get_rate(disp->aclk);
2323 * zynqmp_disp_aud_enabled - If the audio is enabled
2324 * @disp: Display subsystem
2326 * Return if the audio is enabled depending on the audio clock.
2328 * Return: true if audio is enabled, or false.
2330 bool zynqmp_disp_aud_enabled(struct zynqmp_disp *disp)
2332 return !!disp->audclk;
2336 * zynqmp_disp_get_aud_clk_rate - Get the current audio clock rate
2337 * @disp: Display subsystem
2339 * Return: the current audio clock rate.
2341 unsigned int zynqmp_disp_get_aud_clk_rate(struct zynqmp_disp *disp)
2343 if (zynqmp_disp_aud_enabled(disp))
2345 return clk_get_rate(disp->aclk);
2349 * zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
2350 * @disp: Display subsystem
2352 * Return: the crtc mask of the zyqnmp_disp CRTC.
2354 uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp)
2356 return drm_crtc_mask(&disp->xlnx_crtc.crtc);
2360 * Xlnx bridge functions
2363 static inline struct zynqmp_disp_layer
2364 *bridge_to_layer(struct xlnx_bridge *bridge)
2366 return container_of(bridge, struct zynqmp_disp_layer, bridge);
2369 static int zynqmp_disp_bridge_enable(struct xlnx_bridge *bridge)
2371 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2372 struct zynqmp_disp *disp = layer->disp;
2375 if (!disp->_pl_pclk) {
2376 dev_err(disp->dev, "PL clock is required for live\n");
2380 ret = zynqmp_disp_layer_check_size(disp, layer, layer->w, layer->h);
2384 zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2385 zynqmp_disp_set_alpha(disp, disp->alpha);
2386 ret = zynqmp_disp_layer_enable(layer->disp, layer,
2387 ZYNQMP_DISP_LAYER_LIVE);
2391 if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2392 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2393 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2396 if (zynqmp_disp_av_buf_vid_timing_src_is_int(&disp->av_buf) ||
2397 zynqmp_disp_av_buf_vid_clock_src_is_ps(&disp->av_buf)) {
2399 "Disabling the pipeline to change the clk/timing src");
2400 zynqmp_disp_disable(disp, true);
2401 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, false);
2402 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, false);
2405 zynqmp_disp_enable(disp);
2410 static void zynqmp_disp_bridge_disable(struct xlnx_bridge *bridge)
2412 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2413 struct zynqmp_disp *disp = layer->disp;
2415 zynqmp_disp_disable(disp, false);
2417 zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_LIVE);
2418 if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2419 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2421 if (!zynqmp_disp_layer_is_live(disp)) {
2423 "Disabling the pipeline to change the clk/timing src");
2424 zynqmp_disp_disable(disp, true);
2425 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, true);
2426 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, true);
2427 if (zynqmp_disp_layer_is_enabled(disp))
2428 zynqmp_disp_enable(disp);
2432 static int zynqmp_disp_bridge_set_input(struct xlnx_bridge *bridge,
2433 u32 width, u32 height, u32 bus_fmt)
2435 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2438 ret = zynqmp_disp_layer_check_size(layer->disp, layer, width, height);
2442 ret = zynqmp_disp_layer_set_live_fmt(layer->disp, layer, bus_fmt);
2444 dev_err(layer->disp->dev, "failed to set live fmt\n");
2449 static int zynqmp_disp_bridge_get_input_fmts(struct xlnx_bridge *bridge,
2450 const u32 **fmts, u32 *count)
2452 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2454 *fmts = layer->bus_fmts;
2455 *count = layer->num_bus_fmts;
2461 * DRM plane functions
2464 static inline struct zynqmp_disp_layer *plane_to_layer(struct drm_plane *plane)
2466 return container_of(plane, struct zynqmp_disp_layer, plane);
2469 static int zynqmp_disp_plane_enable(struct drm_plane *plane)
2471 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2472 struct zynqmp_disp *disp = layer->disp;
2475 zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2476 zynqmp_disp_set_alpha(disp, disp->alpha);
2477 ret = zynqmp_disp_layer_enable(layer->disp, layer,
2478 ZYNQMP_DISP_LAYER_NONLIVE);
2482 if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2483 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2484 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2490 static int zynqmp_disp_plane_disable(struct drm_plane *plane)
2492 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2493 struct zynqmp_disp *disp = layer->disp;
2495 zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_NONLIVE);
2496 if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2497 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2502 static int zynqmp_disp_plane_mode_set(struct drm_plane *plane,
2503 struct drm_framebuffer *fb,
2504 int crtc_x, int crtc_y,
2505 unsigned int crtc_w, unsigned int crtc_h,
2506 u32 src_x, u32 src_y,
2507 u32 src_w, u32 src_h)
2509 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2510 const struct drm_format_info *info = fb->format;
2511 struct device *dev = layer->disp->dev;
2517 dev_err(dev, "No format info found\n");
2521 ret = zynqmp_disp_layer_check_size(layer->disp, layer, src_w, src_h);
2525 for (i = 0; i < info->num_planes; i++) {
2526 unsigned int width = src_w / (i ? info->hsub : 1);
2527 unsigned int height = src_h / (i ? info->vsub : 1);
2530 paddr = drm_fb_cma_get_gem_addr(fb, plane->state, i);
2532 dev_err(dev, "failed to get a paddr\n");
2536 layer->dma[i].xt.numf = height;
2537 width_bytes = drm_format_plane_width_bytes(info, i, width);
2538 layer->dma[i].sgl[0].size = width_bytes;
2539 layer->dma[i].sgl[0].icg = fb->pitches[i] -
2540 layer->dma[i].sgl[0].size;
2541 layer->dma[i].xt.src_start = paddr;
2542 layer->dma[i].xt.frame_size = 1;
2543 layer->dma[i].xt.dir = DMA_MEM_TO_DEV;
2544 layer->dma[i].xt.src_sgl = true;
2545 layer->dma[i].xt.dst_sgl = false;
2546 layer->dma[i].is_active = true;
2549 for (; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
2550 layer->dma[i].is_active = false;
2552 ret = zynqmp_disp_layer_set_fmt(layer->disp, layer, info->format);
2554 dev_err(dev, "failed to set dp_sub layer fmt\n");
2559 static void zynqmp_disp_plane_destroy(struct drm_plane *plane)
2561 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2563 xlnx_bridge_unregister(&layer->bridge);
2564 drm_plane_cleanup(plane);
2568 zynqmp_disp_plane_atomic_set_property(struct drm_plane *plane,
2569 struct drm_plane_state *state,
2570 struct drm_property *property, u64 val)
2572 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2573 struct zynqmp_disp *disp = layer->disp;
2576 if (property == disp->g_alpha_prop)
2577 zynqmp_disp_set_alpha(disp, val);
2578 else if (property == disp->g_alpha_en_prop)
2579 zynqmp_disp_set_g_alpha(disp, val);
2580 else if (property == disp->tpg_prop)
2581 ret = zynqmp_disp_layer_set_tpg(disp, layer, val);
2589 zynqmp_disp_plane_atomic_get_property(struct drm_plane *plane,
2590 const struct drm_plane_state *state,
2591 struct drm_property *property,
2594 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2595 struct zynqmp_disp *disp = layer->disp;
2598 if (property == disp->g_alpha_prop)
2599 *val = zynqmp_disp_get_alpha(disp);
2600 else if (property == disp->g_alpha_en_prop)
2601 *val = zynqmp_disp_get_g_alpha(disp);
2602 else if (property == disp->tpg_prop)
2603 *val = zynqmp_disp_layer_get_tpg(disp, layer);
2611 zynqmp_disp_plane_atomic_update_plane(struct drm_plane *plane,
2612 struct drm_crtc *crtc,
2613 struct drm_framebuffer *fb,
2614 int crtc_x, int crtc_y,
2615 unsigned int crtc_w, unsigned int crtc_h,
2616 u32 src_x, u32 src_y,
2617 u32 src_w, u32 src_h,
2618 struct drm_modeset_acquire_ctx *ctx)
2620 struct drm_atomic_state *state;
2621 struct drm_plane_state *plane_state;
2624 state = drm_atomic_state_alloc(plane->dev);
2628 state->acquire_ctx = ctx;
2629 plane_state = drm_atomic_get_plane_state(state, plane);
2630 if (IS_ERR(plane_state)) {
2631 ret = PTR_ERR(plane_state);
2635 ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
2638 drm_atomic_set_fb_for_plane(plane_state, fb);
2639 plane_state->crtc_x = crtc_x;
2640 plane_state->crtc_y = crtc_y;
2641 plane_state->crtc_w = crtc_w;
2642 plane_state->crtc_h = crtc_h;
2643 plane_state->src_x = src_x;
2644 plane_state->src_y = src_y;
2645 plane_state->src_w = src_w;
2646 plane_state->src_h = src_h;
2648 if (plane == crtc->cursor)
2649 state->legacy_cursor_update = true;
2651 /* Do async-update if possible */
2652 state->async_update = !drm_atomic_helper_async_check(plane->dev, state);
2653 ret = drm_atomic_commit(state);
2655 drm_atomic_state_put(state);
2659 static struct drm_plane_funcs zynqmp_disp_plane_funcs = {
2660 .update_plane = zynqmp_disp_plane_atomic_update_plane,
2661 .disable_plane = drm_atomic_helper_disable_plane,
2662 .atomic_set_property = zynqmp_disp_plane_atomic_set_property,
2663 .atomic_get_property = zynqmp_disp_plane_atomic_get_property,
2664 .destroy = zynqmp_disp_plane_destroy,
2665 .reset = drm_atomic_helper_plane_reset,
2666 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
2667 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
2671 zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
2672 struct drm_plane_state *old_state)
2676 if (!plane->state->crtc || !plane->state->fb)
2679 if (plane->state->fb == old_state->fb)
2682 if (old_state->fb &&
2683 old_state->fb->format->format != plane->state->fb->format->format)
2684 zynqmp_disp_plane_disable(plane);
2686 ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
2687 plane->state->crtc_x,
2688 plane->state->crtc_y,
2689 plane->state->crtc_w,
2690 plane->state->crtc_h,
2691 plane->state->src_x >> 16,
2692 plane->state->src_y >> 16,
2693 plane->state->src_w >> 16,
2694 plane->state->src_h >> 16);
2698 zynqmp_disp_plane_enable(plane);
2702 zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
2703 struct drm_plane_state *old_state)
2705 zynqmp_disp_plane_disable(plane);
2708 static int zynqmp_disp_plane_atomic_async_check(struct drm_plane *plane,
2709 struct drm_plane_state *state)
2715 zynqmp_disp_plane_atomic_async_update(struct drm_plane *plane,
2716 struct drm_plane_state *new_state)
2720 if (plane->state->fb == new_state->fb)
2723 if (plane->state->fb &&
2724 plane->state->fb->format->format != new_state->fb->format->format)
2725 zynqmp_disp_plane_disable(plane);
2727 /* Update the current state with new configurations */
2728 drm_atomic_set_fb_for_plane(plane->state, new_state->fb);
2729 plane->state->crtc = new_state->crtc;
2730 plane->state->crtc_x = new_state->crtc_x;
2731 plane->state->crtc_y = new_state->crtc_y;
2732 plane->state->crtc_w = new_state->crtc_w;
2733 plane->state->crtc_h = new_state->crtc_h;
2734 plane->state->src_x = new_state->src_x;
2735 plane->state->src_y = new_state->src_y;
2736 plane->state->src_w = new_state->src_w;
2737 plane->state->src_h = new_state->src_h;
2738 plane->state->state = new_state->state;
2740 ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
2741 plane->state->crtc_x,
2742 plane->state->crtc_y,
2743 plane->state->crtc_w,
2744 plane->state->crtc_h,
2745 plane->state->src_x >> 16,
2746 plane->state->src_y >> 16,
2747 plane->state->src_w >> 16,
2748 plane->state->src_h >> 16);
2752 zynqmp_disp_plane_enable(plane);
2755 static const struct drm_plane_helper_funcs zynqmp_disp_plane_helper_funcs = {
2756 .atomic_update = zynqmp_disp_plane_atomic_update,
2757 .atomic_disable = zynqmp_disp_plane_atomic_disable,
2758 .atomic_async_check = zynqmp_disp_plane_atomic_async_check,
2759 .atomic_async_update = zynqmp_disp_plane_atomic_async_update,
2762 static int zynqmp_disp_create_plane(struct zynqmp_disp *disp)
2764 struct zynqmp_disp_layer *layer;
2767 unsigned int num_fmts = 0;
2768 enum drm_plane_type type;
2771 /* graphics layer is primary, and video layer is overaly */
2772 type = DRM_PLANE_TYPE_OVERLAY;
2773 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2774 layer = &disp->layers[i];
2775 zynqmp_disp_layer_get_fmts(disp, layer, &fmts, &num_fmts);
2776 ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
2777 &zynqmp_disp_plane_funcs, fmts,
2778 num_fmts, NULL, type, NULL);
2781 drm_plane_helper_add(&layer->plane,
2782 &zynqmp_disp_plane_helper_funcs);
2783 type = DRM_PLANE_TYPE_PRIMARY;
2786 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2787 layer = &disp->layers[i];
2788 layer->bridge.enable = &zynqmp_disp_bridge_enable;
2789 layer->bridge.disable = &zynqmp_disp_bridge_disable;
2790 layer->bridge.set_input = &zynqmp_disp_bridge_set_input;
2791 layer->bridge.get_input_fmts =
2792 &zynqmp_disp_bridge_get_input_fmts;
2793 layer->bridge.of_node = layer->of_node;
2794 xlnx_bridge_register(&layer->bridge);
2797 /* Attach properties to each layers */
2798 drm_object_attach_property(&layer->plane.base, disp->g_alpha_prop,
2799 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX);
2800 disp->alpha = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
2801 /* Enable the global alpha as default */
2802 drm_object_attach_property(&layer->plane.base, disp->g_alpha_en_prop,
2804 disp->alpha_en = true;
2806 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2807 drm_object_attach_property(&layer->plane.base, disp->tpg_prop, false);
2813 drm_plane_cleanup(&disp->layers[0].plane);
2817 static void zynqmp_disp_destroy_plane(struct zynqmp_disp *disp)
2821 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2822 zynqmp_disp_plane_destroy(&disp->layers[i].plane);
2826 * Xlnx crtc functions
2829 static inline struct zynqmp_disp *xlnx_crtc_to_disp(struct xlnx_crtc *xlnx_crtc)
2831 return container_of(xlnx_crtc, struct zynqmp_disp, xlnx_crtc);
2834 static int zynqmp_disp_get_max_width(struct xlnx_crtc *xlnx_crtc)
2836 return ZYNQMP_DISP_MAX_WIDTH;
2839 static int zynqmp_disp_get_max_height(struct xlnx_crtc *xlnx_crtc)
2841 return ZYNQMP_DISP_MAX_HEIGHT;
2844 static uint32_t zynqmp_disp_get_format(struct xlnx_crtc *xlnx_crtc)
2846 struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2848 return disp->layers[ZYNQMP_DISP_LAYER_GFX].fmt->drm_fmt;
2851 static unsigned int zynqmp_disp_get_align(struct xlnx_crtc *xlnx_crtc)
2853 struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2854 struct zynqmp_disp_layer *layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2856 return 1 << layer->dma->chan->device->copy_align;
2859 static u64 zynqmp_disp_get_dma_mask(struct xlnx_crtc *xlnx_crtc)
2861 return DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT);
2865 * DRM crtc functions
2868 static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
2870 struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
2872 return xlnx_crtc_to_disp(xlnx_crtc);
2875 static int zynqmp_disp_crtc_mode_set(struct drm_crtc *crtc,
2876 struct drm_display_mode *mode,
2877 struct drm_display_mode *adjusted_mode,
2879 struct drm_framebuffer *old_fb)
2881 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2886 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2887 ret = clk_set_rate(disp->pclk, adjusted_mode->clock * 1000);
2889 dev_err(disp->dev, "failed to set a pixel clock\n");
2893 rate = clk_get_rate(disp->pclk);
2894 diff = rate - adjusted_mode->clock * 1000;
2895 if (abs(diff) > (adjusted_mode->clock * 1000) / 20) {
2896 dev_info(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2897 adjusted_mode->clock, rate);
2899 dev_dbg(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2900 adjusted_mode->clock, rate);
2903 /* The timing register should be programmed always */
2904 zynqmp_dp_encoder_mode_set_stream(disp->dpsub->dp, adjusted_mode);
2910 zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
2911 struct drm_crtc_state *old_crtc_state)
2913 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2914 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2917 zynqmp_disp_crtc_mode_set(crtc, &crtc->state->mode,
2918 adjusted_mode, crtc->x, crtc->y, NULL);
2920 pm_runtime_get_sync(disp->dev);
2921 ret = zynqmp_disp_clk_enable(disp->pclk, &disp->pclk_en);
2923 dev_err(disp->dev, "failed to enable a pixel clock\n");
2926 zynqmp_disp_set_output_fmt(disp, disp->color);
2927 zynqmp_disp_set_bg_color(disp, disp->bg_c0, disp->bg_c1, disp->bg_c2);
2928 zynqmp_disp_enable(disp);
2929 /* Delay of 3 vblank intervals for timing gen to be stable */
2930 vrefresh = (adjusted_mode->clock * 1000) /
2931 (adjusted_mode->vtotal * adjusted_mode->htotal);
2932 msleep(3 * 1000 / vrefresh);
2936 zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
2937 struct drm_crtc_state *old_crtc_state)
2939 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2941 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2942 zynqmp_disp_plane_disable(crtc->primary);
2943 zynqmp_disp_disable(disp, true);
2944 drm_crtc_vblank_off(crtc);
2945 pm_runtime_put_sync(disp->dev);
2948 static int zynqmp_disp_crtc_atomic_check(struct drm_crtc *crtc,
2949 struct drm_crtc_state *state)
2951 return drm_atomic_add_affected_planes(state->state, crtc);
2955 zynqmp_disp_crtc_atomic_begin(struct drm_crtc *crtc,
2956 struct drm_crtc_state *old_crtc_state)
2958 drm_crtc_vblank_on(crtc);
2959 /* Don't rely on vblank when disabling crtc */
2960 spin_lock_irq(&crtc->dev->event_lock);
2961 if (crtc->state->event) {
2962 /* Consume the flip_done event from atomic helper */
2963 crtc->state->event->pipe = drm_crtc_index(crtc);
2964 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
2965 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
2966 crtc->state->event = NULL;
2968 spin_unlock_irq(&crtc->dev->event_lock);
2971 static struct drm_crtc_helper_funcs zynqmp_disp_crtc_helper_funcs = {
2972 .atomic_enable = zynqmp_disp_crtc_atomic_enable,
2973 .atomic_disable = zynqmp_disp_crtc_atomic_disable,
2974 .atomic_check = zynqmp_disp_crtc_atomic_check,
2975 .atomic_begin = zynqmp_disp_crtc_atomic_begin,
2978 static void zynqmp_disp_crtc_destroy(struct drm_crtc *crtc)
2980 zynqmp_disp_crtc_atomic_disable(crtc, NULL);
2981 drm_crtc_cleanup(crtc);
2984 static int zynqmp_disp_crtc_enable_vblank(struct drm_crtc *crtc)
2986 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2988 zynqmp_dp_enable_vblank(disp->dpsub->dp);
2993 static void zynqmp_disp_crtc_disable_vblank(struct drm_crtc *crtc)
2995 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2997 zynqmp_dp_disable_vblank(disp->dpsub->dp);
3001 zynqmp_disp_crtc_atomic_set_property(struct drm_crtc *crtc,
3002 struct drm_crtc_state *state,
3003 struct drm_property *property,
3006 struct zynqmp_disp *disp = crtc_to_disp(crtc);
3009 * CRTC prop values are just stored here and applied when CRTC gets
3012 if (property == disp->color_prop)
3014 else if (property == disp->bg_c0_prop)
3016 else if (property == disp->bg_c1_prop)
3018 else if (property == disp->bg_c2_prop)
3027 zynqmp_disp_crtc_atomic_get_property(struct drm_crtc *crtc,
3028 const struct drm_crtc_state *state,
3029 struct drm_property *property,
3032 struct zynqmp_disp *disp = crtc_to_disp(crtc);
3034 if (property == disp->color_prop)
3036 else if (property == disp->bg_c0_prop)
3038 else if (property == disp->bg_c1_prop)
3040 else if (property == disp->bg_c2_prop)
3048 static struct drm_crtc_funcs zynqmp_disp_crtc_funcs = {
3049 .destroy = zynqmp_disp_crtc_destroy,
3050 .set_config = drm_atomic_helper_set_config,
3051 .page_flip = drm_atomic_helper_page_flip,
3052 .atomic_set_property = zynqmp_disp_crtc_atomic_set_property,
3053 .atomic_get_property = zynqmp_disp_crtc_atomic_get_property,
3054 .reset = drm_atomic_helper_crtc_reset,
3055 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
3056 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
3057 .enable_vblank = zynqmp_disp_crtc_enable_vblank,
3058 .disable_vblank = zynqmp_disp_crtc_disable_vblank,
3061 static void zynqmp_disp_create_crtc(struct zynqmp_disp *disp)
3063 struct drm_plane *plane = &disp->layers[ZYNQMP_DISP_LAYER_GFX].plane;
3064 struct drm_mode_object *obj = &disp->xlnx_crtc.crtc.base;
3067 ret = drm_crtc_init_with_planes(disp->drm, &disp->xlnx_crtc.crtc, plane,
3068 NULL, &zynqmp_disp_crtc_funcs, NULL);
3069 drm_crtc_helper_add(&disp->xlnx_crtc.crtc,
3070 &zynqmp_disp_crtc_helper_funcs);
3071 drm_object_attach_property(obj, disp->color_prop, 0);
3072 zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[0].name);
3073 drm_object_attach_property(obj, disp->bg_c0_prop, 0);
3074 drm_object_attach_property(obj, disp->bg_c1_prop, 0);
3075 drm_object_attach_property(obj, disp->bg_c2_prop, 0);
3077 disp->xlnx_crtc.get_max_width = &zynqmp_disp_get_max_width;
3078 disp->xlnx_crtc.get_max_height = &zynqmp_disp_get_max_height;
3079 disp->xlnx_crtc.get_format = &zynqmp_disp_get_format;
3080 disp->xlnx_crtc.get_align = &zynqmp_disp_get_align;
3081 disp->xlnx_crtc.get_dma_mask = &zynqmp_disp_get_dma_mask;
3082 xlnx_crtc_register(disp->drm, &disp->xlnx_crtc);
3085 static void zynqmp_disp_destroy_crtc(struct zynqmp_disp *disp)
3087 xlnx_crtc_unregister(disp->drm, &disp->xlnx_crtc);
3088 zynqmp_disp_crtc_destroy(&disp->xlnx_crtc.crtc);
3091 static void zynqmp_disp_map_crtc_to_plane(struct zynqmp_disp *disp)
3093 u32 possible_crtcs = drm_crtc_mask(&disp->xlnx_crtc.crtc);
3096 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
3097 disp->layers[i].plane.possible_crtcs = possible_crtcs;
3101 * Component functions
3104 int zynqmp_disp_bind(struct device *dev, struct device *master, void *data)
3106 struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
3107 struct zynqmp_disp *disp = dpsub->disp;
3108 struct drm_device *drm = data;
3115 max = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
3116 disp->g_alpha_prop = drm_property_create_range(drm, 0, "alpha", 0, max);
3117 disp->g_alpha_en_prop = drm_property_create_bool(drm, 0,
3119 num = ARRAY_SIZE(zynqmp_disp_color_enum);
3120 disp->color_prop = drm_property_create_enum(drm, 0,
3122 zynqmp_disp_color_enum,
3124 max = ZYNQMP_DISP_V_BLEND_BG_MAX;
3125 disp->bg_c0_prop = drm_property_create_range(drm, 0, "bg_c0", 0, max);
3126 disp->bg_c1_prop = drm_property_create_range(drm, 0, "bg_c1", 0, max);
3127 disp->bg_c2_prop = drm_property_create_range(drm, 0, "bg_c2", 0, max);
3128 disp->tpg_prop = drm_property_create_bool(drm, 0, "tpg");
3130 ret = zynqmp_disp_create_plane(disp);
3133 zynqmp_disp_create_crtc(disp);
3134 zynqmp_disp_map_crtc_to_plane(disp);
3139 void zynqmp_disp_unbind(struct device *dev, struct device *master, void *data)
3141 struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
3142 struct zynqmp_disp *disp = dpsub->disp;
3144 zynqmp_disp_destroy_crtc(disp);
3145 zynqmp_disp_destroy_plane(disp);
3146 drm_property_destroy(disp->drm, disp->bg_c2_prop);
3147 drm_property_destroy(disp->drm, disp->bg_c1_prop);
3148 drm_property_destroy(disp->drm, disp->bg_c0_prop);
3149 drm_property_destroy(disp->drm, disp->color_prop);
3150 drm_property_destroy(disp->drm, disp->g_alpha_en_prop);
3151 drm_property_destroy(disp->drm, disp->g_alpha_prop);
3155 * Platform initialization functions
3158 static int zynqmp_disp_enumerate_fmts(struct zynqmp_disp *disp)
3160 struct zynqmp_disp_layer *layer;
3162 u32 i, size, num_bus_fmts;
3163 u32 gfx_fmt = ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565;
3165 num_bus_fmts = ARRAY_SIZE(av_buf_live_fmts);
3166 bus_fmts = devm_kzalloc(disp->dev, sizeof(*bus_fmts) * num_bus_fmts,
3170 for (i = 0; i < num_bus_fmts; i++)
3171 bus_fmts[i] = av_buf_live_fmts[i].bus_fmt;
3173 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
3174 layer->num_bus_fmts = num_bus_fmts;
3175 layer->bus_fmts = bus_fmts;
3176 size = ARRAY_SIZE(av_buf_vid_fmts);
3177 layer->num_fmts = size;
3178 layer->drm_fmts = devm_kzalloc(disp->dev,
3179 sizeof(*layer->drm_fmts) * size,
3181 if (!layer->drm_fmts)
3183 for (i = 0; i < layer->num_fmts; i++)
3184 layer->drm_fmts[i] = av_buf_vid_fmts[i].drm_fmt;
3185 layer->fmt = &av_buf_vid_fmts[ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV];
3187 layer = &disp->layers[ZYNQMP_DISP_LAYER_GFX];
3188 layer->num_bus_fmts = num_bus_fmts;
3189 layer->bus_fmts = bus_fmts;
3190 size = ARRAY_SIZE(av_buf_gfx_fmts);
3191 layer->num_fmts = size;
3192 layer->drm_fmts = devm_kzalloc(disp->dev,
3193 sizeof(*layer->drm_fmts) * size,
3195 if (!layer->drm_fmts)
3198 for (i = 0; i < layer->num_fmts; i++)
3199 layer->drm_fmts[i] = av_buf_gfx_fmts[i].drm_fmt;
3200 if (zynqmp_disp_gfx_init_fmt < ARRAY_SIZE(zynqmp_disp_gfx_init_fmts))
3201 gfx_fmt = zynqmp_disp_gfx_init_fmts[zynqmp_disp_gfx_init_fmt];
3202 layer->fmt = &av_buf_gfx_fmts[gfx_fmt];
3207 int zynqmp_disp_probe(struct platform_device *pdev)
3209 struct zynqmp_dpsub *dpsub;
3210 struct zynqmp_disp *disp;
3211 struct resource *res;
3214 disp = devm_kzalloc(&pdev->dev, sizeof(*disp), GFP_KERNEL);
3217 disp->dev = &pdev->dev;
3219 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
3220 disp->blend.base = devm_ioremap_resource(&pdev->dev, res);
3221 if (IS_ERR(disp->blend.base))
3222 return PTR_ERR(disp->blend.base);
3224 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
3225 disp->av_buf.base = devm_ioremap_resource(&pdev->dev, res);
3226 if (IS_ERR(disp->av_buf.base))
3227 return PTR_ERR(disp->av_buf.base);
3229 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
3230 disp->aud.base = devm_ioremap_resource(&pdev->dev, res);
3231 if (IS_ERR(disp->aud.base))
3232 return PTR_ERR(disp->aud.base);
3234 dpsub = platform_get_drvdata(pdev);
3236 disp->dpsub = dpsub;
3238 ret = zynqmp_disp_enumerate_fmts(disp);
3242 /* Try the live PL video clock */
3243 disp->_pl_pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk");
3244 if (!IS_ERR(disp->_pl_pclk)) {
3245 disp->pclk = disp->_pl_pclk;
3246 ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3250 } else if (PTR_ERR(disp->_pl_pclk) == -EPROBE_DEFER) {
3251 return PTR_ERR(disp->_pl_pclk);
3254 /* If the live PL video clock is not valid, fall back to PS clock */
3256 disp->_ps_pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in");
3257 if (IS_ERR(disp->_ps_pclk)) {
3258 dev_err(disp->dev, "failed to init any video clock\n");
3259 return PTR_ERR(disp->_ps_pclk);
3261 disp->pclk = disp->_ps_pclk;
3262 ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3265 dev_err(disp->dev, "failed to init any video clock\n");
3270 disp->aclk = devm_clk_get(disp->dev, "dp_apb_clk");
3271 if (IS_ERR(disp->aclk))
3272 return PTR_ERR(disp->aclk);
3273 ret = zynqmp_disp_clk_enable(disp->aclk, &disp->aclk_en);
3275 dev_err(disp->dev, "failed to enable the APB clk\n");
3279 /* Try the live PL audio clock */
3280 disp->_pl_audclk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
3281 if (!IS_ERR(disp->_pl_audclk)) {
3282 disp->audclk = disp->_pl_audclk;
3283 ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3286 disp->audclk = NULL;
3289 /* If the live PL audio clock is not valid, fall back to PS clock */
3290 if (!disp->audclk) {
3291 disp->_ps_audclk = devm_clk_get(disp->dev, "dp_aud_clk");
3292 if (!IS_ERR(disp->_ps_audclk)) {
3293 disp->audclk = disp->_ps_audclk;
3294 ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3297 disp->audclk = NULL;
3300 if (!disp->audclk) {
3302 "audio is disabled due to clock failure\n");
3306 ret = zynqmp_disp_layer_create(disp);
3310 zynqmp_disp_init(disp);
3315 zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3319 int zynqmp_disp_remove(struct platform_device *pdev)
3321 struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
3322 struct zynqmp_disp *disp = dpsub->disp;
3324 zynqmp_disp_layer_destroy(disp);
3326 zynqmp_disp_clk_disable(disp->audclk, &disp->audclk_en);
3327 zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3328 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);