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 /* Blender registers */
73 #define ZYNQMP_DISP_V_BLEND_BG_CLR_0 0x0
74 #define ZYNQMP_DISP_V_BLEND_BG_CLR_1 0x4
75 #define ZYNQMP_DISP_V_BLEND_BG_CLR_2 0x8
76 #define ZYNQMP_DISP_V_BLEND_BG_MAX 0xfff
77 #define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA 0xc
78 #define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK 0x1fe
79 #define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX 0xff
80 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT 0x14
81 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB 0x0
82 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444 0x1
83 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422 0x2
84 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY 0x3
85 #define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_XVYCC 0x4
86 #define ZYNQMP_DISP_V_BLEND_OUTPUT_EN_DOWNSAMPLE BIT(4)
87 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL 0x18
88 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US BIT(0)
89 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB BIT(1)
90 #define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_BYPASS BIT(8)
91 #define ZYNQMP_DISP_V_BLEND_NUM_COEFF 9
92 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0 0x20
93 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF1 0x24
94 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF2 0x28
95 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF3 0x2c
96 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF4 0x30
97 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF5 0x34
98 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF6 0x38
99 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF7 0x3c
100 #define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF8 0x40
101 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0 0x44
102 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF1 0x48
103 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF2 0x4c
104 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF3 0x50
105 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF4 0x54
106 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF5 0x58
107 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF6 0x5c
108 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF7 0x60
109 #define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF8 0x64
110 #define ZYNQMP_DISP_V_BLEND_NUM_OFFSET 3
111 #define ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET 0x68
112 #define ZYNQMP_DISP_V_BLEND_CR_IN1CSC_OFFSET 0x6c
113 #define ZYNQMP_DISP_V_BLEND_CB_IN1CSC_OFFSET 0x70
114 #define ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET 0x74
115 #define ZYNQMP_DISP_V_BLEND_CR_OUTCSC_OFFSET 0x78
116 #define ZYNQMP_DISP_V_BLEND_CB_OUTCSC_OFFSET 0x7c
117 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0 0x80
118 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF1 0x84
119 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF2 0x88
120 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF3 0x8c
121 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF4 0x90
122 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF5 0x94
123 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF6 0x98
124 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF7 0x9c
125 #define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF8 0xa0
126 #define ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET 0xa4
127 #define ZYNQMP_DISP_V_BLEND_CR_IN2CSC_OFFSET 0xa8
128 #define ZYNQMP_DISP_V_BLEND_CB_IN2CSC_OFFSET 0xac
129 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_ENABLE 0x1d0
130 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP1 0x1d4
131 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP2 0x1d8
132 #define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP3 0x1dc
134 /* AV buffer manager registers */
135 #define ZYNQMP_DISP_AV_BUF_FMT 0x0
136 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_SHIFT 0
137 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK (0x1f << 0)
138 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_UYVY (0 << 0)
139 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY (1 << 0)
140 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YVYU (2 << 0)
141 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV (3 << 0)
142 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16 (4 << 0)
143 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24 (5 << 0)
144 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI (6 << 0)
145 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO (7 << 0)
146 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2 (8 << 0)
147 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444 (9 << 0)
148 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888 (10 << 0)
149 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880 (11 << 0)
150 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10 (12 << 0)
151 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444_10 (13 << 0)
152 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_10 (14 << 0)
153 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10 (15 << 0)
154 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_10 (16 << 0)
155 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24_10 (17 << 0)
156 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10 (18 << 0)
157 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420 (19 << 0)
158 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420 (20 << 0)
159 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420 (21 << 0)
160 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420_10 (22 << 0)
161 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10 (23 << 0)
162 #define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420_10 (24 << 0)
163 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_SHIFT 8
164 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK (0xf << 8)
165 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888 (0 << 8)
166 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888 (1 << 8)
167 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888 (2 << 8)
168 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888 (3 << 8)
169 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551 (4 << 8)
170 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444 (5 << 8)
171 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565 (6 << 8)
172 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_8BPP (7 << 8)
173 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_4BPP (8 << 8)
174 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_2BPP (9 << 8)
175 #define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_1BPP (10 << 8)
176 #define ZYNQMP_DISP_AV_BUF_NON_LIVE_LATENCY 0x8
177 #define ZYNQMP_DISP_AV_BUF_CHBUF 0x10
178 #define ZYNQMP_DISP_AV_BUF_CHBUF_EN BIT(0)
179 #define ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH BIT(1)
180 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT 2
181 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MASK (0xf << 2)
182 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX 0xf
183 #define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX 0x3
184 #define ZYNQMP_DISP_AV_BUF_STATUS 0x28
185 #define ZYNQMP_DISP_AV_BUF_STC_CTRL 0x2c
186 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EN BIT(0)
187 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_SHIFT 1
188 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VSYNC 0
189 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VID 1
190 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_AUD 2
191 #define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_INT_VSYNC 3
192 #define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE0 0x30
193 #define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE1 0x34
194 #define ZYNQMP_DISP_AV_BUF_STC_ADJ 0x38
195 #define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS0 0x3c
196 #define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS1 0x40
197 #define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS0 0x44
198 #define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS1 0x48
199 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS0 0x4c
200 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS1 0x50
201 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS0 0x54
202 #define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS1 0x58
203 #define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT0 0x60
204 #define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT1 0x64
205 #define ZYNQMP_DISP_AV_BUF_OUTPUT 0x70
206 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_SHIFT 0
207 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK (0x3 << 0)
208 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE (0 << 0)
209 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM (1 << 0)
210 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN (2 << 0)
211 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE (3 << 0)
212 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_SHIFT 2
213 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK (0x3 << 2)
214 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE (0 << 2)
215 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM (1 << 2)
216 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE (2 << 2)
217 #define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_NONE (3 << 2)
218 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_SHIFT 4
219 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK (0x3 << 4)
220 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PL (0 << 4)
221 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM (1 << 4)
222 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PATTERN (2 << 4)
223 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE (3 << 4)
224 #define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN BIT(6)
225 #define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT0 0x74
226 #define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT1 0x78
227 #define ZYNQMP_DISP_AV_BUF_PATTERN_GEN_SELECT 0x100
228 #define ZYNQMP_DISP_AV_BUF_CLK_SRC 0x120
229 #define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS BIT(0)
230 #define ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS BIT(1)
231 #define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING BIT(2)
232 #define ZYNQMP_DISP_AV_BUF_SRST_REG 0x124
233 #define ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST BIT(1)
234 #define ZYNQMP_DISP_AV_BUF_AUDIO_CH_CONFIG 0x12c
235 #define ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF 0x200
236 #define ZYNQMP_DISP_AV_BUF_GFX_COMP1_SF 0x204
237 #define ZYNQMP_DISP_AV_BUF_GFX_COMP2_SF 0x208
238 #define ZYNQMP_DISP_AV_BUF_VID_COMP0_SF 0x20c
239 #define ZYNQMP_DISP_AV_BUF_VID_COMP1_SF 0x210
240 #define ZYNQMP_DISP_AV_BUF_VID_COMP2_SF 0x214
241 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF 0x218
242 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP1_SF 0x21c
243 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP2_SF 0x220
244 #define ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG 0x224
245 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF 0x228
246 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP1_SF 0x22c
247 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP2_SF 0x230
248 #define ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG 0x234
249 #define ZYNQMP_DISP_AV_BUF_4BIT_SF 0x11111
250 #define ZYNQMP_DISP_AV_BUF_5BIT_SF 0x10842
251 #define ZYNQMP_DISP_AV_BUF_6BIT_SF 0x10410
252 #define ZYNQMP_DISP_AV_BUF_8BIT_SF 0x10101
253 #define ZYNQMP_DISP_AV_BUF_10BIT_SF 0x10040
254 #define ZYNQMP_DISP_AV_BUF_NULL_SF 0
255 #define ZYNQMP_DISP_AV_BUF_NUM_SF 3
256 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 0x0
257 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 0x1
258 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 0x2
259 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12 0x3
260 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASK GENMASK(2, 0)
261 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB 0x0
262 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444 0x1
263 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422 0x2
264 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY 0x3
265 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASK GENMASK(5, 4)
266 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_CB_FIRST BIT(8)
267 #define ZYNQMP_DISP_AV_BUF_PALETTE_MEMORY 0x400
269 /* Audio registers */
270 #define ZYNQMP_DISP_AUD_MIXER_VOLUME 0x0
271 #define ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE 0x20002000
272 #define ZYNQMP_DISP_AUD_MIXER_META_DATA 0x4
273 #define ZYNQMP_DISP_AUD_CH_STATUS0 0x8
274 #define ZYNQMP_DISP_AUD_CH_STATUS1 0xc
275 #define ZYNQMP_DISP_AUD_CH_STATUS2 0x10
276 #define ZYNQMP_DISP_AUD_CH_STATUS3 0x14
277 #define ZYNQMP_DISP_AUD_CH_STATUS4 0x18
278 #define ZYNQMP_DISP_AUD_CH_STATUS5 0x1c
279 #define ZYNQMP_DISP_AUD_CH_A_DATA0 0x20
280 #define ZYNQMP_DISP_AUD_CH_A_DATA1 0x24
281 #define ZYNQMP_DISP_AUD_CH_A_DATA2 0x28
282 #define ZYNQMP_DISP_AUD_CH_A_DATA3 0x2c
283 #define ZYNQMP_DISP_AUD_CH_A_DATA4 0x30
284 #define ZYNQMP_DISP_AUD_CH_A_DATA5 0x34
285 #define ZYNQMP_DISP_AUD_CH_B_DATA0 0x38
286 #define ZYNQMP_DISP_AUD_CH_B_DATA1 0x3c
287 #define ZYNQMP_DISP_AUD_CH_B_DATA2 0x40
288 #define ZYNQMP_DISP_AUD_CH_B_DATA3 0x44
289 #define ZYNQMP_DISP_AUD_CH_B_DATA4 0x48
290 #define ZYNQMP_DISP_AUD_CH_B_DATA5 0x4c
291 #define ZYNQMP_DISP_AUD_SOFT_RESET 0xc00
292 #define ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST BIT(0)
294 #define ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS 4
295 #define ZYNQMP_DISP_AV_BUF_NUM_BUFFERS 6
297 #define ZYNQMP_DISP_NUM_LAYERS 2
298 #define ZYNQMP_DISP_MAX_NUM_SUB_PLANES 3
300 * 3840x2160 is advertised max resolution, but almost any resolutions under
301 * 300Mhz pixel rate would work. Thus put 4096 as maximum width and height.
303 #define ZYNQMP_DISP_MAX_WIDTH 4096
304 #define ZYNQMP_DISP_MAX_HEIGHT 4096
305 /* 44 bit addressing. This is acutally DPDMA limitation */
306 #define ZYNQMP_DISP_MAX_DMA_BIT 44
309 * enum zynqmp_disp_layer_type - Layer type (can be used for hw ID)
310 * @ZYNQMP_DISP_LAYER_VID: Video layer
311 * @ZYNQMP_DISP_LAYER_GFX: Graphics layer
313 enum zynqmp_disp_layer_type {
314 ZYNQMP_DISP_LAYER_VID,
315 ZYNQMP_DISP_LAYER_GFX
319 * enum zynqmp_disp_layer_mode - Layer mode
320 * @ZYNQMP_DISP_LAYER_NONLIVE: non-live (memory) mode
321 * @ZYNQMP_DISP_LAYER_LIVE: live (stream) mode
323 enum zynqmp_disp_layer_mode {
324 ZYNQMP_DISP_LAYER_NONLIVE,
325 ZYNQMP_DISP_LAYER_LIVE
329 * struct zynqmp_disp_layer_dma - struct for DMA engine
331 * @is_active: flag if the DMA is active
332 * @xt: Interleaved desc config container
333 * @sgl: Data chunk for dma_interleaved_template
335 struct zynqmp_disp_layer_dma {
336 struct dma_chan *chan;
338 struct dma_interleaved_template xt;
339 struct data_chunk sgl[1];
343 * struct zynqmp_disp_layer - Display subsystem layer
345 * @bridge: Xlnx bridge
346 * @of_node: device node
347 * @dma: struct for DMA engine
348 * @num_chan: Number of DMA channel
350 * @offset: Layer offset in the register space
351 * @enabled: flag if enabled
352 * @fmt: Current format descriptor
353 * @drm_fmts: Array of supported DRM formats
354 * @num_fmts: Number of supported DRM formats
355 * @bus_fmts: Array of supported bus formats
356 * @num_bus_fmts: Number of supported bus formats
359 * @mode: the operation mode
360 * @other: other layer
361 * @disp: back pointer to struct zynqmp_disp
363 struct zynqmp_disp_layer {
364 struct drm_plane plane;
365 struct xlnx_bridge bridge;
366 struct device_node *of_node;
367 struct zynqmp_disp_layer_dma dma[ZYNQMP_DISP_MAX_NUM_SUB_PLANES];
368 unsigned int num_chan;
369 enum zynqmp_disp_layer_type id;
372 const struct zynqmp_disp_fmt *fmt;
374 unsigned int num_fmts;
376 unsigned int num_bus_fmts;
379 enum zynqmp_disp_layer_mode mode;
380 struct zynqmp_disp_layer *other;
381 struct zynqmp_disp *disp;
385 * struct zynqmp_disp_blend - Blender
386 * @base: Base address offset
388 struct zynqmp_disp_blend {
393 * struct zynqmp_disp_av_buf - AV buffer manager
394 * @base: Base address offset
396 struct zynqmp_disp_av_buf {
401 * struct zynqmp_disp_aud - Audio
402 * @base: Base address offset
404 struct zynqmp_disp_aud {
409 * struct zynqmp_disp - Display subsystem
410 * @xlnx_crtc: Xilinx DRM crtc
411 * @dev: device structure
412 * @dpsub: Display subsystem
414 * @enabled: flag if enabled
415 * @blend: Blender block
416 * @av_buf: AV buffer manager block
419 * @g_alpha_prop: global alpha property
420 * @alpha: current global alpha value
421 * @g_alpha_en_prop: the global alpha enable property
422 * @alpha_en: flag if the global alpha is enabled
423 * @color_prop: output color format property
424 * @color: current output color value
425 * @bg_c0_prop: 1st component of background color property
426 * @bg_c0: current value of 1st background color component
427 * @bg_c1_prop: 2nd component of background color property
428 * @bg_c1: current value of 2nd background color component
429 * @bg_c2_prop: 3rd component of background color property
430 * @bg_c2: current value of 3rd background color component
431 * @tpg_prop: Test Pattern Generation mode property
432 * @tpg_on: current TPG mode state
433 * @event: pending vblank event request
434 * @_ps_pclk: Pixel clock from PS
435 * @_pl_pclk: Pixel clock from PL
437 * @pclk_en: Flag if the pixel clock is enabled
438 * @_ps_audclk: Audio clock from PS
439 * @_pl_audclk: Audio clock from PL
440 * @audclk: Audio clock
441 * @audclk_en: Flag if the audio clock is enabled
443 * @aclk_en: Flag if the APB clock is enabled
446 struct xlnx_crtc xlnx_crtc;
448 struct zynqmp_dpsub *dpsub;
449 struct drm_device *drm;
451 struct zynqmp_disp_blend blend;
452 struct zynqmp_disp_av_buf av_buf;
453 struct zynqmp_disp_aud aud;
454 struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
455 struct drm_property *g_alpha_prop;
457 struct drm_property *g_alpha_en_prop;
459 struct drm_property *color_prop;
461 struct drm_property *bg_c0_prop;
463 struct drm_property *bg_c1_prop;
465 struct drm_property *bg_c2_prop;
467 struct drm_property *tpg_prop;
469 struct drm_pending_vblank_event *event;
470 /* Don't operate directly on _ps_ */
471 struct clk *_ps_pclk;
472 struct clk *_pl_pclk;
475 struct clk *_ps_audclk;
476 struct clk *_pl_audclk;
484 * struct zynqmp_disp_fmt - Display subsystem format mapping
485 * @drm_fmt: drm format
486 * @disp_fmt: Display subsystem format
487 * @bus_fmt: Bus formats (live formats)
488 * @rgb: flag for RGB formats
489 * @swap: flag to swap r & b for rgb formats, and u & v for yuv formats
490 * @chroma_sub: flag for chroma subsampled formats
491 * @sf: scaling factors for upto 3 color components
493 struct zynqmp_disp_fmt {
503 static void zynqmp_disp_write(void __iomem *base, int offset, u32 val)
505 writel(val, base + offset);
508 static u32 zynqmp_disp_read(void __iomem *base, int offset)
510 return readl(base + offset);
513 static void zynqmp_disp_clr(void __iomem *base, int offset, u32 clr)
515 zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) & ~clr);
518 static void zynqmp_disp_set(void __iomem *base, int offset, u32 set)
520 zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) | set);
528 * zynqmp_disp_clk_enable - Enable the clock if needed
530 * @flag: flag if the clock is enabled
532 * Enable the clock only if it's not enabled @flag.
534 * Return: value from clk_prepare_enable().
536 static int zynqmp_disp_clk_enable(struct clk *clk, bool *flag)
541 ret = clk_prepare_enable(clk);
550 * zynqmp_disp_clk_enable - Enable the clock if needed
552 * @flag: flag if the clock is enabled
554 * Disable the clock only if it's enabled @flag.
556 static void zynqmp_disp_clk_disable(struct clk *clk, bool *flag)
559 clk_disable_unprepare(clk);
565 * zynqmp_disp_clk_enable - Enable and disable the clock
567 * @flag: flag if the clock is enabled
569 * This is to ensure the clock is disabled. The initial hardware state is
570 * unknown, and this makes sure that the clock is disabled.
572 * Return: value from clk_prepare_enable().
574 static int zynqmp_disp_clk_enable_disable(struct clk *clk, bool *flag)
579 ret = clk_prepare_enable(clk);
580 clk_disable_unprepare(clk);
591 * zynqmp_disp_blend_set_output_fmt - Set the output format of the blend
592 * @blend: blend object
593 * @fmt: output format
595 * Set the output format to @fmt.
598 zynqmp_disp_blend_set_output_fmt(struct zynqmp_disp_blend *blend, u32 fmt)
600 u16 reset_coeffs[] = { 0x1000, 0x0, 0x0,
603 u32 reset_offsets[] = { 0x0, 0x0, 0x0 };
604 u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
605 0x7d4d, 0x7ab3, 0x800,
606 0x800, 0x794d, 0x7eb3 };
607 u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
612 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt);
613 if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) {
614 coeffs = reset_coeffs;
615 offsets = reset_offsets;
617 /* Hardcode Full-range SDTV values. Can be runtime config */
618 coeffs = sdtv_coeffs;
619 offsets = full_range_offsets;
622 offset = ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0;
623 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
624 zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
626 offset = ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET;
627 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
628 zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
632 * zynqmp_disp_blend_layer_enable - Enable a layer
633 * @blend: blend object
634 * @layer: layer to enable
636 * Enable a layer @layer.
638 static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
639 struct zynqmp_disp_layer *layer)
641 u32 reg, offset, i, s0, s1;
642 u16 sdtv_coeffs[] = { 0x1000, 0x166f, 0x0,
643 0x1000, 0x7483, 0x7a7f,
644 0x1000, 0x0, 0x1c5a };
645 u16 swap_coeffs[] = { 0x1000, 0x0, 0x0,
649 u32 offsets[] = { 0x0, 0x1800, 0x1800 };
651 reg = layer->fmt->rgb ? ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB : 0;
652 reg |= layer->fmt->chroma_sub ?
653 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0;
655 zynqmp_disp_write(blend->base,
656 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset,
659 if (layer->id == ZYNQMP_DISP_LAYER_VID)
660 offset = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0;
662 offset = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0;
664 if (!layer->fmt->rgb) {
665 coeffs = sdtv_coeffs;
669 coeffs = swap_coeffs;
673 /* No offset for RGB formats */
674 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
678 if (layer->fmt->swap) {
679 for (i = 0; i < 3; i++) {
680 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
681 coeffs[i * 3 + s1] ^= coeffs[i * 3 + s0];
682 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
686 /* Program coefficients. Can be runtime configurable */
687 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
688 zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
690 if (layer->id == ZYNQMP_DISP_LAYER_VID)
691 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET;
693 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET;
695 /* Program offsets. Can be runtime configurable */
696 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
697 zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
701 * zynqmp_disp_blend_layer_disable - Disable a layer
702 * @blend: blend object
703 * @layer: layer to disable
705 * Disable a layer @layer.
707 static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
708 struct zynqmp_disp_layer *layer)
713 zynqmp_disp_write(blend->base,
714 ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset, 0);
716 if (layer->id == ZYNQMP_DISP_LAYER_VID)
717 offset = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0;
719 offset = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0;
720 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
721 zynqmp_disp_write(blend->base, offset + i * 4, 0);
723 if (layer->id == ZYNQMP_DISP_LAYER_VID)
724 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET;
726 offset = ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET;
728 for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
729 zynqmp_disp_write(blend->base, offset + i * 4, 0);
733 * zynqmp_disp_blend_set_bg_color - Set the background color
734 * @blend: blend object
735 * @c0: color component 0
736 * @c1: color component 1
737 * @c2: color component 2
739 * Set the background color.
741 static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp_blend *blend,
742 u32 c0, u32 c1, u32 c2)
744 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_0, c0);
745 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_1, c1);
746 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_2, c2);
750 * zynqmp_disp_blend_set_alpha - Set the alpha for blending
751 * @blend: blend object
752 * @alpha: alpha value to be used
754 * Set the alpha for blending.
757 zynqmp_disp_blend_set_alpha(struct zynqmp_disp_blend *blend, u32 alpha)
761 reg = zynqmp_disp_read(blend->base,
762 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA);
763 reg &= ~ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK;
765 zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
770 * zynqmp_disp_blend_enable_alpha - Enable/disable the global alpha
771 * @blend: blend object
772 * @enable: flag to enable or disable alpha blending
774 * Enable/disable the global alpha blending based on @enable.
777 zynqmp_disp_blend_enable_alpha(struct zynqmp_disp_blend *blend, bool enable)
780 zynqmp_disp_set(blend->base,
781 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
783 zynqmp_disp_clr(blend->base,
784 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
787 /* List of blend output formats */
788 /* The id / order should be aligned with zynqmp_disp_color_enum */
789 static const struct zynqmp_disp_fmt blend_output_fmts[] = {
791 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB,
793 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444,
795 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422,
797 .disp_fmt = ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY,
802 * AV buffer manager functions
805 /* List of video layer formats */
806 #define ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV 2
807 static const struct zynqmp_disp_fmt av_buf_vid_fmts[] = {
809 .drm_fmt = DRM_FORMAT_VYUY,
810 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
814 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
815 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
816 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
818 .drm_fmt = DRM_FORMAT_UYVY,
819 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
823 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
824 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
825 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
827 .drm_fmt = DRM_FORMAT_YUYV,
828 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
832 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
833 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
834 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
836 .drm_fmt = DRM_FORMAT_YVYU,
837 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
841 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
842 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
843 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
845 .drm_fmt = DRM_FORMAT_YUV422,
846 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
850 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
851 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
852 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
854 .drm_fmt = DRM_FORMAT_YVU422,
855 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
859 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
860 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
861 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
863 .drm_fmt = DRM_FORMAT_YUV444,
864 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
868 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
869 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
870 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
872 .drm_fmt = DRM_FORMAT_YVU444,
873 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
877 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
878 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
879 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
881 .drm_fmt = DRM_FORMAT_NV16,
882 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
886 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
887 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
888 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
890 .drm_fmt = DRM_FORMAT_NV61,
891 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
895 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
896 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
897 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
899 .drm_fmt = DRM_FORMAT_BGR888,
900 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
904 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
905 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
906 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
908 .drm_fmt = DRM_FORMAT_RGB888,
909 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
913 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
914 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
915 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
917 .drm_fmt = DRM_FORMAT_XBGR8888,
918 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
922 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
923 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
924 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
926 .drm_fmt = DRM_FORMAT_XRGB8888,
927 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
931 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
932 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
933 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
935 .drm_fmt = DRM_FORMAT_XBGR2101010,
936 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
940 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
941 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
942 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
944 .drm_fmt = DRM_FORMAT_XRGB2101010,
945 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
949 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
950 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
951 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
953 .drm_fmt = DRM_FORMAT_YUV420,
954 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
958 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
959 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
960 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
962 .drm_fmt = DRM_FORMAT_YVU420,
963 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
967 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
968 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
969 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
971 .drm_fmt = DRM_FORMAT_NV12,
972 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
976 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
977 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
978 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
980 .drm_fmt = DRM_FORMAT_NV21,
981 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
985 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
986 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
987 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
989 .drm_fmt = DRM_FORMAT_XV15,
990 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10,
994 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
995 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
996 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
998 .drm_fmt = DRM_FORMAT_XV20,
999 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10,
1003 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1004 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1005 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1009 /* List of graphics layer formats */
1010 #define ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565 10
1011 static const struct zynqmp_disp_fmt av_buf_gfx_fmts[] = {
1013 .drm_fmt = DRM_FORMAT_ABGR8888,
1014 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
1017 .chroma_sub = false,
1018 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1019 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1020 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1022 .drm_fmt = DRM_FORMAT_ARGB8888,
1023 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
1026 .chroma_sub = false,
1027 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1028 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1029 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1031 .drm_fmt = DRM_FORMAT_RGBA8888,
1032 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
1035 .chroma_sub = false,
1036 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1037 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1038 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1040 .drm_fmt = DRM_FORMAT_BGRA8888,
1041 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
1044 .chroma_sub = false,
1045 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1046 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1047 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1049 .drm_fmt = DRM_FORMAT_BGR888,
1050 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888,
1053 .chroma_sub = false,
1054 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1055 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1056 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1058 .drm_fmt = DRM_FORMAT_RGB888,
1059 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888,
1062 .chroma_sub = false,
1063 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1064 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1065 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1067 .drm_fmt = DRM_FORMAT_RGBA5551,
1068 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
1071 .chroma_sub = false,
1072 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1073 .sf[1] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1074 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1076 .drm_fmt = DRM_FORMAT_BGRA5551,
1077 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
1080 .chroma_sub = false,
1081 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1082 .sf[1] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1083 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1085 .drm_fmt = DRM_FORMAT_RGBA4444,
1086 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
1089 .chroma_sub = false,
1090 .sf[0] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1091 .sf[1] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1092 .sf[2] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1094 .drm_fmt = DRM_FORMAT_BGRA4444,
1095 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
1098 .chroma_sub = false,
1099 .sf[0] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1100 .sf[1] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1101 .sf[2] = ZYNQMP_DISP_AV_BUF_4BIT_SF,
1103 .drm_fmt = DRM_FORMAT_RGB565,
1104 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
1107 .chroma_sub = false,
1108 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1109 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1110 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1112 .drm_fmt = DRM_FORMAT_BGR565,
1113 .disp_fmt = ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
1116 .chroma_sub = false,
1117 .sf[0] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1118 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1119 .sf[2] = ZYNQMP_DISP_AV_BUF_5BIT_SF,
1123 /* List of live formats */
1124 /* Format can be combination of color, bpc, and cb-cr order.
1125 * - Color: RGB / YUV444 / YUV422 / Y only
1126 * - BPC: 6, 8, 10, 12
1127 * - Swap: Cb and Cr swap
1128 * which can be 32 bus formats. Only list the subset of those for now.
1130 static const struct zynqmp_disp_fmt av_buf_live_fmts[] = {
1132 .bus_fmt = MEDIA_BUS_FMT_RGB666_1X18,
1133 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 ||
1134 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
1137 .chroma_sub = false,
1138 .sf[0] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1139 .sf[1] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1140 .sf[2] = ZYNQMP_DISP_AV_BUF_6BIT_SF,
1142 .bus_fmt = MEDIA_BUS_FMT_RBG888_1X24,
1143 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1144 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
1147 .chroma_sub = false,
1148 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1149 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1150 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1152 .bus_fmt = MEDIA_BUS_FMT_UYVY8_1X16,
1153 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1154 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1158 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1159 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1160 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1162 .bus_fmt = MEDIA_BUS_FMT_VUY8_1X24,
1163 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 ||
1164 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444,
1167 .chroma_sub = false,
1168 .sf[0] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1169 .sf[1] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1170 .sf[2] = ZYNQMP_DISP_AV_BUF_8BIT_SF,
1172 .bus_fmt = MEDIA_BUS_FMT_UYVY10_1X20,
1173 .disp_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 ||
1174 ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
1178 .sf[0] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1179 .sf[1] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1180 .sf[2] = ZYNQMP_DISP_AV_BUF_10BIT_SF,
1185 * zynqmp_disp_av_buf_set_fmt - Set the input formats
1186 * @av_buf: av buffer manager
1189 * Set the av buffer manager format to @fmt. @fmt should have valid values
1190 * for both video and graphics layer.
1193 zynqmp_disp_av_buf_set_fmt(struct zynqmp_disp_av_buf *av_buf, u32 fmt)
1195 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT, fmt);
1199 * zynqmp_disp_av_buf_get_fmt - Get the input formats
1200 * @av_buf: av buffer manager
1202 * Get the input formats (which include video and graphics) of
1203 * av buffer manager.
1205 * Return: value of ZYNQMP_DISP_AV_BUF_FMT register.
1208 zynqmp_disp_av_buf_get_fmt(struct zynqmp_disp_av_buf *av_buf)
1210 return zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT);
1214 * zynqmp_disp_av_buf_set_live_fmt - Set the live_input format
1215 * @av_buf: av buffer manager
1217 * @is_vid: if it's for video layer
1219 * Set the live input format to @fmt. @fmt should have valid values.
1220 * @vid will determine if it's for video layer or graphics layer
1221 * @fmt should be a valid hardware value.
1223 static void zynqmp_disp_av_buf_set_live_fmt(struct zynqmp_disp_av_buf *av_buf,
1224 u32 fmt, bool is_vid)
1229 offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG;
1231 offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
1233 zynqmp_disp_write(av_buf->base, offset, fmt);
1237 * zynqmp_disp_av_buf_set_vid_clock_src - Set the video clock source
1238 * @av_buf: av buffer manager
1239 * @from_ps: flag if the video clock is from ps
1241 * Set the video clock source based on @from_ps. It can come from either PS or
1245 zynqmp_disp_av_buf_set_vid_clock_src(struct zynqmp_disp_av_buf *av_buf,
1248 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1251 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1253 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
1254 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1258 * zynqmp_disp_av_buf_vid_clock_src_is_ps - if ps clock is used
1259 * @av_buf: av buffer manager
1261 * Return: if ps clock is used
1264 zynqmp_disp_av_buf_vid_clock_src_is_ps(struct zynqmp_disp_av_buf *av_buf)
1266 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1268 return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS);
1272 * zynqmp_disp_av_buf_set_vid_timing_src - Set the video timing source
1273 * @av_buf: av buffer manager
1274 * @internal: flag if the video timing is generated internally
1276 * Set the video timing source based on @internal. It can come externally or
1277 * be generated internally.
1280 zynqmp_disp_av_buf_set_vid_timing_src(struct zynqmp_disp_av_buf *av_buf,
1283 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1286 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1288 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1289 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1293 * zynqmp_disp_av_buf_vid_timing_src_is_int - if internal timing is used
1294 * @av_buf: av buffer manager
1296 * Return: if the internal timing is used
1299 zynqmp_disp_av_buf_vid_timing_src_is_int(struct zynqmp_disp_av_buf *av_buf)
1301 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1303 return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING);
1307 * zynqmp_disp_av_buf_set_aud_clock_src - Set the audio clock source
1308 * @av_buf: av buffer manager
1309 * @from_ps: flag if the video clock is from ps
1311 * Set the audio clock source based on @from_ps. It can come from either PS or
1315 zynqmp_disp_av_buf_set_aud_clock_src(struct zynqmp_disp_av_buf *av_buf,
1318 u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
1321 reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1323 reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
1324 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
1328 * zynqmp_disp_av_buf_enable_buf - Enable buffers
1329 * @av_buf: av buffer manager
1331 * Enable all (video and audio) buffers.
1334 zynqmp_disp_av_buf_enable_buf(struct zynqmp_disp_av_buf *av_buf)
1338 reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1339 reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX <<
1340 ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1342 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
1343 zynqmp_disp_write(av_buf->base,
1344 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1346 reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1347 reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX <<
1348 ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1350 for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1351 zynqmp_disp_write(av_buf->base,
1352 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1356 * zynqmp_disp_av_buf_disable_buf - Disable buffers
1357 * @av_buf: av buffer manager
1359 * Disable all (video and audio) buffers.
1362 zynqmp_disp_av_buf_disable_buf(struct zynqmp_disp_av_buf *av_buf)
1366 reg = ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH & ~ZYNQMP_DISP_AV_BUF_CHBUF_EN;
1367 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
1368 zynqmp_disp_write(av_buf->base,
1369 ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
1373 * zynqmp_disp_av_buf_enable_aud - Enable audio
1374 * @av_buf: av buffer manager
1376 * Enable all audio buffers.
1379 zynqmp_disp_av_buf_enable_aud(struct zynqmp_disp_av_buf *av_buf)
1383 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1384 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1385 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM;
1386 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1387 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1391 * zynqmp_disp_av_buf_enable - Enable the video pipe
1392 * @av_buf: av buffer manager
1394 * De-assert the video pipe reset
1397 zynqmp_disp_av_buf_enable(struct zynqmp_disp_av_buf *av_buf)
1399 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG, 0);
1403 * zynqmp_disp_av_buf_disable - Disable the video pipe
1404 * @av_buf: av buffer manager
1406 * Assert the video pipe reset
1409 zynqmp_disp_av_buf_disable(struct zynqmp_disp_av_buf *av_buf)
1411 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG,
1412 ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST);
1416 * zynqmp_disp_av_buf_disable_aud - Disable audio
1417 * @av_buf: av buffer manager
1419 * Disable all audio buffers.
1422 zynqmp_disp_av_buf_disable_aud(struct zynqmp_disp_av_buf *av_buf)
1426 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1427 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
1428 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE;
1429 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
1430 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1434 * zynqmp_disp_av_buf_set_tpg - Set TPG mode
1435 * @av_buf: av buffer manager
1436 * @tpg_on: if TPG should be on
1438 * Set the TPG mode based on @tpg_on.
1440 static void zynqmp_disp_av_buf_set_tpg(struct zynqmp_disp_av_buf *av_buf,
1445 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1446 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1448 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1450 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
1451 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1455 * zynqmp_disp_av_buf_enable_vid - Enable the video layer buffer
1456 * @av_buf: av buffer manager
1457 * @layer: layer to enable
1458 * @mode: operation mode of layer
1460 * Enable the video/graphics buffer for @layer.
1462 static void zynqmp_disp_av_buf_enable_vid(struct zynqmp_disp_av_buf *av_buf,
1463 struct zynqmp_disp_layer *layer,
1464 enum zynqmp_disp_layer_mode mode)
1468 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1469 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1470 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1471 if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1472 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
1474 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE;
1476 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1477 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1478 if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
1479 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
1481 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE;
1483 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1487 * zynqmp_disp_av_buf_disable_vid - Disable the video layer buffer
1488 * @av_buf: av buffer manager
1489 * @layer: layer to disable
1491 * Disable the video/graphics buffer for @layer.
1494 zynqmp_disp_av_buf_disable_vid(struct zynqmp_disp_av_buf *av_buf,
1495 struct zynqmp_disp_layer *layer)
1499 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
1500 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1501 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
1502 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE;
1504 reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
1505 reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE;
1507 zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
1511 * zynqmp_disp_av_buf_init_sf - Initialize scaling factors
1512 * @av_buf: av buffer manager
1513 * @vid_fmt: video format descriptor
1514 * @gfx_fmt: graphics format descriptor
1516 * Initialize scaling factors for both video and graphics layers.
1517 * If the format descriptor is NULL, the function skips the programming.
1519 static void zynqmp_disp_av_buf_init_sf(struct zynqmp_disp_av_buf *av_buf,
1520 const struct zynqmp_disp_fmt *vid_fmt,
1521 const struct zynqmp_disp_fmt *gfx_fmt)
1527 offset = ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF;
1528 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1529 zynqmp_disp_write(av_buf->base, offset + i * 4,
1534 offset = ZYNQMP_DISP_AV_BUF_VID_COMP0_SF;
1535 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1536 zynqmp_disp_write(av_buf->base, offset + i * 4,
1542 * zynqmp_disp_av_buf_init_live_sf - Initialize scaling factors for live source
1543 * @av_buf: av buffer manager
1544 * @fmt: format descriptor
1545 * @is_vid: flag if this is for video layer
1547 * Initialize scaling factors for live source.
1549 static void zynqmp_disp_av_buf_init_live_sf(struct zynqmp_disp_av_buf *av_buf,
1550 const struct zynqmp_disp_fmt *fmt,
1557 offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF;
1559 offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF;
1561 for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
1562 zynqmp_disp_write(av_buf->base, offset + i * 4,
1571 * zynqmp_disp_aud_init - Initialize the audio
1574 * Initialize the audio with default mixer volume. The de-assertion will
1575 * initialize the audio states.
1577 static void zynqmp_disp_aud_init(struct zynqmp_disp_aud *aud)
1579 /* Clear the audio soft reset register as it's an non-reset flop */
1580 zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
1581 zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_MIXER_VOLUME,
1582 ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
1586 * zynqmp_disp_aud_deinit - De-initialize the audio
1589 * Put the audio in reset.
1591 static void zynqmp_disp_aud_deinit(struct zynqmp_disp_aud *aud)
1593 zynqmp_disp_set(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET,
1594 ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
1598 * ZynqMP Display layer functions
1602 * zynqmp_disp_layer_check_size - Verify width and height for the layer
1603 * @disp: Display subsystem
1608 * The Display subsystem has the limitation that both layers should have
1609 * identical size. This function stores width and height of @layer, and verifies
1610 * if the size (width and height) is valid.
1612 * Return: 0 on success, or -EINVAL if width or/and height is invalid.
1614 static int zynqmp_disp_layer_check_size(struct zynqmp_disp *disp,
1615 struct zynqmp_disp_layer *layer,
1616 u32 width, u32 height)
1618 struct zynqmp_disp_layer *other = layer->other;
1620 if (other->enabled && (other->w != width || other->h != height)) {
1621 dev_err(disp->dev, "Layer width:height must be %d:%d\n",
1622 other->w, other->h);
1633 * zynqmp_disp_map_fmt - Find the Display subsystem format for given drm format
1634 * @fmts: format table to look up
1635 * @size: size of the table @fmts
1636 * @drm_fmt: DRM format to search
1638 * Search a Display subsystem format corresponding to the given DRM format
1639 * @drm_fmt, and return the format descriptor which contains the Display
1640 * subsystem format value.
1642 * Return: a Display subsystem format descriptor on success, or NULL.
1644 static const struct zynqmp_disp_fmt *
1645 zynqmp_disp_map_fmt(const struct zynqmp_disp_fmt fmts[],
1646 unsigned int size, uint32_t drm_fmt)
1650 for (i = 0; i < size; i++)
1651 if (fmts[i].drm_fmt == drm_fmt)
1658 * zynqmp_disp_set_fmt - Set the format of the layer
1659 * @disp: Display subsystem
1660 * @layer: layer to set the format
1661 * @drm_fmt: DRM format to set
1663 * Set the format of the given layer to @drm_fmt.
1665 * Return: 0 on success. -EINVAL if @drm_fmt is not supported by the layer.
1667 static int zynqmp_disp_layer_set_fmt(struct zynqmp_disp *disp,
1668 struct zynqmp_disp_layer *layer,
1671 const struct zynqmp_disp_fmt *fmt;
1672 const struct zynqmp_disp_fmt *vid_fmt = NULL, *gfx_fmt = NULL;
1673 u32 size, fmts, mask;
1675 if (layer->id == ZYNQMP_DISP_LAYER_VID) {
1676 size = ARRAY_SIZE(av_buf_vid_fmts);
1677 mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK;
1678 fmt = zynqmp_disp_map_fmt(av_buf_vid_fmts, size, drm_fmt);
1681 size = ARRAY_SIZE(av_buf_gfx_fmts);
1682 mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
1683 fmt = zynqmp_disp_map_fmt(av_buf_gfx_fmts, size, drm_fmt);
1690 fmts = zynqmp_disp_av_buf_get_fmt(&disp->av_buf);
1692 fmts |= fmt->disp_fmt;
1693 zynqmp_disp_av_buf_set_fmt(&disp->av_buf, fmts);
1694 zynqmp_disp_av_buf_init_sf(&disp->av_buf, vid_fmt, gfx_fmt);
1701 * zynqmp_disp_map_live_fmt - Find the hardware format for given bus format
1702 * @fmts: format table to look up
1703 * @size: size of the table @fmts
1704 * @bus_fmt: bus format to search
1706 * Search a Display subsystem format corresponding to the given bus format
1707 * @bus_fmt, and return the format descriptor which contains the Display
1708 * subsystem format value.
1710 * Return: a Display subsystem format descriptor on success, or NULL.
1712 static const struct zynqmp_disp_fmt *
1713 zynqmp_disp_map_live_fmt(const struct zynqmp_disp_fmt fmts[],
1714 unsigned int size, uint32_t bus_fmt)
1718 for (i = 0; i < size; i++)
1719 if (fmts[i].bus_fmt == bus_fmt)
1726 * zynqmp_disp_set_live_fmt - Set the live format of the layer
1727 * @disp: Display subsystem
1728 * @layer: layer to set the format
1729 * @bus_fmt: bus format to set
1731 * Set the live format of the given layer to @live_fmt.
1733 * Return: 0 on success. -EINVAL if @bus_fmt is not supported by the layer.
1735 static int zynqmp_disp_layer_set_live_fmt(struct zynqmp_disp *disp,
1736 struct zynqmp_disp_layer *layer,
1739 const struct zynqmp_disp_fmt *fmt;
1741 bool is_vid = layer->id == ZYNQMP_DISP_LAYER_VID;
1743 size = ARRAY_SIZE(av_buf_live_fmts);
1744 fmt = zynqmp_disp_map_live_fmt(av_buf_live_fmts, size, bus_fmt);
1748 zynqmp_disp_av_buf_set_live_fmt(&disp->av_buf, fmt->disp_fmt, is_vid);
1749 zynqmp_disp_av_buf_init_live_sf(&disp->av_buf, fmt, is_vid);
1756 * zynqmp_disp_set_tpg - Enable or disable TPG
1757 * @disp: Display subsystem
1758 * @layer: Video layer
1759 * @tpg_on: flag if TPG needs to be enabled or disabled
1761 * Enable / disable the TPG mode on the video layer @layer depending on
1762 * @tpg_on. The video layer should be disabled prior to enable request.
1764 * Return: 0 on success. -ENODEV if it's not video layer. -EIO if
1765 * the video layer is enabled.
1767 static int zynqmp_disp_layer_set_tpg(struct zynqmp_disp *disp,
1768 struct zynqmp_disp_layer *layer,
1771 if (layer->id != ZYNQMP_DISP_LAYER_VID) {
1773 "only the video layer has the tpg mode\n");
1777 if (layer->enabled) {
1779 "the video layer should be disabled for tpg mode\n");
1783 zynqmp_disp_av_buf_set_tpg(&disp->av_buf, tpg_on);
1784 disp->tpg_on = tpg_on;
1790 * zynqmp_disp_get_tpg - Get the TPG mode status
1791 * @disp: Display subsystem
1792 * @layer: Video layer
1794 * Return if the TPG is enabled or not.
1796 * Return: true if TPG is on, otherwise false
1798 static bool zynqmp_disp_layer_get_tpg(struct zynqmp_disp *disp,
1799 struct zynqmp_disp_layer *layer)
1801 return disp->tpg_on;
1805 * zynqmp_disp_get_fmt - Get the supported DRM formats of the layer
1806 * @disp: Display subsystem
1807 * @layer: layer to get the formats
1808 * @drm_fmts: pointer to array of DRM format strings
1809 * @num_fmts: pointer to number of returned DRM formats
1811 * Get the supported DRM formats of the given layer.
1813 static void zynqmp_disp_layer_get_fmts(struct zynqmp_disp *disp,
1814 struct zynqmp_disp_layer *layer,
1815 u32 **drm_fmts, unsigned int *num_fmts)
1817 *drm_fmts = layer->drm_fmts;
1818 *num_fmts = layer->num_fmts;
1822 * zynqmp_disp_layer_enable - Enable the layer
1823 * @disp: Display subsystem
1824 * @layer: layer to esable
1825 * @mode: operation mode
1827 * Enable the layer @layer.
1829 * Return: 0 on success, otherwise error code.
1831 static int zynqmp_disp_layer_enable(struct zynqmp_disp *disp,
1832 struct zynqmp_disp_layer *layer,
1833 enum zynqmp_disp_layer_mode mode)
1835 struct device *dev = disp->dev;
1836 struct dma_async_tx_descriptor *desc;
1837 enum dma_ctrl_flags flags;
1840 if (layer->enabled && layer->mode != mode) {
1841 dev_err(dev, "layer is already enabled in different mode\n");
1845 zynqmp_disp_av_buf_enable_vid(&disp->av_buf, layer, mode);
1846 zynqmp_disp_blend_layer_enable(&disp->blend, layer);
1848 layer->enabled = true;
1851 if (mode == ZYNQMP_DISP_LAYER_LIVE)
1854 for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++) {
1855 struct zynqmp_disp_layer_dma *dma = &layer->dma[i];
1857 if (dma->chan && dma->is_active) {
1858 flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
1859 desc = dmaengine_prep_interleaved_dma(dma->chan,
1862 dev_err(dev, "failed to prep DMA descriptor\n");
1866 dmaengine_submit(desc);
1867 dma_async_issue_pending(dma->chan);
1875 * zynqmp_disp_layer_disable - Disable the layer
1876 * @disp: Display subsystem
1877 * @layer: layer to disable
1878 * @mode: operation mode
1880 * Disable the layer @layer.
1882 * Return: 0 on success, or -EBUSY if the layer is in different mode.
1884 static int zynqmp_disp_layer_disable(struct zynqmp_disp *disp,
1885 struct zynqmp_disp_layer *layer,
1886 enum zynqmp_disp_layer_mode mode)
1888 struct device *dev = disp->dev;
1891 if (layer->mode != mode) {
1892 dev_err(dev, "the layer is operating in different mode\n");
1896 for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
1897 if (layer->dma[i].chan && layer->dma[i].is_active)
1898 dmaengine_terminate_sync(layer->dma[i].chan);
1900 zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
1901 zynqmp_disp_blend_layer_disable(&disp->blend, layer);
1902 layer->enabled = false;
1908 * zynqmp_disp_layer_request_dma - Request DMA channels for a layer
1909 * @disp: Display subsystem
1910 * @layer: layer to request DMA channels
1911 * @name: identifier string for layer type
1913 * Request DMA engine channels for corresponding layer.
1915 * Return: 0 on success, or err value from of_dma_request_slave_channel().
1918 zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
1919 struct zynqmp_disp_layer *layer, const char *name)
1921 struct zynqmp_disp_layer_dma *dma;
1925 for (i = 0; i < layer->num_chan; i++) {
1928 dma = &layer->dma[i];
1929 snprintf(temp, sizeof(temp), "%s%d", name, i);
1930 dma->chan = of_dma_request_slave_channel(layer->of_node,
1932 if (IS_ERR(dma->chan)) {
1933 dev_err(disp->dev, "failed to request dma channel\n");
1934 ret = PTR_ERR(dma->chan);
1944 * zynqmp_disp_layer_release_dma - Release DMA channels for a layer
1945 * @disp: Display subsystem
1946 * @layer: layer to release DMA channels
1948 * Release the dma channels associated with @layer.
1950 static void zynqmp_disp_layer_release_dma(struct zynqmp_disp *disp,
1951 struct zynqmp_disp_layer *layer)
1955 for (i = 0; i < layer->num_chan; i++) {
1956 if (layer->dma[i].chan) {
1957 /* Make sure the channel is terminated before release */
1958 dmaengine_terminate_all(layer->dma[i].chan);
1959 dma_release_channel(layer->dma[i].chan);
1965 * zynqmp_disp_layer_is_live - if any layer is live
1966 * @disp: Display subsystem
1968 * Return: true if any layer is live
1970 static bool zynqmp_disp_layer_is_live(struct zynqmp_disp *disp)
1974 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
1975 if (disp->layers[i].enabled &&
1976 disp->layers[i].mode == ZYNQMP_DISP_LAYER_LIVE)
1984 * zynqmp_disp_layer_is_enabled - if any layer is enabled
1985 * @disp: Display subsystem
1987 * Return: true if any layer is enabled
1989 static bool zynqmp_disp_layer_is_enabled(struct zynqmp_disp *disp)
1993 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
1994 if (disp->layers[i].enabled)
2001 * zynqmp_disp_layer_destroy - Destroy all layers
2002 * @disp: Display subsystem
2004 * Destroy all layers.
2006 static void zynqmp_disp_layer_destroy(struct zynqmp_disp *disp)
2010 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2011 zynqmp_disp_layer_release_dma(disp, &disp->layers[i]);
2012 if (disp->layers[i].of_node)
2013 of_node_put(disp->layers[i].of_node);
2018 * zynqmp_disp_layer_create - Create all layers
2019 * @disp: Display subsystem
2021 * Create all layers.
2023 * Return: 0 on success, otherwise error code from failed function
2025 static int zynqmp_disp_layer_create(struct zynqmp_disp *disp)
2027 struct zynqmp_disp_layer *layer;
2029 int num_chans[ZYNQMP_DISP_NUM_LAYERS] = { 3, 1 };
2030 const char * const dma_name[] = { "vid", "gfx" };
2033 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2036 layer = &disp->layers[i];
2038 layer->offset = i * 4;
2039 layer->other = &disp->layers[!i];
2040 layer->num_chan = num_chans[i];
2041 snprintf(temp, sizeof(temp), "%s-layer", dma_name[i]);
2042 layer->of_node = of_get_child_by_name(disp->dev->of_node, temp);
2043 if (!layer->of_node)
2045 ret = zynqmp_disp_layer_request_dma(disp, layer, dma_name[i]);
2054 zynqmp_disp_layer_destroy(disp);
2059 * ZynqMP Display internal functions
2063 * Output format enumeration.
2064 * The ID should be aligned with blend_output_fmts.
2065 * The string should be aligned with how zynqmp_dp_set_color() decodes.
2067 static struct drm_prop_enum_list zynqmp_disp_color_enum[] = {
2075 * zynqmp_disp_set_output_fmt - Set the output format
2076 * @disp: Display subsystem
2077 * @id: the format ID. Refer to zynqmp_disp_color_enum[].
2079 * This function sets the output format of the display / blender as well as
2080 * the format of DP controller. The @id should be aligned with
2081 * zynqmp_disp_color_enum.
2084 zynqmp_disp_set_output_fmt(struct zynqmp_disp *disp, unsigned int id)
2086 const struct zynqmp_disp_fmt *fmt = &blend_output_fmts[id];
2088 zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[id].name);
2089 zynqmp_disp_blend_set_output_fmt(&disp->blend, fmt->disp_fmt);
2093 * zynqmp_disp_set_bg_color - Set the background color
2094 * @disp: Display subsystem
2095 * @c0: color component 0
2096 * @c1: color component 1
2097 * @c2: color component 2
2099 * Set the background color with given color components (@c0, @c1, @c2).
2101 static void zynqmp_disp_set_bg_color(struct zynqmp_disp *disp,
2102 u32 c0, u32 c1, u32 c2)
2104 zynqmp_disp_blend_set_bg_color(&disp->blend, c0, c1, c2);
2108 * zynqmp_disp_set_alpha - Set the alpha value
2109 * @disp: Display subsystem
2110 * @alpha: alpha value to set
2112 * Set the alpha value for blending.
2114 static void zynqmp_disp_set_alpha(struct zynqmp_disp *disp, u32 alpha)
2116 disp->alpha = alpha;
2117 zynqmp_disp_blend_set_alpha(&disp->blend, alpha);
2121 * zynqmp_disp_get_alpha - Get the alpha value
2122 * @disp: Display subsystem
2124 * Get the alpha value for blending.
2126 * Return: current alpha value.
2128 static u32 zynqmp_disp_get_alpha(struct zynqmp_disp *disp)
2134 * zynqmp_disp_set_g_alpha - Enable/disable the global alpha blending
2135 * @disp: Display subsystem
2136 * @enable: flag to enable or disable alpha blending
2138 * Set the alpha value for blending.
2140 static void zynqmp_disp_set_g_alpha(struct zynqmp_disp *disp, bool enable)
2142 disp->alpha_en = enable;
2143 zynqmp_disp_blend_enable_alpha(&disp->blend, enable);
2147 * zynqmp_disp_get_g_alpha - Get the global alpha status
2148 * @disp: Display subsystem
2150 * Get the global alpha statue.
2152 * Return: true if global alpha is enabled, or false.
2154 static bool zynqmp_disp_get_g_alpha(struct zynqmp_disp *disp)
2156 return disp->alpha_en;
2160 * zynqmp_disp_enable - Enable the Display subsystem
2161 * @disp: Display subsystem
2163 * Enable the Display subsystem.
2165 static void zynqmp_disp_enable(struct zynqmp_disp *disp)
2172 zynqmp_disp_av_buf_enable(&disp->av_buf);
2173 /* Choose clock source based on the DT clock handle */
2174 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, !!disp->_ps_pclk);
2175 zynqmp_disp_av_buf_set_aud_clock_src(&disp->av_buf, !!disp->_ps_audclk);
2176 live = zynqmp_disp_layer_is_live(disp);
2177 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, !live);
2178 zynqmp_disp_av_buf_enable_buf(&disp->av_buf);
2179 zynqmp_disp_av_buf_enable_aud(&disp->av_buf);
2180 zynqmp_disp_aud_init(&disp->aud);
2181 disp->enabled = true;
2185 * zynqmp_disp_disable - Disable the Display subsystem
2186 * @disp: Display subsystem
2187 * @force: flag to disable forcefully
2189 * Disable the Display subsystem.
2191 static void zynqmp_disp_disable(struct zynqmp_disp *disp, bool force)
2193 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2195 if (!force && (!disp->enabled || zynqmp_disp_layer_is_enabled(disp)))
2198 zynqmp_disp_aud_deinit(&disp->aud);
2199 zynqmp_disp_av_buf_disable_aud(&disp->av_buf);
2200 zynqmp_disp_av_buf_disable_buf(&disp->av_buf);
2201 zynqmp_disp_av_buf_disable(&disp->av_buf);
2203 /* Mark the flip is done as crtc is disabled anyway */
2204 if (crtc->state->event) {
2205 complete_all(crtc->state->event->base.completion);
2206 crtc->state->event = NULL;
2209 disp->enabled = false;
2213 * zynqmp_disp_init - Initialize the Display subsystem states
2214 * @disp: Display subsystem
2216 * Some states are not initialized as desired. For example, the output select
2217 * register resets to the live source. This function is to initialize
2218 * some register states as desired.
2220 static void zynqmp_disp_init(struct zynqmp_disp *disp)
2222 struct zynqmp_disp_layer *layer;
2225 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2226 layer = &disp->layers[i];
2227 zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
2232 * ZynqMP Display external functions for zynqmp_dp
2236 * zynqmp_disp_handle_vblank - Handle the vblank event
2237 * @disp: Display subsystem
2239 * This function handles the vblank interrupt, and sends an event to
2240 * CRTC object. This will be called by the DP vblank interrupt handler.
2242 void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
2244 struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
2246 drm_crtc_handle_vblank(crtc);
2250 * zynqmp_disp_get_apb_clk_rate - Get the current APB clock rate
2251 * @disp: Display subsystem
2253 * Return: the current APB clock rate.
2255 unsigned int zynqmp_disp_get_apb_clk_rate(struct zynqmp_disp *disp)
2257 return clk_get_rate(disp->aclk);
2261 * zynqmp_disp_aud_enabled - If the audio is enabled
2262 * @disp: Display subsystem
2264 * Return if the audio is enabled depending on the audio clock.
2266 * Return: true if audio is enabled, or false.
2268 bool zynqmp_disp_aud_enabled(struct zynqmp_disp *disp)
2270 return !!disp->audclk;
2274 * zynqmp_disp_get_aud_clk_rate - Get the current audio clock rate
2275 * @disp: Display subsystem
2277 * Return: the current audio clock rate.
2279 unsigned int zynqmp_disp_get_aud_clk_rate(struct zynqmp_disp *disp)
2281 if (zynqmp_disp_aud_enabled(disp))
2283 return clk_get_rate(disp->aclk);
2287 * zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
2288 * @disp: Display subsystem
2290 * Return: the crtc mask of the zyqnmp_disp CRTC.
2292 uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp)
2294 return drm_crtc_mask(&disp->xlnx_crtc.crtc);
2298 * Xlnx bridge functions
2301 static inline struct zynqmp_disp_layer
2302 *bridge_to_layer(struct xlnx_bridge *bridge)
2304 return container_of(bridge, struct zynqmp_disp_layer, bridge);
2307 static int zynqmp_disp_bridge_enable(struct xlnx_bridge *bridge)
2309 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2310 struct zynqmp_disp *disp = layer->disp;
2313 if (!disp->_pl_pclk) {
2314 dev_err(disp->dev, "PL clock is required for live\n");
2318 ret = zynqmp_disp_layer_check_size(disp, layer, layer->w, layer->h);
2322 zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2323 zynqmp_disp_set_alpha(disp, disp->alpha);
2324 ret = zynqmp_disp_layer_enable(layer->disp, layer,
2325 ZYNQMP_DISP_LAYER_LIVE);
2329 if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2330 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2331 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2334 if (zynqmp_disp_av_buf_vid_timing_src_is_int(&disp->av_buf) ||
2335 zynqmp_disp_av_buf_vid_clock_src_is_ps(&disp->av_buf)) {
2337 "Disabling the pipeline to change the clk/timing src");
2338 zynqmp_disp_disable(disp, true);
2339 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, false);
2340 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, false);
2343 zynqmp_disp_enable(disp);
2348 static void zynqmp_disp_bridge_disable(struct xlnx_bridge *bridge)
2350 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2351 struct zynqmp_disp *disp = layer->disp;
2353 zynqmp_disp_disable(disp, false);
2355 zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_LIVE);
2356 if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2357 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2359 if (!zynqmp_disp_layer_is_live(disp)) {
2361 "Disabling the pipeline to change the clk/timing src");
2362 zynqmp_disp_disable(disp, true);
2363 zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, true);
2364 zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, true);
2365 if (zynqmp_disp_layer_is_enabled(disp))
2366 zynqmp_disp_enable(disp);
2370 static int zynqmp_disp_bridge_set_input(struct xlnx_bridge *bridge,
2371 u32 width, u32 height, u32 bus_fmt)
2373 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2376 ret = zynqmp_disp_layer_check_size(layer->disp, layer, width, height);
2380 ret = zynqmp_disp_layer_set_live_fmt(layer->disp, layer, bus_fmt);
2382 dev_err(layer->disp->dev, "failed to set live fmt\n");
2387 static int zynqmp_disp_bridge_get_input_fmts(struct xlnx_bridge *bridge,
2388 const u32 **fmts, u32 *count)
2390 struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
2392 *fmts = layer->bus_fmts;
2393 *count = layer->num_bus_fmts;
2399 * DRM plane functions
2402 static inline struct zynqmp_disp_layer *plane_to_layer(struct drm_plane *plane)
2404 return container_of(plane, struct zynqmp_disp_layer, plane);
2407 static int zynqmp_disp_plane_enable(struct drm_plane *plane)
2409 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2410 struct zynqmp_disp *disp = layer->disp;
2413 zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
2414 zynqmp_disp_set_alpha(disp, disp->alpha);
2415 ret = zynqmp_disp_layer_enable(layer->disp, layer,
2416 ZYNQMP_DISP_LAYER_NONLIVE);
2420 if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
2421 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2422 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2428 static int zynqmp_disp_plane_disable(struct drm_plane *plane)
2430 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2431 struct zynqmp_disp *disp = layer->disp;
2433 zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_NONLIVE);
2434 if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
2435 zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
2440 static int zynqmp_disp_plane_mode_set(struct drm_plane *plane,
2441 struct drm_framebuffer *fb,
2442 int crtc_x, int crtc_y,
2443 unsigned int crtc_w, unsigned int crtc_h,
2444 u32 src_x, u32 src_y,
2445 u32 src_w, u32 src_h)
2447 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2448 const struct drm_format_info *info = fb->format;
2449 struct drm_format_name_buf format_name;
2450 struct device *dev = layer->disp->dev;
2456 dev_err(dev, "unsupported framebuffer format %s\n",
2457 drm_get_format_name(info->format, &format_name));
2461 ret = zynqmp_disp_layer_check_size(layer->disp, layer, src_w, src_h);
2465 for (i = 0; i < info->num_planes; i++) {
2466 unsigned int width = src_w / (i ? info->hsub : 1);
2467 unsigned int height = src_h / (i ? info->vsub : 1);
2470 paddr = drm_fb_cma_get_gem_addr(fb, plane->state, i);
2472 dev_err(dev, "failed to get a paddr\n");
2476 layer->dma[i].xt.numf = height;
2477 width_bytes = drm_format_plane_width_bytes(info, i, width);
2478 layer->dma[i].sgl[0].size = width_bytes;
2479 layer->dma[i].sgl[0].icg = fb->pitches[i] -
2480 layer->dma[i].sgl[0].size;
2481 layer->dma[i].xt.src_start = paddr;
2482 layer->dma[i].xt.frame_size = 1;
2483 layer->dma[i].xt.dir = DMA_MEM_TO_DEV;
2484 layer->dma[i].xt.src_sgl = true;
2485 layer->dma[i].xt.dst_sgl = false;
2486 layer->dma[i].is_active = true;
2489 for (; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
2490 layer->dma[i].is_active = false;
2492 ret = zynqmp_disp_layer_set_fmt(layer->disp, layer, info->format);
2494 dev_err(dev, "failed to set dp_sub layer fmt\n");
2499 static void zynqmp_disp_plane_destroy(struct drm_plane *plane)
2501 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2503 xlnx_bridge_unregister(&layer->bridge);
2504 drm_plane_cleanup(plane);
2508 zynqmp_disp_plane_atomic_set_property(struct drm_plane *plane,
2509 struct drm_plane_state *state,
2510 struct drm_property *property, u64 val)
2512 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2513 struct zynqmp_disp *disp = layer->disp;
2516 if (property == disp->g_alpha_prop)
2517 zynqmp_disp_set_alpha(disp, val);
2518 else if (property == disp->g_alpha_en_prop)
2519 zynqmp_disp_set_g_alpha(disp, val);
2520 else if (property == disp->tpg_prop)
2521 ret = zynqmp_disp_layer_set_tpg(disp, layer, val);
2529 zynqmp_disp_plane_atomic_get_property(struct drm_plane *plane,
2530 const struct drm_plane_state *state,
2531 struct drm_property *property,
2534 struct zynqmp_disp_layer *layer = plane_to_layer(plane);
2535 struct zynqmp_disp *disp = layer->disp;
2538 if (property == disp->g_alpha_prop)
2539 *val = zynqmp_disp_get_alpha(disp);
2540 else if (property == disp->g_alpha_en_prop)
2541 *val = zynqmp_disp_get_g_alpha(disp);
2542 else if (property == disp->tpg_prop)
2543 *val = zynqmp_disp_layer_get_tpg(disp, layer);
2550 static struct drm_plane_funcs zynqmp_disp_plane_funcs = {
2551 .update_plane = drm_atomic_helper_update_plane,
2552 .disable_plane = drm_atomic_helper_disable_plane,
2553 .atomic_set_property = zynqmp_disp_plane_atomic_set_property,
2554 .atomic_get_property = zynqmp_disp_plane_atomic_get_property,
2555 .destroy = zynqmp_disp_plane_destroy,
2556 .reset = drm_atomic_helper_plane_reset,
2557 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
2558 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
2562 zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
2563 struct drm_plane_state *old_state)
2567 if (!plane->state->crtc || !plane->state->fb)
2570 if (old_state->fb &&
2571 old_state->fb->format->format != plane->state->fb->format->format)
2572 zynqmp_disp_plane_disable(plane);
2574 ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
2575 plane->state->crtc_x,
2576 plane->state->crtc_y,
2577 plane->state->crtc_w,
2578 plane->state->crtc_h,
2579 plane->state->src_x >> 16,
2580 plane->state->src_y >> 16,
2581 plane->state->src_w >> 16,
2582 plane->state->src_h >> 16);
2586 zynqmp_disp_plane_enable(plane);
2590 zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
2591 struct drm_plane_state *old_state)
2593 zynqmp_disp_plane_disable(plane);
2596 static const struct drm_plane_helper_funcs zynqmp_disp_plane_helper_funcs = {
2597 .atomic_update = zynqmp_disp_plane_atomic_update,
2598 .atomic_disable = zynqmp_disp_plane_atomic_disable,
2601 static int zynqmp_disp_create_plane(struct zynqmp_disp *disp)
2603 struct zynqmp_disp_layer *layer;
2606 unsigned int num_fmts = 0;
2607 enum drm_plane_type type;
2610 /* graphics layer is primary, and video layer is overaly */
2611 type = DRM_PLANE_TYPE_OVERLAY;
2612 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2613 layer = &disp->layers[i];
2614 zynqmp_disp_layer_get_fmts(disp, layer, &fmts, &num_fmts);
2615 ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
2616 &zynqmp_disp_plane_funcs, fmts,
2617 num_fmts, NULL, type, NULL);
2620 drm_plane_helper_add(&layer->plane,
2621 &zynqmp_disp_plane_helper_funcs);
2622 type = DRM_PLANE_TYPE_PRIMARY;
2625 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
2626 layer = &disp->layers[i];
2627 layer->bridge.enable = &zynqmp_disp_bridge_enable;
2628 layer->bridge.disable = &zynqmp_disp_bridge_disable;
2629 layer->bridge.set_input = &zynqmp_disp_bridge_set_input;
2630 layer->bridge.get_input_fmts =
2631 &zynqmp_disp_bridge_get_input_fmts;
2632 layer->bridge.of_node = layer->of_node;
2633 xlnx_bridge_register(&layer->bridge);
2636 /* Attach properties to each layers */
2637 drm_object_attach_property(&layer->plane.base, disp->g_alpha_prop,
2638 ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX);
2639 disp->alpha = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
2640 /* Enable the global alpha as default */
2641 drm_object_attach_property(&layer->plane.base, disp->g_alpha_en_prop,
2643 disp->alpha_en = true;
2645 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2646 drm_object_attach_property(&layer->plane.base, disp->tpg_prop, false);
2652 drm_plane_cleanup(&disp->layers[0].plane);
2656 static void zynqmp_disp_destroy_plane(struct zynqmp_disp *disp)
2660 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2661 zynqmp_disp_plane_destroy(&disp->layers[i].plane);
2665 * Xlnx crtc functions
2668 static inline struct zynqmp_disp *xlnx_crtc_to_disp(struct xlnx_crtc *xlnx_crtc)
2670 return container_of(xlnx_crtc, struct zynqmp_disp, xlnx_crtc);
2673 static int zynqmp_disp_get_max_width(struct xlnx_crtc *xlnx_crtc)
2675 return ZYNQMP_DISP_MAX_WIDTH;
2678 static int zynqmp_disp_get_max_height(struct xlnx_crtc *xlnx_crtc)
2680 return ZYNQMP_DISP_MAX_HEIGHT;
2683 static uint32_t zynqmp_disp_get_format(struct xlnx_crtc *xlnx_crtc)
2685 struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2687 return disp->layers[ZYNQMP_DISP_LAYER_GFX].fmt->drm_fmt;
2690 static unsigned int zynqmp_disp_get_align(struct xlnx_crtc *xlnx_crtc)
2692 struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
2693 struct zynqmp_disp_layer *layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
2695 return 1 << layer->dma->chan->device->copy_align;
2698 static u64 zynqmp_disp_get_dma_mask(struct xlnx_crtc *xlnx_crtc)
2700 return DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT);
2704 * DRM crtc functions
2707 static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
2709 struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
2711 return xlnx_crtc_to_disp(xlnx_crtc);
2714 static int zynqmp_disp_crtc_mode_set(struct drm_crtc *crtc,
2715 struct drm_display_mode *mode,
2716 struct drm_display_mode *adjusted_mode,
2718 struct drm_framebuffer *old_fb)
2720 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2725 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2726 ret = clk_set_rate(disp->pclk, adjusted_mode->clock * 1000);
2728 dev_err(disp->dev, "failed to set a pixel clock\n");
2732 rate = clk_get_rate(disp->pclk);
2733 diff = rate - adjusted_mode->clock * 1000;
2734 if (abs(diff) > (adjusted_mode->clock * 1000) / 20) {
2735 dev_info(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2736 adjusted_mode->clock, rate);
2738 dev_dbg(disp->dev, "request pixel rate: %d actual rate: %lu\n",
2739 adjusted_mode->clock, rate);
2742 /* The timing register should be programmed always */
2743 zynqmp_dp_encoder_mode_set_stream(disp->dpsub->dp, adjusted_mode);
2749 zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
2750 struct drm_crtc_state *old_crtc_state)
2752 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2753 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
2756 zynqmp_disp_crtc_mode_set(crtc, &crtc->state->mode,
2757 adjusted_mode, crtc->x, crtc->y, NULL);
2759 pm_runtime_get_sync(disp->dev);
2760 ret = zynqmp_disp_clk_enable(disp->pclk, &disp->pclk_en);
2762 dev_err(disp->dev, "failed to enable a pixel clock\n");
2765 zynqmp_disp_set_output_fmt(disp, disp->color);
2766 zynqmp_disp_set_bg_color(disp, disp->bg_c0, disp->bg_c1, disp->bg_c2);
2767 zynqmp_disp_enable(disp);
2768 /* Delay of 3 vblank intervals for timing gen to be stable */
2769 vrefresh = (adjusted_mode->clock * 1000) /
2770 (adjusted_mode->vtotal * adjusted_mode->htotal);
2771 msleep(3 * 1000 / vrefresh);
2775 zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
2776 struct drm_crtc_state *old_crtc_state)
2778 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2780 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
2781 zynqmp_disp_plane_disable(crtc->primary);
2782 zynqmp_disp_disable(disp, true);
2783 pm_runtime_put_sync(disp->dev);
2786 static int zynqmp_disp_crtc_atomic_check(struct drm_crtc *crtc,
2787 struct drm_crtc_state *state)
2789 return drm_atomic_add_affected_planes(state->state, crtc);
2793 zynqmp_disp_crtc_atomic_begin(struct drm_crtc *crtc,
2794 struct drm_crtc_state *old_crtc_state)
2796 /* Don't rely on vblank when disabling crtc */
2797 spin_lock_irq(&crtc->dev->event_lock);
2798 if (crtc->primary->state->fb && crtc->state->event) {
2799 /* Consume the flip_done event from atomic helper */
2800 crtc->state->event->pipe = drm_crtc_index(crtc);
2801 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
2802 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
2803 crtc->state->event = NULL;
2805 spin_unlock_irq(&crtc->dev->event_lock);
2808 static struct drm_crtc_helper_funcs zynqmp_disp_crtc_helper_funcs = {
2809 .atomic_enable = zynqmp_disp_crtc_atomic_enable,
2810 .atomic_disable = zynqmp_disp_crtc_atomic_disable,
2811 .atomic_check = zynqmp_disp_crtc_atomic_check,
2812 .atomic_begin = zynqmp_disp_crtc_atomic_begin,
2815 static void zynqmp_disp_crtc_destroy(struct drm_crtc *crtc)
2817 zynqmp_disp_crtc_atomic_disable(crtc, NULL);
2818 drm_crtc_cleanup(crtc);
2821 static int zynqmp_disp_crtc_enable_vblank(struct drm_crtc *crtc)
2823 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2825 zynqmp_dp_enable_vblank(disp->dpsub->dp);
2830 static void zynqmp_disp_crtc_disable_vblank(struct drm_crtc *crtc)
2832 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2834 zynqmp_dp_disable_vblank(disp->dpsub->dp);
2838 zynqmp_disp_crtc_atomic_set_property(struct drm_crtc *crtc,
2839 struct drm_crtc_state *state,
2840 struct drm_property *property,
2843 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2846 * CRTC prop values are just stored here and applied when CRTC gets
2849 if (property == disp->color_prop)
2851 else if (property == disp->bg_c0_prop)
2853 else if (property == disp->bg_c1_prop)
2855 else if (property == disp->bg_c2_prop)
2864 zynqmp_disp_crtc_atomic_get_property(struct drm_crtc *crtc,
2865 const struct drm_crtc_state *state,
2866 struct drm_property *property,
2869 struct zynqmp_disp *disp = crtc_to_disp(crtc);
2871 if (property == disp->color_prop)
2873 else if (property == disp->bg_c0_prop)
2875 else if (property == disp->bg_c1_prop)
2877 else if (property == disp->bg_c2_prop)
2885 static struct drm_crtc_funcs zynqmp_disp_crtc_funcs = {
2886 .destroy = zynqmp_disp_crtc_destroy,
2887 .set_config = drm_atomic_helper_set_config,
2888 .page_flip = drm_atomic_helper_page_flip,
2889 .atomic_set_property = zynqmp_disp_crtc_atomic_set_property,
2890 .atomic_get_property = zynqmp_disp_crtc_atomic_get_property,
2891 .reset = drm_atomic_helper_crtc_reset,
2892 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
2893 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
2894 .enable_vblank = zynqmp_disp_crtc_enable_vblank,
2895 .disable_vblank = zynqmp_disp_crtc_disable_vblank,
2898 static void zynqmp_disp_create_crtc(struct zynqmp_disp *disp)
2900 struct drm_plane *plane = &disp->layers[ZYNQMP_DISP_LAYER_GFX].plane;
2901 struct drm_mode_object *obj = &disp->xlnx_crtc.crtc.base;
2904 ret = drm_crtc_init_with_planes(disp->drm, &disp->xlnx_crtc.crtc, plane,
2905 NULL, &zynqmp_disp_crtc_funcs, NULL);
2906 drm_crtc_helper_add(&disp->xlnx_crtc.crtc,
2907 &zynqmp_disp_crtc_helper_funcs);
2908 drm_object_attach_property(obj, disp->color_prop, 0);
2909 zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[0].name);
2910 drm_object_attach_property(obj, disp->bg_c0_prop, 0);
2911 drm_object_attach_property(obj, disp->bg_c1_prop, 0);
2912 drm_object_attach_property(obj, disp->bg_c2_prop, 0);
2914 disp->xlnx_crtc.get_max_width = &zynqmp_disp_get_max_width;
2915 disp->xlnx_crtc.get_max_height = &zynqmp_disp_get_max_height;
2916 disp->xlnx_crtc.get_format = &zynqmp_disp_get_format;
2917 disp->xlnx_crtc.get_align = &zynqmp_disp_get_align;
2918 disp->xlnx_crtc.get_dma_mask = &zynqmp_disp_get_dma_mask;
2919 xlnx_crtc_register(disp->drm, &disp->xlnx_crtc);
2922 static void zynqmp_disp_destroy_crtc(struct zynqmp_disp *disp)
2924 xlnx_crtc_unregister(disp->drm, &disp->xlnx_crtc);
2925 zynqmp_disp_crtc_destroy(&disp->xlnx_crtc.crtc);
2928 static void zynqmp_disp_map_crtc_to_plane(struct zynqmp_disp *disp)
2930 u32 possible_crtcs = drm_crtc_mask(&disp->xlnx_crtc.crtc);
2933 for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
2934 disp->layers[i].plane.possible_crtcs = possible_crtcs;
2938 * Component functions
2941 int zynqmp_disp_bind(struct device *dev, struct device *master, void *data)
2943 struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
2944 struct zynqmp_disp *disp = dpsub->disp;
2945 struct drm_device *drm = data;
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,
2956 num = ARRAY_SIZE(zynqmp_disp_color_enum);
2957 disp->color_prop = drm_property_create_enum(drm, 0,
2959 zynqmp_disp_color_enum,
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");
2967 ret = zynqmp_disp_create_plane(disp);
2970 zynqmp_disp_create_crtc(disp);
2971 zynqmp_disp_map_crtc_to_plane(disp);
2976 void zynqmp_disp_unbind(struct device *dev, struct device *master, void *data)
2978 struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
2979 struct zynqmp_disp *disp = dpsub->disp;
2981 zynqmp_disp_destroy_crtc(disp);
2982 zynqmp_disp_destroy_plane(disp);
2983 drm_property_destroy(disp->drm, disp->bg_c2_prop);
2984 drm_property_destroy(disp->drm, disp->bg_c1_prop);
2985 drm_property_destroy(disp->drm, disp->bg_c0_prop);
2986 drm_property_destroy(disp->drm, disp->color_prop);
2987 drm_property_destroy(disp->drm, disp->g_alpha_en_prop);
2988 drm_property_destroy(disp->drm, disp->g_alpha_prop);
2992 * Platform initialization functions
2995 static int zynqmp_disp_enumerate_fmts(struct zynqmp_disp *disp)
2997 struct zynqmp_disp_layer *layer;
2999 u32 i, size, num_bus_fmts;
3001 num_bus_fmts = ARRAY_SIZE(av_buf_live_fmts);
3002 bus_fmts = devm_kzalloc(disp->dev, sizeof(*bus_fmts) * num_bus_fmts,
3006 for (i = 0; i < num_bus_fmts; i++)
3007 bus_fmts[i] = av_buf_live_fmts[i].bus_fmt;
3009 layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
3010 layer->num_bus_fmts = num_bus_fmts;
3011 layer->bus_fmts = bus_fmts;
3012 size = ARRAY_SIZE(av_buf_vid_fmts);
3013 layer->num_fmts = size;
3014 layer->drm_fmts = devm_kzalloc(disp->dev,
3015 sizeof(*layer->drm_fmts) * size,
3017 if (!layer->drm_fmts)
3019 for (i = 0; i < layer->num_fmts; i++)
3020 layer->drm_fmts[i] = av_buf_vid_fmts[i].drm_fmt;
3021 layer->fmt = &av_buf_vid_fmts[ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV];
3023 layer = &disp->layers[ZYNQMP_DISP_LAYER_GFX];
3024 layer->num_bus_fmts = num_bus_fmts;
3025 layer->bus_fmts = bus_fmts;
3026 size = ARRAY_SIZE(av_buf_gfx_fmts);
3027 layer->num_fmts = size;
3028 layer->drm_fmts = devm_kzalloc(disp->dev,
3029 sizeof(*layer->drm_fmts) * size,
3031 if (!layer->drm_fmts)
3034 for (i = 0; i < layer->num_fmts; i++)
3035 layer->drm_fmts[i] = av_buf_gfx_fmts[i].drm_fmt;
3036 layer->fmt = &av_buf_gfx_fmts[ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565];
3041 int zynqmp_disp_probe(struct platform_device *pdev)
3043 struct zynqmp_dpsub *dpsub;
3044 struct zynqmp_disp *disp;
3045 struct resource *res;
3048 disp = devm_kzalloc(&pdev->dev, sizeof(*disp), GFP_KERNEL);
3051 disp->dev = &pdev->dev;
3053 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
3054 disp->blend.base = devm_ioremap_resource(&pdev->dev, res);
3055 if (IS_ERR(disp->blend.base))
3056 return PTR_ERR(disp->blend.base);
3058 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
3059 disp->av_buf.base = devm_ioremap_resource(&pdev->dev, res);
3060 if (IS_ERR(disp->av_buf.base))
3061 return PTR_ERR(disp->av_buf.base);
3063 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
3064 disp->aud.base = devm_ioremap_resource(&pdev->dev, res);
3065 if (IS_ERR(disp->aud.base))
3066 return PTR_ERR(disp->aud.base);
3068 dpsub = platform_get_drvdata(pdev);
3070 disp->dpsub = dpsub;
3072 ret = zynqmp_disp_enumerate_fmts(disp);
3076 /* Try the live PL video clock */
3077 disp->_pl_pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk");
3078 if (!IS_ERR(disp->_pl_pclk)) {
3079 disp->pclk = disp->_pl_pclk;
3080 ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3084 } else if (PTR_ERR(disp->_pl_pclk) == -EPROBE_DEFER) {
3085 return PTR_ERR(disp->_pl_pclk);
3088 /* If the live PL video clock is not valid, fall back to PS clock */
3090 disp->_ps_pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in");
3091 if (IS_ERR(disp->_ps_pclk)) {
3092 dev_err(disp->dev, "failed to init any video clock\n");
3093 return PTR_ERR(disp->_ps_pclk);
3095 disp->pclk = disp->_ps_pclk;
3096 ret = zynqmp_disp_clk_enable_disable(disp->pclk,
3099 dev_err(disp->dev, "failed to init any video clock\n");
3104 disp->aclk = devm_clk_get(disp->dev, "dp_apb_clk");
3105 if (IS_ERR(disp->aclk))
3106 return PTR_ERR(disp->aclk);
3107 ret = zynqmp_disp_clk_enable(disp->aclk, &disp->aclk_en);
3109 dev_err(disp->dev, "failed to enable the APB clk\n");
3113 /* Try the live PL audio clock */
3114 disp->_pl_audclk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
3115 if (!IS_ERR(disp->_pl_audclk)) {
3116 disp->audclk = disp->_pl_audclk;
3117 ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3120 disp->audclk = NULL;
3123 /* If the live PL audio clock is not valid, fall back to PS clock */
3124 if (!disp->audclk) {
3125 disp->_ps_audclk = devm_clk_get(disp->dev, "dp_aud_clk");
3126 if (!IS_ERR(disp->_ps_audclk)) {
3127 disp->audclk = disp->_ps_audclk;
3128 ret = zynqmp_disp_clk_enable_disable(disp->audclk,
3131 disp->audclk = NULL;
3134 if (!disp->audclk) {
3136 "audio is disabled due to clock failure\n");
3140 ret = zynqmp_disp_layer_create(disp);
3144 zynqmp_disp_init(disp);
3149 zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3153 int zynqmp_disp_remove(struct platform_device *pdev)
3155 struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
3156 struct zynqmp_disp *disp = dpsub->disp;
3158 zynqmp_disp_layer_destroy(disp);
3160 zynqmp_disp_clk_disable(disp->audclk, &disp->audclk_en);
3161 zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
3162 zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);