2 * DisplayPort subsystem support for Xilinx DRM KMS
4 * Copyright (C) 2015 Xilinx, Inc.
6 * Author: Hyun Woo Kwon <hyunk@xilinx.com>
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <drm/drm_crtc.h>
20 #include <drm/drm_crtc_helper.h>
21 #include <drm/drm_fourcc.h>
23 #include <linux/debugfs.h>
24 #include <linux/device.h>
25 #include <linux/interrupt.h>
26 #include <linux/irqreturn.h>
27 #include <linux/list.h>
28 #include <linux/module.h>
29 #include <linux/mutex.h>
31 #include <linux/platform_device.h>
32 #include <linux/uaccess.h>
34 #include "xilinx_drm_dp_sub.h"
35 #include "xilinx_drm_drv.h"
37 /* Blender registers */
38 #define XILINX_DP_SUB_V_BLEND_BG_CLR_0 0x0
39 #define XILINX_DP_SUB_V_BLEND_BG_CLR_1 0x4
40 #define XILINX_DP_SUB_V_BLEND_BG_CLR_2 0x8
41 #define XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA 0xc
42 #define XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA_MASK 0x1fe
43 #define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT 0x14
44 #define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB 0x0
45 #define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR444 0x1
46 #define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR422 0x2
47 #define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YONLY 0x3
48 #define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_XVYCC 0x4
49 #define XILINX_DP_SUB_V_BLEND_OUTPUT_EN_DOWNSAMPLE BIT(4)
50 #define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL 0x18
51 #define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_EN_US BIT(0)
52 #define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_RGB BIT(1)
53 #define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_BYPASS BIT(8)
54 #define XILINX_DP_SUB_V_BLEND_NUM_COEFF 9
55 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF0 0x20
56 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF1 0x24
57 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF2 0x28
58 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF3 0x2c
59 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF4 0x30
60 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF5 0x34
61 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF6 0x38
62 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF7 0x3c
63 #define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF8 0x40
64 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF0 0x44
65 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF1 0x48
66 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF2 0x4c
67 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF3 0x50
68 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF4 0x54
69 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF5 0x58
70 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF6 0x5c
71 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF7 0x60
72 #define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF8 0x64
73 #define XILINX_DP_SUB_V_BLEND_NUM_OFFSET 3
74 #define XILINX_DP_SUB_V_BLEND_LUMA_IN1CSC_OFFSET 0x68
75 #define XILINX_DP_SUB_V_BLEND_CR_IN1CSC_OFFSET 0x6c
76 #define XILINX_DP_SUB_V_BLEND_CB_IN1CSC_OFFSET 0x70
77 #define XILINX_DP_SUB_V_BLEND_LUMA_OUTCSC_OFFSET 0x74
78 #define XILINX_DP_SUB_V_BLEND_CR_OUTCSC_OFFSET 0x78
79 #define XILINX_DP_SUB_V_BLEND_CB_OUTCSC_OFFSET 0x7c
80 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF0 0x80
81 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF1 0x84
82 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF2 0x88
83 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF3 0x8c
84 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF4 0x90
85 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF5 0x94
86 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF6 0x98
87 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF7 0x9c
88 #define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF8 0xa0
89 #define XILINX_DP_SUB_V_BLEND_LUMA_IN2CSC_OFFSET 0xa4
90 #define XILINX_DP_SUB_V_BLEND_CR_IN2CSC_OFFSET 0xa8
91 #define XILINX_DP_SUB_V_BLEND_CB_IN2CSC_OFFSET 0xac
92 #define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_ENABLE 0x1d0
93 #define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_COMP1 0x1d4
94 #define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_COMP2 0x1d8
95 #define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_COMP3 0x1dc
97 /* AV buffer manager registers */
98 #define XILINX_DP_SUB_AV_BUF_FMT 0x0
99 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_SHIFT 0
100 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_MASK (0x1f << 0)
101 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_UYVY (0 << 0)
102 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_VYUY (1 << 0)
103 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YVYU (2 << 0)
104 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUYV (3 << 0)
105 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16 (4 << 0)
106 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV24 (5 << 0)
107 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI (6 << 0)
108 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_MONO (7 << 0)
109 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2 (8 << 0)
110 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUV444 (9 << 0)
111 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888 (10 << 0)
112 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGBA8880 (11 << 0)
113 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888_10 (12 << 0)
114 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUV444_10 (13 << 0)
115 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2_10 (14 << 0)
116 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_10 (15 << 0)
117 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_10 (16 << 0)
118 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV24_10 (17 << 0)
119 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YONLY_10 (18 << 0)
120 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_420 (19 << 0)
121 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420 (20 << 0)
122 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2_420 (21 << 0)
123 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_420_10 (22 << 0)
124 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420_10 (23 << 0)
125 #define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2_420_10 (24 << 0)
126 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_SHIFT 8
127 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_MASK (0xf << 8)
128 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA8888 (0 << 8)
129 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_ABGR8888 (1 << 8)
130 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB888 (2 << 8)
131 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_BGR888 (3 << 8)
132 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA5551 (4 << 8)
133 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA4444 (5 << 8)
134 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB565 (6 << 8)
135 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_8BPP (7 << 8)
136 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_4BPP (8 << 8)
137 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_2BPP (9 << 8)
138 #define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_1BPP (10 << 8)
139 #define XILINX_DP_SUB_AV_BUF_NON_LIVE_LATENCY 0x8
140 #define XILINX_DP_SUB_AV_BUF_CHBUF 0x10
141 #define XILINX_DP_SUB_AV_BUF_CHBUF_EN BIT(0)
142 #define XILINX_DP_SUB_AV_BUF_CHBUF_FLUSH BIT(1)
143 #define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_SHIFT 2
144 #define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_MASK (0xf << 2)
145 #define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_MAX 0xf
146 #define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_AUD_MAX 0x3
147 #define XILINX_DP_SUB_AV_BUF_STATUS 0x28
148 #define XILINX_DP_SUB_AV_BUF_STC_CTRL 0x2c
149 #define XILINX_DP_SUB_AV_BUF_STC_CTRL_EN BIT(0)
150 #define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_SHIFT 1
151 #define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_EX_VSYNC 0
152 #define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_EX_VID 1
153 #define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_EX_AUD 2
154 #define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_INT_VSYNC 3
155 #define XILINX_DP_SUB_AV_BUF_STC_INIT_VALUE0 0x30
156 #define XILINX_DP_SUB_AV_BUF_STC_INIT_VALUE1 0x34
157 #define XILINX_DP_SUB_AV_BUF_STC_ADJ 0x38
158 #define XILINX_DP_SUB_AV_BUF_STC_VID_VSYNC_TS0 0x3c
159 #define XILINX_DP_SUB_AV_BUF_STC_VID_VSYNC_TS1 0x40
160 #define XILINX_DP_SUB_AV_BUF_STC_EXT_VSYNC_TS0 0x44
161 #define XILINX_DP_SUB_AV_BUF_STC_EXT_VSYNC_TS1 0x48
162 #define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT_TS0 0x4c
163 #define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT_TS1 0x50
164 #define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT2_TS0 0x54
165 #define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT2_TS1 0x58
166 #define XILINX_DP_SUB_AV_BUF_STC_SNAPSHOT0 0x60
167 #define XILINX_DP_SUB_AV_BUF_STC_SNAPSHOT1 0x64
168 #define XILINX_DP_SUB_AV_BUF_OUTPUT 0x70
169 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_SHIFT 0
170 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MASK (0x3 << 0)
171 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_PL (0 << 0)
172 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MEM (1 << 0)
173 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_PATTERN (2 << 0)
174 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_NONE (3 << 0)
175 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_SHIFT 2
176 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MASK (0x3 << 2)
177 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_DISABLE (0 << 2)
178 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MEM (1 << 2)
179 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_LIVE (2 << 2)
180 #define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_NONE (3 << 2)
181 #define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_SHIFT 4
182 #define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MASK (0x3 << 4)
183 #define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_PL (0 << 4)
184 #define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MEM (1 << 4)
185 #define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_PATTERN (2 << 4)
186 #define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_DISABLE (3 << 4)
187 #define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD2_EN BIT(6)
188 #define XILINX_DP_SUB_AV_BUF_HCOUNT_VCOUNT_INT0 0x74
189 #define XILINX_DP_SUB_AV_BUF_HCOUNT_VCOUNT_INT1 0x78
190 #define XILINX_DP_SUB_AV_BUF_PATTERN_GEN_SELECT 0x100
191 #define XILINX_DP_SUB_AV_BUF_CLK_SRC 0x120
192 #define XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_FROM_PS BIT(0)
193 #define XILINX_DP_SUB_AV_BUF_CLK_SRC_AUD_FROM_PS BIT(1)
194 #define XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING BIT(2)
195 #define XILINX_DP_SUB_AV_BUF_SRST_REG 0x124
196 #define XILINX_DP_SUB_AV_BUF_SRST_REG_VID_RST BIT(1)
197 #define XILINX_DP_SUB_AV_BUF_AUDIO_CH_CONFIG 0x12c
198 #define XILINX_DP_SUB_AV_BUF_GFX_COMP0_SF 0x200
199 #define XILINX_DP_SUB_AV_BUF_GFX_COMP1_SF 0x204
200 #define XILINX_DP_SUB_AV_BUF_GFX_COMP2_SF 0x208
201 #define XILINX_DP_SUB_AV_BUF_VID_COMP0_SF 0x20c
202 #define XILINX_DP_SUB_AV_BUF_VID_COMP1_SF 0x210
203 #define XILINX_DP_SUB_AV_BUF_VID_COMP2_SF 0x214
204 #define XILINX_DP_SUB_AV_BUF_LIVE_VID_COMP0_SF 0x218
205 #define XILINX_DP_SUB_AV_BUF_LIVE_VID_COMP1_SF 0x21c
206 #define XILINX_DP_SUB_AV_BUF_LIVE_VID_COMP2_SF 0x220
207 #define XILINX_DP_SUB_AV_BUF_4BIT_SF 0x11111
208 #define XILINX_DP_SUB_AV_BUF_5BIT_SF 0x10842
209 #define XILINX_DP_SUB_AV_BUF_6BIT_SF 0x10410
210 #define XILINX_DP_SUB_AV_BUF_8BIT_SF 0x10101
211 #define XILINX_DP_SUB_AV_BUF_10BIT_SF 0x10040
212 #define XILINX_DP_SUB_AV_BUF_NULL_SF 0
213 #define XILINX_DP_SUB_AV_BUF_NUM_SF 3
214 #define XILINX_DP_SUB_AV_BUF_LIVE_CB_CR_SWAP 0x224
215 #define XILINX_DP_SUB_AV_BUF_PALETTE_MEMORY 0x400
217 /* Audio registers */
218 #define XILINX_DP_SUB_AUD_MIXER_VOLUME 0x0
219 #define XILINX_DP_SUB_AUD_MIXER_VOLUME_NO_SCALE 0x20002000
220 #define XILINX_DP_SUB_AUD_MIXER_META_DATA 0x4
221 #define XILINX_DP_SUB_AUD_CH_STATUS0 0x8
222 #define XILINX_DP_SUB_AUD_CH_STATUS1 0xc
223 #define XILINX_DP_SUB_AUD_CH_STATUS2 0x10
224 #define XILINX_DP_SUB_AUD_CH_STATUS3 0x14
225 #define XILINX_DP_SUB_AUD_CH_STATUS4 0x18
226 #define XILINX_DP_SUB_AUD_CH_STATUS5 0x1c
227 #define XILINX_DP_SUB_AUD_CH_A_DATA0 0x20
228 #define XILINX_DP_SUB_AUD_CH_A_DATA1 0x24
229 #define XILINX_DP_SUB_AUD_CH_A_DATA2 0x28
230 #define XILINX_DP_SUB_AUD_CH_A_DATA3 0x2c
231 #define XILINX_DP_SUB_AUD_CH_A_DATA4 0x30
232 #define XILINX_DP_SUB_AUD_CH_A_DATA5 0x34
233 #define XILINX_DP_SUB_AUD_CH_B_DATA0 0x38
234 #define XILINX_DP_SUB_AUD_CH_B_DATA1 0x3c
235 #define XILINX_DP_SUB_AUD_CH_B_DATA2 0x40
236 #define XILINX_DP_SUB_AUD_CH_B_DATA3 0x44
237 #define XILINX_DP_SUB_AUD_CH_B_DATA4 0x48
238 #define XILINX_DP_SUB_AUD_CH_B_DATA5 0x4c
239 #define XILINX_DP_SUB_AUD_SOFT_RESET 0xc00
240 #define XILINX_DP_SUB_AUD_SOFT_RESET_AUD_SRST BIT(0)
242 #define XILINX_DP_SUB_AV_BUF_NUM_VID_GFX_BUFFERS 4
243 #define XILINX_DP_SUB_AV_BUF_NUM_BUFFERS 6
246 * enum xilinx_drm_dp_sub_layer_type - Layer type
247 * @XILINX_DRM_DP_SUB_LAYER_VID: video layer
248 * @XILINX_DRM_DP_SUB_LAYER_GFX: graphics layer
250 enum xilinx_drm_dp_sub_layer_type {
251 XILINX_DRM_DP_SUB_LAYER_VID,
252 XILINX_DRM_DP_SUB_LAYER_GFX
256 * struct xilinx_drm_dp_sub_layer - DP subsystem layer
258 * @offset: layer offset in the register space
259 * @avail: flag if layer is available
260 * @primary: flag for primary plane
261 * @enabled: flag if the layer is enabled
262 * @fmt: format descriptor
263 * @drm_fmts: array of supported DRM formats
264 * @num_fmts: number of supported DRM formats
267 * @other: other layer
269 struct xilinx_drm_dp_sub_layer {
270 enum xilinx_drm_dp_sub_layer_type id;
275 const struct xilinx_drm_dp_sub_fmt *fmt;
277 unsigned int num_fmts;
280 struct xilinx_drm_dp_sub_layer *other;
284 * struct xilinx_drm_dp_sub_blend - DP subsystem blender
285 * @base: pre-calculated base address
287 struct xilinx_drm_dp_sub_blend {
292 * struct xilinx_drm_dp_sub_av_buf - DP subsystem av buffer manager
293 * @base: pre-calculated base address
295 struct xilinx_drm_dp_sub_av_buf {
300 * struct xilinx_drm_dp_sub_aud - DP subsystem audio
301 * @base: pre-calculated base address
303 struct xilinx_drm_dp_sub_aud {
308 * struct xilinx_drm_dp_sub - DP subsystem
309 * @dev: device structure
310 * @blend: blender device
311 * @av_buf: av buffer manager device
314 * @list: entry in the global DP subsystem list
315 * @vblank_fn: vblank handler
316 * @vblank_data: vblank data to be used in vblank_fn
317 * @vid_clk_pl: flag if the clock is from PL
318 * @alpha: stored global alpha value
319 * @alpha_en: flag if the global alpha is enabled
321 struct xilinx_drm_dp_sub {
323 struct xilinx_drm_dp_sub_blend blend;
324 struct xilinx_drm_dp_sub_av_buf av_buf;
325 struct xilinx_drm_dp_sub_aud aud;
326 struct xilinx_drm_dp_sub_layer layers[XILINX_DRM_DP_SUB_NUM_LAYERS];
327 struct list_head list;
328 void (*vblank_fn)(void *);
336 * struct xilinx_drm_dp_sub_fmt - DP subsystem format mapping
337 * @drm_fmt: drm format
338 * @dp_sub_fmt: DP subsystem format
339 * @rgb: flag for RGB formats
340 * @swap: flag to swap r & b for rgb formats, and u & v for yuv formats
341 * @chroma_sub: flag for chroma subsampled formats
342 * @sf: scaling factors for upto 3 color components
345 struct xilinx_drm_dp_sub_fmt {
355 static LIST_HEAD(xilinx_drm_dp_sub_list);
356 static DEFINE_MUTEX(xilinx_drm_dp_sub_lock);
358 #ifdef CONFIG_DRM_XILINX_DP_SUB_DEBUG_FS
359 #define XILINX_DP_SUB_DEBUGFS_READ_MAX_SIZE 32
360 #define XILINX_DP_SUB_DEBUGFS_MAX_BG_COLOR_VAL 0xFFF
361 #define IN_RANGE(x, min, max) ({ \
362 typeof(x) _x = (x); \
363 _x >= (min) && _x <= (max); })
365 /* Match xilinx_dp_testcases vs dp_debugfs_reqs[] entry */
366 enum xilinx_dp_sub_testcases {
368 DP_SUB_TC_OUTPUT_FMT,
372 struct xilinx_dp_sub_debugfs {
373 enum xilinx_dp_sub_testcases testcase;
378 struct xilinx_drm_dp_sub *xilinx_dp_sub;
381 static struct xilinx_dp_sub_debugfs dp_sub_debugfs;
382 struct xilinx_dp_sub_debugfs_request {
384 enum xilinx_dp_sub_testcases tc;
385 ssize_t (*read_handler)(char **kern_buff);
386 ssize_t (*write_handler)(char **cmd);
389 static s64 xilinx_dp_sub_debugfs_argument_value(char *arg)
396 if (!kstrtos64(arg, 0, &value))
403 xilinx_dp_sub_debugfs_update_v_blend(u16 *sdtv_coeffs, u32 *full_range_offsets)
405 struct xilinx_drm_dp_sub *dp_sub = dp_sub_debugfs.xilinx_dp_sub;
408 /* Hardcode SDTV coefficients. Can be runtime configurable */
409 offset = XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF0;
410 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_COEFF; i++)
411 xilinx_drm_writel(dp_sub->blend.base, offset + i * 4,
414 offset = XILINX_DP_SUB_V_BLEND_LUMA_OUTCSC_OFFSET;
415 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_OFFSET; i++)
416 xilinx_drm_writel(dp_sub->blend.base, offset + i * 4,
417 full_range_offsets[i]);
420 static void xilinx_dp_sub_debugfs_output_format(u32 fmt)
422 struct xilinx_drm_dp_sub *dp_sub = dp_sub_debugfs.xilinx_dp_sub;
424 xilinx_drm_writel(dp_sub->blend.base,
425 XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT, fmt);
427 if (fmt != XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB) {
428 u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
429 0x7d4d, 0x7ab3, 0x800,
430 0x800, 0x794d, 0x7eb3 };
431 u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
433 xilinx_dp_sub_debugfs_update_v_blend(sdtv_coeffs,
436 /* In case of RGB set the reset values*/
437 u16 sdtv_coeffs[] = { 0x1000, 0x0, 0x0,
440 u32 full_range_offsets[] = { 0x0, 0x0, 0x0 };
442 xilinx_dp_sub_debugfs_update_v_blend(sdtv_coeffs,
448 xilinx_dp_sub_debugfs_background_color_write(char **dp_sub_test_arg)
450 char *r_color, *g_color, *b_color;
451 s64 r_val, g_val, b_val;
453 r_color = strsep(dp_sub_test_arg, " ");
454 g_color = strsep(dp_sub_test_arg, " ");
455 b_color = strsep(dp_sub_test_arg, " ");
457 /* char * to int conversion */
458 r_val = xilinx_dp_sub_debugfs_argument_value(r_color);
459 g_val = xilinx_dp_sub_debugfs_argument_value(g_color);
460 b_val = xilinx_dp_sub_debugfs_argument_value(b_color);
462 if (!(IN_RANGE(r_val, 0, XILINX_DP_SUB_DEBUGFS_MAX_BG_COLOR_VAL) &&
463 IN_RANGE(g_val, 0, XILINX_DP_SUB_DEBUGFS_MAX_BG_COLOR_VAL) &&
464 IN_RANGE(b_val, 0, XILINX_DP_SUB_DEBUGFS_MAX_BG_COLOR_VAL)))
467 dp_sub_debugfs.r_value = r_val;
468 dp_sub_debugfs.g_value = g_val;
469 dp_sub_debugfs.b_value = b_val;
471 dp_sub_debugfs.testcase = DP_SUB_TC_BG_COLOR;
477 xilinx_dp_sub_debugfs_output_display_format_write(char **dp_sub_test_arg)
480 struct xilinx_drm_dp_sub *dp_sub = dp_sub_debugfs.xilinx_dp_sub;
483 /* Read the value from an user value */
484 output_format = strsep(dp_sub_test_arg, " ");
485 if (strncmp(output_format, "rgb", 3) == 0) {
486 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB;
487 } else if (strncmp(output_format, "ycbcr444", 8) == 0) {
488 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR444;
489 } else if (strncmp(output_format, "ycbcr422", 8) == 0) {
490 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR422;
491 fmt |= XILINX_DP_SUB_V_BLEND_OUTPUT_EN_DOWNSAMPLE;
492 } else if (strncmp(output_format, "yonly", 5) == 0) {
493 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YONLY;
495 dev_err(dp_sub->dev, "Invalid output format\n");
499 dp_sub_debugfs.output_fmt =
500 xilinx_drm_readl(dp_sub->blend.base,
501 XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT);
503 xilinx_dp_sub_debugfs_output_format(fmt);
504 dp_sub_debugfs.testcase = DP_SUB_TC_OUTPUT_FMT;
510 xilinx_dp_sub_debugfs_output_display_format_read(char **kern_buff)
514 dp_sub_debugfs.testcase = DP_SUB_TC_NONE;
515 xilinx_dp_sub_debugfs_output_format(dp_sub_debugfs.output_fmt);
517 out_str_len = strlen("Success");
518 out_str_len = min_t(size_t, XILINX_DP_SUB_DEBUGFS_READ_MAX_SIZE,
520 snprintf(*kern_buff, out_str_len, "%s", "Success");
526 xilinx_dp_sub_debugfs_background_color_read(char **kern_buff)
530 dp_sub_debugfs.testcase = DP_SUB_TC_NONE;
531 dp_sub_debugfs.r_value = 0;
532 dp_sub_debugfs.g_value = 0;
533 dp_sub_debugfs.b_value = 0;
535 out_str_len = strlen("Success");
536 out_str_len = min_t(size_t, XILINX_DP_SUB_DEBUGFS_READ_MAX_SIZE,
538 snprintf(*kern_buff, out_str_len, "%s", "Success");
543 /* Match xilinx_dp_testcases vs dp_debugfs_reqs[] entry */
544 static struct xilinx_dp_sub_debugfs_request dp_sub_debugfs_reqs[] = {
545 {"BACKGROUND_COLOR", DP_SUB_TC_BG_COLOR,
546 xilinx_dp_sub_debugfs_background_color_read,
547 xilinx_dp_sub_debugfs_background_color_write},
548 {"OUTPUT_DISPLAY_FORMAT", DP_SUB_TC_OUTPUT_FMT,
549 xilinx_dp_sub_debugfs_output_display_format_read,
550 xilinx_dp_sub_debugfs_output_display_format_write},
554 xilinx_dp_sub_debugfs_write(struct file *f, const char __user *buf,
555 size_t size, loff_t *pos)
557 char *kern_buff, *dp_sub_test_req, *kern_buff_start;
561 if (*pos != 0 || size <= 0)
564 if (dp_sub_debugfs.testcase != DP_SUB_TC_NONE)
567 kern_buff = kzalloc(size, GFP_KERNEL);
570 kern_buff_start = kern_buff;
572 ret = strncpy_from_user(kern_buff, buf, size);
574 kfree(kern_buff_start);
578 /* Read the testcase name and argument from an user request */
579 dp_sub_test_req = strsep(&kern_buff, " ");
581 for (i = 0; i < ARRAY_SIZE(dp_sub_debugfs_reqs); i++) {
582 if (!strcasecmp(dp_sub_test_req, dp_sub_debugfs_reqs[i].req))
583 if (!dp_sub_debugfs_reqs[i].write_handler(&kern_buff)) {
584 kfree(kern_buff_start);
588 kfree(kern_buff_start);
592 static ssize_t xilinx_dp_sub_debugfs_read(struct file *f, char __user *buf,
593 size_t size, loff_t *pos)
595 char *kern_buff = NULL;
596 size_t kern_buff_len, out_str_len;
605 kern_buff = kzalloc(XILINX_DP_SUB_DEBUGFS_READ_MAX_SIZE, GFP_KERNEL);
607 dp_sub_debugfs.testcase = DP_SUB_TC_NONE;
611 if (dp_sub_debugfs.testcase == DP_SUB_TC_NONE) {
612 out_str_len = strlen("No testcase executed");
613 out_str_len = min_t(size_t, XILINX_DP_SUB_DEBUGFS_READ_MAX_SIZE,
615 snprintf(kern_buff, out_str_len, "%s", "No testcase executed");
617 ret = dp_sub_debugfs_reqs[dp_sub_debugfs.testcase].read_handler(
625 kern_buff_len = strlen(kern_buff);
626 size = min(size, kern_buff_len);
628 ret = copy_to_user(buf, kern_buff, size);
638 static const struct file_operations fops_xilinx_dp_sub_dbgfs = {
639 .owner = THIS_MODULE,
640 .read = xilinx_dp_sub_debugfs_read,
641 .write = xilinx_dp_sub_debugfs_write,
644 static int xilinx_dp_sub_debugfs_init(struct xilinx_drm_dp_sub *dp_sub)
647 struct dentry *xilinx_dp_sub_debugfs_dir, *xilinx_dp_sub_debugfs_file;
649 dp_sub_debugfs.testcase = DP_SUB_TC_NONE;
650 dp_sub_debugfs.xilinx_dp_sub = dp_sub;
652 xilinx_dp_sub_debugfs_dir = debugfs_create_dir("dp_sub", NULL);
653 if (!xilinx_dp_sub_debugfs_dir) {
654 dev_err(dp_sub->dev, "debugfs_create_dir failed\n");
658 xilinx_dp_sub_debugfs_file =
659 debugfs_create_file("testcase", 0444,
660 xilinx_dp_sub_debugfs_dir, NULL,
661 &fops_xilinx_dp_sub_dbgfs);
662 if (!xilinx_dp_sub_debugfs_file) {
663 dev_err(dp_sub->dev, "debugfs_create_file testcase failed\n");
670 debugfs_remove_recursive(xilinx_dp_sub_debugfs_dir);
671 xilinx_dp_sub_debugfs_dir = NULL;
675 static void xilinx_drm_dp_sub_debugfs_bg_color(struct xilinx_drm_dp_sub *dp_sub)
677 if (dp_sub_debugfs.testcase == DP_SUB_TC_BG_COLOR) {
678 xilinx_drm_writel(dp_sub->blend.base,
679 XILINX_DP_SUB_V_BLEND_BG_CLR_0,
680 dp_sub_debugfs.r_value);
681 xilinx_drm_writel(dp_sub->blend.base,
682 XILINX_DP_SUB_V_BLEND_BG_CLR_1,
683 dp_sub_debugfs.g_value);
684 xilinx_drm_writel(dp_sub->blend.base,
685 XILINX_DP_SUB_V_BLEND_BG_CLR_2,
686 dp_sub_debugfs.b_value);
690 static int xilinx_dp_sub_debugfs_init(struct xilinx_drm_dp_sub *dp_sub)
695 static void xilinx_drm_dp_sub_debugfs_bg_color(struct xilinx_drm_dp_sub *dp_sub)
698 #endif /* CONFIG_DP_DEBUG_FS */
700 /* Blender functions */
703 * xilinx_drm_dp_sub_blend_layer_enable - Enable a layer
704 * @blend: blend object
705 * @layer: layer to enable
707 * Enable a layer @layer.
710 xilinx_drm_dp_sub_blend_layer_enable(struct xilinx_drm_dp_sub_blend *blend,
711 struct xilinx_drm_dp_sub_layer *layer)
713 u32 reg, offset, i, s0, s1;
714 u16 sdtv_coeffs[] = { 0x1000, 0x166f, 0x0,
715 0x1000, 0x7483, 0x7a7f,
716 0x1000, 0x0, 0x1c5a };
717 u16 swap_coeffs[] = { 0x1000, 0x0, 0x0,
721 u32 offsets[] = { 0x0, 0x1800, 0x1800 };
723 reg = layer->fmt->rgb ? XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_RGB : 0;
724 reg |= layer->fmt->chroma_sub ?
725 XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_EN_US : 0;
727 xilinx_drm_writel(blend->base,
728 XILINX_DP_SUB_V_BLEND_LAYER_CONTROL + layer->offset,
731 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
732 offset = XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF0;
734 offset = XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF0;
736 if (!layer->fmt->rgb) {
737 coeffs = sdtv_coeffs;
741 coeffs = swap_coeffs;
745 /* No offset for RGB formats */
746 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_OFFSET; i++)
750 if (layer->fmt->swap) {
751 for (i = 0; i < 3; i++) {
752 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
753 coeffs[i * 3 + s1] ^= coeffs[i * 3 + s0];
754 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
758 /* Program coefficients. Can be runtime configurable */
759 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_COEFF; i++)
760 xilinx_drm_writel(blend->base, offset + i * 4, coeffs[i]);
762 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
763 offset = XILINX_DP_SUB_V_BLEND_LUMA_IN1CSC_OFFSET;
765 offset = XILINX_DP_SUB_V_BLEND_LUMA_IN2CSC_OFFSET;
767 /* Program offsets. Can be runtime configurable */
768 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_OFFSET; i++)
769 xilinx_drm_writel(blend->base, offset + i * 4, offsets[i]);
773 * xilinx_drm_dp_sub_blend_layer_disable - Disable a layer
774 * @blend: blend object
775 * @layer: layer to disable
777 * Disable a layer @layer.
780 xilinx_drm_dp_sub_blend_layer_disable(struct xilinx_drm_dp_sub_blend *blend,
781 struct xilinx_drm_dp_sub_layer *layer)
783 xilinx_drm_writel(blend->base,
784 XILINX_DP_SUB_V_BLEND_LAYER_CONTROL + layer->offset,
789 * xilinx_drm_dp_sub_blend_set_bg_color - Set the background color
790 * @blend: blend object
791 * @c0: color component 0
792 * @c1: color component 1
793 * @c2: color component 2
795 * Set the background color.
798 xilinx_drm_dp_sub_blend_set_bg_color(struct xilinx_drm_dp_sub_blend *blend,
799 u32 c0, u32 c1, u32 c2)
801 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_BG_CLR_0, c0);
802 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_BG_CLR_1, c1);
803 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_BG_CLR_2, c2);
807 * xilinx_drm_dp_sub_blend_set_alpha - Set the alpha for blending
808 * @blend: blend object
809 * @alpha: alpha value to be used
811 * Set the alpha for blending.
814 xilinx_drm_dp_sub_blend_set_alpha(struct xilinx_drm_dp_sub_blend *blend,
819 reg = xilinx_drm_readl(blend->base,
820 XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA);
821 reg &= ~XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA_MASK;
823 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA,
828 * xilinx_drm_dp_sub_blend_enable_alpha - Enable/disable the global alpha
829 * @blend: blend object
830 * @enable: flag to enable or disable alpha blending
832 * Enable/disable the global alpha blending based on @enable.
835 xilinx_drm_dp_sub_blend_enable_alpha(struct xilinx_drm_dp_sub_blend *blend,
839 xilinx_drm_set(blend->base,
840 XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
842 xilinx_drm_clr(blend->base,
843 XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
846 static const struct xilinx_drm_dp_sub_fmt blend_output_fmts[] = {
848 .drm_fmt = DRM_FORMAT_RGB888,
849 .dp_sub_fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB,
853 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
854 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
855 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
858 .drm_fmt = DRM_FORMAT_YUV444,
859 .dp_sub_fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR444,
863 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
864 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
865 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
868 .drm_fmt = DRM_FORMAT_YUV422,
869 .dp_sub_fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR422,
873 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
874 .sf[1] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
875 .sf[2] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
882 * xilinx_drm_dp_sub_blend_set_output_fmt - Set the output format
883 * @blend: blend object
884 * @fmt: output format
886 * Set the output format to @fmt.
889 xilinx_drm_dp_sub_blend_set_output_fmt(struct xilinx_drm_dp_sub_blend *blend,
892 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT,
896 /* AV buffer manager functions */
898 static const struct xilinx_drm_dp_sub_fmt av_buf_vid_fmts[] = {
900 .drm_fmt = DRM_FORMAT_VYUY,
901 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_VYUY,
905 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
906 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
907 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
910 .drm_fmt = DRM_FORMAT_UYVY,
911 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_VYUY,
915 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
916 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
917 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
920 .drm_fmt = DRM_FORMAT_YUYV,
921 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUYV,
925 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
926 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
927 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
930 .drm_fmt = DRM_FORMAT_YVYU,
931 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUYV,
935 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
936 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
937 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
940 .drm_fmt = DRM_FORMAT_YUV422,
941 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16,
945 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
946 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
947 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
950 .drm_fmt = DRM_FORMAT_YVU422,
951 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16,
955 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
956 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
957 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
960 .drm_fmt = DRM_FORMAT_YUV444,
961 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV24,
965 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
966 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
967 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
970 .drm_fmt = DRM_FORMAT_YVU444,
971 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV24,
975 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
976 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
977 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
980 .drm_fmt = DRM_FORMAT_NV16,
981 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI,
985 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
986 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
987 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
990 .drm_fmt = DRM_FORMAT_NV61,
991 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI,
995 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
996 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
997 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1000 .drm_fmt = DRM_FORMAT_BGR888,
1001 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888,
1004 .chroma_sub = false,
1005 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1006 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1007 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1010 .drm_fmt = DRM_FORMAT_RGB888,
1011 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888,
1014 .chroma_sub = false,
1015 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1016 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1017 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1020 .drm_fmt = DRM_FORMAT_XBGR8888,
1021 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGBA8880,
1024 .chroma_sub = false,
1025 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1026 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1027 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1030 .drm_fmt = DRM_FORMAT_XRGB8888,
1031 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGBA8880,
1034 .chroma_sub = false,
1035 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1036 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1037 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1040 .drm_fmt = DRM_FORMAT_XBGR2101010,
1041 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888_10,
1044 .chroma_sub = false,
1045 .sf[0] = XILINX_DP_SUB_AV_BUF_10BIT_SF,
1046 .sf[1] = XILINX_DP_SUB_AV_BUF_10BIT_SF,
1047 .sf[2] = XILINX_DP_SUB_AV_BUF_10BIT_SF,
1048 .name = "xbgr2101010",
1050 .drm_fmt = DRM_FORMAT_XRGB2101010,
1051 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888_10,
1054 .chroma_sub = false,
1055 .sf[0] = XILINX_DP_SUB_AV_BUF_10BIT_SF,
1056 .sf[1] = XILINX_DP_SUB_AV_BUF_10BIT_SF,
1057 .sf[2] = XILINX_DP_SUB_AV_BUF_10BIT_SF,
1058 .name = "xrgb2101010",
1060 .drm_fmt = DRM_FORMAT_YUV420,
1061 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_420,
1065 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1066 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1067 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1070 .drm_fmt = DRM_FORMAT_YVU420,
1071 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_420,
1075 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1076 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1077 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1080 .drm_fmt = DRM_FORMAT_NV12,
1081 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420,
1085 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1086 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1087 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1090 .drm_fmt = DRM_FORMAT_NV21,
1091 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420,
1095 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1096 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1097 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1102 static const struct xilinx_drm_dp_sub_fmt av_buf_gfx_fmts[] = {
1104 .drm_fmt = DRM_FORMAT_ABGR8888,
1105 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA8888,
1108 .chroma_sub = false,
1109 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1110 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1111 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1114 .drm_fmt = DRM_FORMAT_ARGB8888,
1115 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA8888,
1118 .chroma_sub = false,
1119 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1120 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1121 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1124 .drm_fmt = DRM_FORMAT_RGBA8888,
1125 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_ABGR8888,
1128 .chroma_sub = false,
1129 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1130 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1131 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1134 .drm_fmt = DRM_FORMAT_BGRA8888,
1135 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_ABGR8888,
1138 .chroma_sub = false,
1139 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1140 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1141 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1144 .drm_fmt = DRM_FORMAT_BGR888,
1145 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB888,
1148 .chroma_sub = false,
1149 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1150 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1151 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1154 .drm_fmt = DRM_FORMAT_RGB888,
1155 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_BGR888,
1158 .chroma_sub = false,
1159 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1160 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1161 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
1164 .drm_fmt = DRM_FORMAT_RGBA5551,
1165 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA5551,
1168 .chroma_sub = false,
1169 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1170 .sf[1] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1171 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1174 .drm_fmt = DRM_FORMAT_BGRA5551,
1175 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA5551,
1178 .chroma_sub = false,
1179 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1180 .sf[1] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1181 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1184 .drm_fmt = DRM_FORMAT_RGBA4444,
1185 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA4444,
1188 .chroma_sub = false,
1189 .sf[0] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
1190 .sf[1] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
1191 .sf[2] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
1194 .drm_fmt = DRM_FORMAT_BGRA4444,
1195 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA4444,
1198 .chroma_sub = false,
1199 .sf[0] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
1200 .sf[1] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
1201 .sf[2] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
1204 .drm_fmt = DRM_FORMAT_RGB565,
1205 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB565,
1208 .chroma_sub = false,
1209 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1210 .sf[1] = XILINX_DP_SUB_AV_BUF_6BIT_SF,
1211 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1214 .drm_fmt = DRM_FORMAT_BGR565,
1215 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB565,
1218 .chroma_sub = false,
1219 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1220 .sf[1] = XILINX_DP_SUB_AV_BUF_6BIT_SF,
1221 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
1227 * xilinx_drm_dp_sub_av_buf_set_fmt - Set the input formats
1228 * @av_buf: av buffer manager
1231 * Set the av buffer manager format to @fmt. @fmt should have valid values
1232 * for both video and graphics layer.
1235 xilinx_drm_dp_sub_av_buf_set_fmt(struct xilinx_drm_dp_sub_av_buf *av_buf,
1238 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_FMT, fmt);
1242 * xilinx_drm_dp_sub_av_buf_get_fmt - Get the input formats
1243 * @av_buf: av buffer manager
1245 * Get the input formats (which include video and graphics) of
1246 * av buffer manager.
1248 * Return: value of XILINX_DP_SUB_AV_BUF_FMT register.
1251 xilinx_drm_dp_sub_av_buf_get_fmt(struct xilinx_drm_dp_sub_av_buf *av_buf)
1253 return xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_FMT);
1257 * xilinx_drm_dp_sub_av_buf_set_vid_clock_src - Set the video clock source
1258 * @av_buf: av buffer manager
1259 * @from_ps: flag if the video clock is from ps
1261 * Set the video clock source based on @from_ps. It can come from either PS or
1264 static void xilinx_drm_dp_sub_av_buf_set_vid_clock_src(
1265 struct xilinx_drm_dp_sub_av_buf *av_buf, bool from_ps)
1269 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC);
1271 reg |= XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_FROM_PS;
1273 reg &= ~XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_FROM_PS;
1274 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC, reg);
1278 * xilinx_drm_dp_sub_av_buf_set_vid_timing_src - Set the video timing source
1279 * @av_buf: av buffer manager
1280 * @internal: flag if the video timing is generated internally
1282 * Set the video timing source based on @internal. It can come externally or
1283 * be generated internally.
1285 static void xilinx_drm_dp_sub_av_buf_set_vid_timing_src(
1286 struct xilinx_drm_dp_sub_av_buf *av_buf, bool internal)
1290 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC);
1292 reg |= XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1294 reg &= ~XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
1295 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC, reg);
1299 * xilinx_drm_dp_sub_av_buf_set_aud_clock_src - Set the audio clock source
1300 * @av_buf: av buffer manager
1301 * @from_ps: flag if the video clock is from ps
1303 * Set the audio clock source based on @from_ps. It can come from either PS or
1306 static void xilinx_drm_dp_sub_av_buf_set_aud_clock_src(
1307 struct xilinx_drm_dp_sub_av_buf *av_buf, bool from_ps)
1311 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC);
1313 reg |= XILINX_DP_SUB_AV_BUF_CLK_SRC_AUD_FROM_PS;
1315 reg &= ~XILINX_DP_SUB_AV_BUF_CLK_SRC_AUD_FROM_PS;
1316 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC, reg);
1320 * xilinx_drm_dp_sub_av_buf_enable_buf - Enable buffers
1321 * @av_buf: av buffer manager
1323 * Enable all (video and audio) buffers.
1326 xilinx_drm_dp_sub_av_buf_enable_buf(struct xilinx_drm_dp_sub_av_buf *av_buf)
1330 reg = XILINX_DP_SUB_AV_BUF_CHBUF_EN;
1331 reg |= XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_MAX <<
1332 XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1334 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
1335 xilinx_drm_writel(av_buf->base,
1336 XILINX_DP_SUB_AV_BUF_CHBUF + i * 4, reg);
1338 reg = XILINX_DP_SUB_AV_BUF_CHBUF_EN;
1339 reg |= XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_AUD_MAX <<
1340 XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_SHIFT;
1342 for (; i < XILINX_DP_SUB_AV_BUF_NUM_BUFFERS; i++)
1343 xilinx_drm_writel(av_buf->base,
1344 XILINX_DP_SUB_AV_BUF_CHBUF + i * 4, reg);
1348 * xilinx_drm_dp_sub_av_buf_disable_buf - Disable buffers
1349 * @av_buf: av buffer manager
1351 * Disable all (video and audio) buffers.
1354 xilinx_drm_dp_sub_av_buf_disable_buf(struct xilinx_drm_dp_sub_av_buf *av_buf)
1358 reg = XILINX_DP_SUB_AV_BUF_CHBUF_FLUSH & ~XILINX_DP_SUB_AV_BUF_CHBUF_EN;
1359 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_BUFFERS; i++)
1360 xilinx_drm_writel(av_buf->base,
1361 XILINX_DP_SUB_AV_BUF_CHBUF + i * 4, reg);
1365 * xilinx_drm_dp_sub_av_buf_enable_aud - Enable audio
1366 * @av_buf: av buffer manager
1368 * Enable all audio buffers.
1371 xilinx_drm_dp_sub_av_buf_enable_aud(struct xilinx_drm_dp_sub_av_buf *av_buf)
1375 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
1376 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MASK;
1377 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MEM;
1378 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_AUD2_EN;
1379 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
1383 * xilinx_drm_dp_sub_av_buf_enable - Enable the video pipe
1384 * @av_buf: av buffer manager
1386 * De-assert the video pipe reset
1389 xilinx_drm_dp_sub_av_buf_enable(struct xilinx_drm_dp_sub_av_buf *av_buf)
1391 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_SRST_REG, 0);
1395 * xilinx_drm_dp_sub_av_buf_disable - Disable the video pipe
1396 * @av_buf: av buffer manager
1398 * Assert the video pipe reset
1401 xilinx_drm_dp_sub_av_buf_disable(struct xilinx_drm_dp_sub_av_buf *av_buf)
1403 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_SRST_REG,
1404 XILINX_DP_SUB_AV_BUF_SRST_REG_VID_RST);
1408 * xilinx_drm_dp_sub_av_buf_disable_aud - Disable audio
1409 * @av_buf: av buffer manager
1411 * Disable all audio buffers.
1414 xilinx_drm_dp_sub_av_buf_disable_aud(struct xilinx_drm_dp_sub_av_buf *av_buf)
1418 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
1419 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MASK;
1420 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_DISABLE;
1421 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_AUD2_EN;
1422 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
1426 * xilinx_drm_dp_sub_av_buf_enable_vid - Enable the video layer buffer
1427 * @av_buf: av buffer manager
1428 * @layer: layer to enable
1430 * Enable the video/graphics buffer for @layer.
1433 xilinx_drm_dp_sub_av_buf_enable_vid(struct xilinx_drm_dp_sub_av_buf *av_buf,
1434 struct xilinx_drm_dp_sub_layer *layer)
1438 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
1439 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID) {
1440 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MASK;
1441 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MEM;
1443 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MASK;
1444 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MEM;
1446 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
1450 * xilinx_drm_dp_sub_av_buf_disable_vid - Disable the video layer buffer
1451 * @av_buf: av buffer manager
1452 * @layer: layer to disable
1454 * Disable the video/graphics buffer for @layer.
1457 xilinx_drm_dp_sub_av_buf_disable_vid(struct xilinx_drm_dp_sub_av_buf *av_buf,
1458 struct xilinx_drm_dp_sub_layer *layer)
1462 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
1464 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID) {
1465 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MASK;
1466 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_NONE;
1468 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MASK;
1469 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_DISABLE;
1472 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
1476 * xilinx_drm_dp_sub_av_buf_init_fmts - Initialize the layer formats
1477 * @av_buf: av buffer manager
1478 * @vid_fmt: video format descriptor
1479 * @gfx_fmt: graphics format descriptor
1481 * Initialize formats of both video and graphics layers.
1484 xilinx_drm_dp_sub_av_buf_init_fmts(struct xilinx_drm_dp_sub_av_buf *av_buf,
1485 const struct xilinx_drm_dp_sub_fmt *vid_fmt,
1486 const struct xilinx_drm_dp_sub_fmt *gfx_fmt)
1490 reg = vid_fmt->dp_sub_fmt;
1491 reg |= gfx_fmt->dp_sub_fmt;
1492 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_FMT, reg);
1496 * xilinx_drm_dp_sub_av_buf_init_sf - Initialize scaling factors
1497 * @av_buf: av buffer manager
1498 * @vid_fmt: video format descriptor
1499 * @gfx_fmt: graphics format descriptor
1501 * Initialize scaling factors for both video and graphics layers.
1504 xilinx_drm_dp_sub_av_buf_init_sf(struct xilinx_drm_dp_sub_av_buf *av_buf,
1505 const struct xilinx_drm_dp_sub_fmt *vid_fmt,
1506 const struct xilinx_drm_dp_sub_fmt *gfx_fmt)
1512 offset = XILINX_DP_SUB_AV_BUF_GFX_COMP0_SF;
1513 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_SF; i++)
1514 xilinx_drm_writel(av_buf->base, offset + i * 4,
1519 offset = XILINX_DP_SUB_AV_BUF_VID_COMP0_SF;
1520 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_SF; i++)
1521 xilinx_drm_writel(av_buf->base, offset + i * 4,
1526 /* Audio functions */
1529 * xilinx_drm_dp_sub_aud_init - Initialize the audio
1532 * Initialize the audio with default mixer volume. The de-assertion will
1533 * initialize the audio states.
1535 static void xilinx_drm_dp_sub_aud_init(struct xilinx_drm_dp_sub_aud *aud)
1537 /* Clear the audio soft reset register as it's an non-reset flop */
1538 xilinx_drm_writel(aud->base, XILINX_DP_SUB_AUD_SOFT_RESET, 0);
1539 xilinx_drm_writel(aud->base, XILINX_DP_SUB_AUD_MIXER_VOLUME,
1540 XILINX_DP_SUB_AUD_MIXER_VOLUME_NO_SCALE);
1544 * xilinx_drm_dp_sub_aud_deinit - De-initialize the audio
1547 * Put the audio in reset.
1549 static void xilinx_drm_dp_sub_aud_deinit(struct xilinx_drm_dp_sub_aud *aud)
1551 xilinx_drm_set(aud->base, XILINX_DP_SUB_AUD_SOFT_RESET,
1552 XILINX_DP_SUB_AUD_SOFT_RESET_AUD_SRST);
1555 /* DP subsystem layer functions */
1558 * xilinx_drm_dp_sub_layer_check_size - Verify width and height for the layer
1559 * @dp_sub: DP subsystem
1564 * The DP subsystem has the limitation that both layers should have
1565 * identical size. This function stores width and height of @layer, and verifies
1566 * if the size (width and height) is valid.
1568 * Return: 0 on success, or -EINVAL if width or/and height is invalid.
1570 int xilinx_drm_dp_sub_layer_check_size(struct xilinx_drm_dp_sub *dp_sub,
1571 struct xilinx_drm_dp_sub_layer *layer,
1572 u32 width, u32 height)
1574 struct xilinx_drm_dp_sub_layer *other = layer->other;
1576 if (other->enabled && (other->w != width || other->h != height)) {
1577 dev_err(dp_sub->dev, "Layer width:height must be %d:%d\n",
1578 other->w, other->h);
1587 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_check_size);
1590 * xilinx_drm_dp_sub_map_fmt - Find the DP subsystem format for given drm format
1591 * @fmts: format table to look up
1592 * @size: size of the table @fmts
1593 * @drm_fmt: DRM format to search
1595 * Search a DP subsystem format corresponding to the given DRM format @drm_fmt,
1596 * and return the format descriptor which contains the DP subsystem format
1599 * Return: a DP subsystem format descriptor on success, or NULL.
1601 static const struct xilinx_drm_dp_sub_fmt *
1602 xilinx_drm_dp_sub_map_fmt(const struct xilinx_drm_dp_sub_fmt fmts[],
1603 unsigned int size, u32 drm_fmt)
1607 for (i = 0; i < size; i++)
1608 if (fmts[i].drm_fmt == drm_fmt)
1615 * xilinx_drm_dp_sub_set_fmt - Set the format of the layer
1616 * @dp_sub: DP subsystem
1617 * @layer: layer to set the format
1618 * @drm_fmt: DRM format to set
1620 * Set the format of the given layer to @drm_fmt.
1622 * Return: 0 on success. -EINVAL if @drm_fmt is not supported by the layer.
1624 int xilinx_drm_dp_sub_layer_set_fmt(struct xilinx_drm_dp_sub *dp_sub,
1625 struct xilinx_drm_dp_sub_layer *layer,
1628 const struct xilinx_drm_dp_sub_fmt *fmt;
1629 const struct xilinx_drm_dp_sub_fmt *vid_fmt = NULL, *gfx_fmt = NULL;
1630 u32 size, fmts, mask;
1632 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID) {
1633 size = ARRAY_SIZE(av_buf_vid_fmts);
1634 mask = ~XILINX_DP_SUB_AV_BUF_FMT_NL_VID_MASK;
1635 fmt = xilinx_drm_dp_sub_map_fmt(av_buf_vid_fmts, size, drm_fmt);
1638 size = ARRAY_SIZE(av_buf_gfx_fmts);
1639 mask = ~XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_MASK;
1640 fmt = xilinx_drm_dp_sub_map_fmt(av_buf_gfx_fmts, size, drm_fmt);
1647 fmts = xilinx_drm_dp_sub_av_buf_get_fmt(&dp_sub->av_buf);
1649 fmts |= fmt->dp_sub_fmt;
1650 xilinx_drm_dp_sub_av_buf_set_fmt(&dp_sub->av_buf, fmts);
1651 xilinx_drm_dp_sub_av_buf_init_sf(&dp_sub->av_buf, vid_fmt, gfx_fmt);
1657 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_set_fmt);
1660 * xilinx_drm_dp_sub_get_fmt - Get the format of the layer
1661 * @dp_sub: DP subsystem
1662 * @layer: layer to set the format
1664 * Get the format of the given layer.
1666 * Return: DRM format of the layer
1668 u32 xilinx_drm_dp_sub_layer_get_fmt(struct xilinx_drm_dp_sub *dp_sub,
1669 struct xilinx_drm_dp_sub_layer *layer)
1671 return layer->fmt->drm_fmt;
1673 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_get_fmt);
1676 * xilinx_drm_dp_sub_get_fmt - Get the supported DRM formats of the layer
1677 * @dp_sub: DP subsystem
1678 * @layer: layer to get the formats
1679 * @drm_fmts: pointer to array of DRM format strings
1680 * @num_fmts: pointer to number of returned DRM formats
1682 * Get the supported DRM formats of the given layer.
1684 void xilinx_drm_dp_sub_layer_get_fmts(struct xilinx_drm_dp_sub *dp_sub,
1685 struct xilinx_drm_dp_sub_layer *layer,
1687 unsigned int *num_fmts)
1689 *drm_fmts = layer->drm_fmts;
1690 *num_fmts = layer->num_fmts;
1692 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_get_fmts);
1695 * xilinx_drm_dp_sub_layer_enable - Enable the layer
1696 * @dp_sub: DP subsystem
1697 * @layer: layer to esable
1699 * Enable the layer @layer.
1701 void xilinx_drm_dp_sub_layer_enable(struct xilinx_drm_dp_sub *dp_sub,
1702 struct xilinx_drm_dp_sub_layer *layer)
1704 xilinx_drm_dp_sub_av_buf_enable_vid(&dp_sub->av_buf, layer);
1705 xilinx_drm_dp_sub_blend_layer_enable(&dp_sub->blend, layer);
1706 layer->enabled = true;
1707 if (layer->other->enabled) {
1708 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend,
1710 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend,
1715 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
1718 alpha = XILINX_DRM_DP_SUB_MAX_ALPHA;
1719 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend, alpha);
1720 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend, true);
1723 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_enable);
1726 * xilinx_drm_dp_sub_layer_enable - Disable the layer
1727 * @dp_sub: DP subsystem
1728 * @layer: layer to disable
1730 * Disable the layer @layer.
1732 void xilinx_drm_dp_sub_layer_disable(struct xilinx_drm_dp_sub *dp_sub,
1733 struct xilinx_drm_dp_sub_layer *layer)
1735 xilinx_drm_dp_sub_av_buf_disable_vid(&dp_sub->av_buf, layer);
1736 xilinx_drm_dp_sub_blend_layer_disable(&dp_sub->blend, layer);
1737 layer->enabled = false;
1738 if (layer->other->enabled) {
1741 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
1742 alpha = XILINX_DRM_DP_SUB_MAX_ALPHA;
1745 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend, alpha);
1746 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend, true);
1749 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_disable);
1752 * xilinx_drm_dp_sub_layer_get - Get the DP subsystem layer
1753 * @dp_sub: DP subsystem
1754 * @primary: flag to indicate the primary plane
1756 * Check if there's any available layer based on the flag @primary, and return
1759 * Return: a DP subsystem layer on success, or -ENODEV error pointer.
1761 struct xilinx_drm_dp_sub_layer *
1762 xilinx_drm_dp_sub_layer_get(struct xilinx_drm_dp_sub *dp_sub, bool primary)
1764 struct xilinx_drm_dp_sub_layer *layer = NULL;
1767 for (i = 0; i < XILINX_DRM_DP_SUB_NUM_LAYERS; i++) {
1768 if (dp_sub->layers[i].primary == primary) {
1769 layer = &dp_sub->layers[i];
1774 if (!layer || !layer->avail)
1775 return ERR_PTR(-ENODEV);
1779 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_get);
1782 * xilinx_drm_dp_sub_layer_get - Put the DP subsystem layer
1783 * @dp_sub: DP subsystem
1784 * @layer: DP subsystem layer
1786 * Return the DP subsystem layer @layer when it's no longer used.
1788 void xilinx_drm_dp_sub_layer_put(struct xilinx_drm_dp_sub *dp_sub,
1789 struct xilinx_drm_dp_sub_layer *layer)
1791 layer->avail = true;
1793 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_put);
1795 /* DP subsystem functions */
1798 * xilinx_drm_dp_sub_set_output_fmt - Set the output format
1799 * @dp_sub: DP subsystem
1800 * @drm_fmt: DRM format to set
1802 * Set the output format of the DP subsystem. The flag @primary indicates that
1803 * which layer to configure.
1805 * Return: 0 on success, or -EINVAL if @drm_fmt is not supported for output.
1807 int xilinx_drm_dp_sub_set_output_fmt(struct xilinx_drm_dp_sub *dp_sub,
1810 const struct xilinx_drm_dp_sub_fmt *fmt;
1812 fmt = xilinx_drm_dp_sub_map_fmt(blend_output_fmts,
1813 ARRAY_SIZE(blend_output_fmts), drm_fmt);
1817 xilinx_drm_dp_sub_blend_set_output_fmt(&dp_sub->blend, fmt->dp_sub_fmt);
1821 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_set_output_fmt);
1824 * xilinx_drm_dp_sub_set_bg_color - Set the background color
1825 * @dp_sub: DP subsystem
1826 * @c0: color component 0
1827 * @c1: color component 1
1828 * @c2: color component 2
1830 * Set the background color with given color components (@c0, @c1, @c2).
1832 void xilinx_drm_dp_sub_set_bg_color(struct xilinx_drm_dp_sub *dp_sub,
1833 u32 c0, u32 c1, u32 c2)
1835 xilinx_drm_dp_sub_blend_set_bg_color(&dp_sub->blend, c0, c1, c2);
1836 xilinx_drm_dp_sub_debugfs_bg_color(dp_sub);
1838 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_set_bg_color);
1841 * xilinx_drm_dp_sub_set_alpha - Set the alpha value
1842 * @dp_sub: DP subsystem
1843 * @alpha: alpha value to set
1845 * Set the alpha value for blending.
1847 void xilinx_drm_dp_sub_set_alpha(struct xilinx_drm_dp_sub *dp_sub, u32 alpha)
1849 dp_sub->alpha = alpha;
1850 if (dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].enabled &&
1851 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].enabled)
1852 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend, alpha);
1854 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_set_alpha);
1857 * xilinx_drm_dp_sub_enable_alpha - Enable/disable the global alpha blending
1858 * @dp_sub: DP subsystem
1859 * @enable: flag to enable or disable alpha blending
1861 * Set the alpha value for blending.
1864 xilinx_drm_dp_sub_enable_alpha(struct xilinx_drm_dp_sub *dp_sub, bool enable)
1866 dp_sub->alpha_en = enable;
1867 if (dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].enabled &&
1868 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].enabled)
1869 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend, enable);
1871 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_enable_alpha);
1874 * xilinx_drm_dp_sub_handle_vblank - Vblank handling wrapper
1875 * @dp_sub: DP subsystem
1877 * Trigger the registered vblank handler. This function is supposed to be
1878 * called in the actual vblank handler.
1880 void xilinx_drm_dp_sub_handle_vblank(struct xilinx_drm_dp_sub *dp_sub)
1882 if (dp_sub->vblank_fn)
1883 dp_sub->vblank_fn(dp_sub->vblank_data);
1885 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_handle_vblank);
1888 * xilinx_drm_dp_sub_enable_vblank - Enable the vblank handling
1889 * @dp_sub: DP subsystem
1890 * @vblank_fn: callback to be called on vblank event
1891 * @vblank_data: data to be used in @vblank_fn
1893 * This function register the vblank handler, and the handler will be triggered
1894 * on vblank event after.
1896 void xilinx_drm_dp_sub_enable_vblank(struct xilinx_drm_dp_sub *dp_sub,
1897 void (*vblank_fn)(void *),
1900 dp_sub->vblank_fn = vblank_fn;
1901 dp_sub->vblank_data = vblank_data;
1903 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_enable_vblank);
1906 * xilinx_drm_dp_sub_disable_vblank - Disable the vblank handling
1907 * @dp_sub: DP subsystem
1909 * Disable the vblank handler. The vblank handler and data are unregistered.
1911 void xilinx_drm_dp_sub_disable_vblank(struct xilinx_drm_dp_sub *dp_sub)
1913 dp_sub->vblank_fn = NULL;
1914 dp_sub->vblank_data = NULL;
1916 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_disable_vblank);
1919 * xilinx_drm_dp_sub_enable - Enable the DP subsystem
1920 * @dp_sub: DP subsystem
1922 * Enable the DP subsystem.
1924 void xilinx_drm_dp_sub_enable(struct xilinx_drm_dp_sub *dp_sub)
1926 const struct xilinx_drm_dp_sub_fmt *vid_fmt;
1927 const struct xilinx_drm_dp_sub_fmt *gfx_fmt;
1929 vid_fmt = dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].fmt;
1930 gfx_fmt = dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].fmt;
1931 xilinx_drm_dp_sub_av_buf_enable(&dp_sub->av_buf);
1932 xilinx_drm_dp_sub_av_buf_init_fmts(&dp_sub->av_buf, vid_fmt, gfx_fmt);
1933 xilinx_drm_dp_sub_av_buf_init_sf(&dp_sub->av_buf, vid_fmt, gfx_fmt);
1934 xilinx_drm_dp_sub_av_buf_set_vid_clock_src(&dp_sub->av_buf,
1935 !dp_sub->vid_clk_pl);
1936 xilinx_drm_dp_sub_av_buf_set_vid_timing_src(&dp_sub->av_buf, true);
1937 xilinx_drm_dp_sub_av_buf_set_aud_clock_src(&dp_sub->av_buf, true);
1938 xilinx_drm_dp_sub_av_buf_enable_buf(&dp_sub->av_buf);
1939 xilinx_drm_dp_sub_av_buf_enable_aud(&dp_sub->av_buf);
1940 xilinx_drm_dp_sub_aud_init(&dp_sub->aud);
1942 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_enable);
1945 * xilinx_drm_dp_sub_enable - Disable the DP subsystem
1946 * @dp_sub: DP subsystem
1948 * Disable the DP subsystem.
1950 void xilinx_drm_dp_sub_disable(struct xilinx_drm_dp_sub *dp_sub)
1952 xilinx_drm_dp_sub_aud_deinit(&dp_sub->aud);
1953 xilinx_drm_dp_sub_av_buf_disable_aud(&dp_sub->av_buf);
1954 xilinx_drm_dp_sub_av_buf_disable_buf(&dp_sub->av_buf);
1955 xilinx_drm_dp_sub_av_buf_disable(&dp_sub->av_buf);
1957 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_disable);
1959 /* DP subsystem initialization functions */
1962 * xilinx_drm_dp_sub_of_get - Get the DP subsystem instance
1963 * @np: parent device node
1965 * This function searches and returns a DP subsystem structure for
1966 * the parent device node, @np. The DP subsystem node should be a child node of
1967 * @np, with 'xlnx,dp-sub' property pointing to the DP device node. An instance
1968 * can be shared by multiple users.
1970 * Return: corresponding DP subsystem structure if found. NULL if
1971 * the device node doesn't have 'xlnx,dp-sub' property, or -EPROBE_DEFER error
1972 * pointer if the the DP subsystem isn't found.
1974 struct xilinx_drm_dp_sub *xilinx_drm_dp_sub_of_get(struct device_node *np)
1976 struct device_node *xilinx_drm_dp_sub_node;
1977 struct xilinx_drm_dp_sub *found = NULL;
1978 struct xilinx_drm_dp_sub *dp_sub;
1980 if (!of_find_property(np, "xlnx,dp-sub", NULL))
1983 xilinx_drm_dp_sub_node = of_parse_phandle(np, "xlnx,dp-sub", 0);
1984 if (!xilinx_drm_dp_sub_node)
1985 return ERR_PTR(-EINVAL);
1987 mutex_lock(&xilinx_drm_dp_sub_lock);
1988 list_for_each_entry(dp_sub, &xilinx_drm_dp_sub_list, list) {
1989 if (dp_sub->dev->of_node == xilinx_drm_dp_sub_node) {
1994 mutex_unlock(&xilinx_drm_dp_sub_lock);
1996 of_node_put(xilinx_drm_dp_sub_node);
1999 return ERR_PTR(-EPROBE_DEFER);
2003 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_of_get);
2006 * xilinx_drm_dp_sub_put - Put the DP subsystem instance
2007 * @dp_sub: DP subsystem
2009 * Put the DP subsystem instance @dp_sub.
2011 void xilinx_drm_dp_sub_put(struct xilinx_drm_dp_sub *dp_sub)
2015 EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_put);
2018 * xilinx_drm_dp_register_device - Register the DP subsystem to the global list
2019 * @dp_sub: DP subsystem
2021 * Register the DP subsystem instance to the global list
2023 static void xilinx_drm_dp_sub_register_device(struct xilinx_drm_dp_sub *dp_sub)
2025 mutex_lock(&xilinx_drm_dp_sub_lock);
2026 list_add_tail(&dp_sub->list, &xilinx_drm_dp_sub_list);
2027 mutex_unlock(&xilinx_drm_dp_sub_lock);
2031 * xilinx_drm_dp_register_device - Unregister the DP subsystem instance
2032 * @dp_sub: DP subsystem
2034 * Unregister the DP subsystem instance from the global list
2037 xilinx_drm_dp_sub_unregister_device(struct xilinx_drm_dp_sub *dp_sub)
2039 mutex_lock(&xilinx_drm_dp_sub_lock);
2040 list_del(&dp_sub->list);
2041 mutex_unlock(&xilinx_drm_dp_sub_lock);
2045 * xilinx_drm_dp_sub_parse_of - Parse the DP subsystem device tree node
2046 * @dp_sub: DP subsystem
2048 * Parse the DP subsystem device tree node.
2050 * Return: 0 on success, or the corresponding error code.
2052 static int xilinx_drm_dp_sub_parse_of(struct xilinx_drm_dp_sub *dp_sub)
2054 struct device_node *node = dp_sub->dev->of_node;
2055 struct xilinx_drm_dp_sub_layer *layer;
2060 ret = of_property_read_string(node, "xlnx,output-fmt", &string);
2062 dev_err(dp_sub->dev, "No colormetry in DT\n");
2066 if (strcmp(string, "rgb") == 0) {
2067 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB;
2068 } else if (strcmp(string, "ycrcb444") == 0) {
2069 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR444;
2070 } else if (strcmp(string, "ycrcb422") == 0) {
2071 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR422;
2072 fmt |= XILINX_DP_SUB_V_BLEND_OUTPUT_EN_DOWNSAMPLE;
2073 } else if (strcmp(string, "yonly") == 0) {
2074 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YONLY;
2076 dev_err(dp_sub->dev, "Invalid output format in DT\n");
2080 xilinx_drm_writel(dp_sub->blend.base,
2081 XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT, fmt);
2083 if (fmt != XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB) {
2084 u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
2085 0x7d4d, 0x7ab3, 0x800,
2086 0x800, 0x794d, 0x7eb3 };
2087 u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
2090 /* Hardcode SDTV coefficients. Can be runtime configurable */
2091 offset = XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF0;
2092 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_COEFF; i++)
2093 xilinx_drm_writel(dp_sub->blend.base, offset + i * 4,
2096 offset = XILINX_DP_SUB_V_BLEND_LUMA_OUTCSC_OFFSET;
2097 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_OFFSET; i++)
2098 xilinx_drm_writel(dp_sub->blend.base, offset + i * 4,
2099 full_range_offsets[i]);
2102 if (of_property_read_bool(node, "xlnx,vid-primary"))
2103 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].primary = true;
2105 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].primary = true;
2107 ret = of_property_read_string(node, "xlnx,vid-fmt", &string);
2109 layer = &dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID];
2110 size = ARRAY_SIZE(av_buf_vid_fmts);
2111 layer->num_fmts = size;
2112 layer->drm_fmts = devm_kzalloc(dp_sub->dev,
2113 sizeof(*layer->drm_fmts) * size,
2115 if (!layer->drm_fmts)
2118 for (i = 0; i < layer->num_fmts; i++) {
2119 const struct xilinx_drm_dp_sub_fmt *fmt =
2120 &av_buf_vid_fmts[i];
2122 if (strcmp(string, fmt->name) == 0)
2125 layer->drm_fmts[i] = fmt->drm_fmt;
2129 dev_info(dp_sub->dev, "Invalid vid-fmt in DT\n");
2130 layer->fmt = &av_buf_vid_fmts[0];
2134 ret = of_property_read_string(node, "xlnx,gfx-fmt", &string);
2136 layer = &dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX];
2137 size = ARRAY_SIZE(av_buf_gfx_fmts);
2138 layer->num_fmts = size;
2139 layer->drm_fmts = devm_kzalloc(dp_sub->dev,
2140 sizeof(*layer->drm_fmts) * size,
2142 if (!layer->drm_fmts)
2145 for (i = 0; i < layer->num_fmts; i++) {
2146 const struct xilinx_drm_dp_sub_fmt *fmt =
2147 &av_buf_gfx_fmts[i];
2149 if (strcmp(string, fmt->name) == 0)
2152 layer->drm_fmts[i] = fmt->drm_fmt;
2156 dev_info(dp_sub->dev, "Invalid vid-fmt in DT\n");
2157 layer->fmt = &av_buf_gfx_fmts[0];
2161 dp_sub->vid_clk_pl = of_property_read_bool(node, "xlnx,vid-clk-pl");
2166 static int xilinx_drm_dp_sub_probe(struct platform_device *pdev)
2168 struct xilinx_drm_dp_sub *dp_sub;
2169 struct resource *res;
2172 dp_sub = devm_kzalloc(&pdev->dev, sizeof(*dp_sub), GFP_KERNEL);
2176 dp_sub->dev = &pdev->dev;
2178 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
2179 dp_sub->blend.base = devm_ioremap_resource(&pdev->dev, res);
2180 if (IS_ERR(dp_sub->blend.base))
2181 return PTR_ERR(dp_sub->blend.base);
2183 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
2184 dp_sub->av_buf.base = devm_ioremap_resource(&pdev->dev, res);
2185 if (IS_ERR(dp_sub->av_buf.base))
2186 return PTR_ERR(dp_sub->av_buf.base);
2188 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
2189 dp_sub->aud.base = devm_ioremap_resource(&pdev->dev, res);
2190 if (IS_ERR(dp_sub->aud.base))
2191 return PTR_ERR(dp_sub->aud.base);
2193 dp_sub->layers[0].id = XILINX_DRM_DP_SUB_LAYER_VID;
2194 dp_sub->layers[0].offset = 0;
2195 dp_sub->layers[0].avail = true;
2196 dp_sub->layers[0].other = &dp_sub->layers[1];
2198 dp_sub->layers[1].id = XILINX_DRM_DP_SUB_LAYER_GFX;
2199 dp_sub->layers[1].offset = 4;
2200 dp_sub->layers[1].avail = true;
2201 dp_sub->layers[1].other = &dp_sub->layers[0];
2203 ret = xilinx_drm_dp_sub_parse_of(dp_sub);
2207 platform_set_drvdata(pdev, dp_sub);
2209 xilinx_drm_dp_sub_register_device(dp_sub);
2211 xilinx_dp_sub_debugfs_init(dp_sub);
2213 dev_info(dp_sub->dev, "Xilinx DisplayPort Subsystem is probed\n");
2218 static int xilinx_drm_dp_sub_remove(struct platform_device *pdev)
2220 struct xilinx_drm_dp_sub *dp_sub = platform_get_drvdata(pdev);
2222 xilinx_drm_dp_sub_unregister_device(dp_sub);
2227 static const struct of_device_id xilinx_drm_dp_sub_of_id_table[] = {
2228 { .compatible = "xlnx,dp-sub" },
2231 MODULE_DEVICE_TABLE(of, xilinx_drm_dp_sub_of_id_table);
2233 static struct platform_driver xilinx_drm_dp_sub_driver = {
2235 .name = "xilinx-drm-dp-sub",
2236 .of_match_table = xilinx_drm_dp_sub_of_id_table,
2238 .probe = xilinx_drm_dp_sub_probe,
2239 .remove = xilinx_drm_dp_sub_remove,
2242 module_platform_driver(xilinx_drm_dp_sub_driver);
2244 MODULE_DESCRIPTION("Xilinx DisplayPort Subsystem Driver");
2245 MODULE_LICENSE("GPL v2");