1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * ZynqMP DisplayPort Driver |
4 | * |
5 | * Copyright (C) 2017 - 2020 Xilinx, Inc. |
6 | * |
7 | * Authors: |
8 | * - Hyun Woo Kwon <hyun.kwon@xilinx.com> |
9 | * - Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
10 | */ |
11 | |
12 | #include <drm/display/drm_dp_helper.h> |
13 | #include <drm/drm_atomic_helper.h> |
14 | #include <drm/drm_crtc.h> |
15 | #include <drm/drm_device.h> |
16 | #include <drm/drm_edid.h> |
17 | #include <drm/drm_fourcc.h> |
18 | #include <drm/drm_modes.h> |
19 | #include <drm/drm_of.h> |
20 | |
21 | #include <linux/clk.h> |
22 | #include <linux/delay.h> |
23 | #include <linux/device.h> |
24 | #include <linux/io.h> |
25 | #include <linux/module.h> |
26 | #include <linux/platform_device.h> |
27 | #include <linux/pm_runtime.h> |
28 | #include <linux/phy/phy.h> |
29 | #include <linux/reset.h> |
30 | #include <linux/slab.h> |
31 | |
32 | #include "zynqmp_disp.h" |
33 | #include "zynqmp_dp.h" |
34 | #include "zynqmp_dpsub.h" |
35 | #include "zynqmp_kms.h" |
36 | |
37 | static uint zynqmp_dp_aux_timeout_ms = 50; |
38 | module_param_named(aux_timeout_ms, zynqmp_dp_aux_timeout_ms, uint, 0444); |
39 | MODULE_PARM_DESC(aux_timeout_ms, "DP aux timeout value in msec (default: 50)" ); |
40 | |
41 | /* |
42 | * Some sink requires a delay after power on request |
43 | */ |
44 | static uint zynqmp_dp_power_on_delay_ms = 4; |
45 | module_param_named(power_on_delay_ms, zynqmp_dp_power_on_delay_ms, uint, 0444); |
46 | MODULE_PARM_DESC(power_on_delay_ms, "DP power on delay in msec (default: 4)" ); |
47 | |
48 | /* Link configuration registers */ |
49 | #define ZYNQMP_DP_LINK_BW_SET 0x0 |
50 | #define ZYNQMP_DP_LANE_COUNT_SET 0x4 |
51 | #define ZYNQMP_DP_ENHANCED_FRAME_EN 0x8 |
52 | #define ZYNQMP_DP_TRAINING_PATTERN_SET 0xc |
53 | #define ZYNQMP_DP_SCRAMBLING_DISABLE 0x14 |
54 | #define ZYNQMP_DP_DOWNSPREAD_CTL 0x18 |
55 | #define ZYNQMP_DP_SOFTWARE_RESET 0x1c |
56 | #define ZYNQMP_DP_SOFTWARE_RESET_STREAM1 BIT(0) |
57 | #define ZYNQMP_DP_SOFTWARE_RESET_STREAM2 BIT(1) |
58 | #define ZYNQMP_DP_SOFTWARE_RESET_STREAM3 BIT(2) |
59 | #define ZYNQMP_DP_SOFTWARE_RESET_STREAM4 BIT(3) |
60 | #define ZYNQMP_DP_SOFTWARE_RESET_AUX BIT(7) |
61 | #define ZYNQMP_DP_SOFTWARE_RESET_ALL (ZYNQMP_DP_SOFTWARE_RESET_STREAM1 | \ |
62 | ZYNQMP_DP_SOFTWARE_RESET_STREAM2 | \ |
63 | ZYNQMP_DP_SOFTWARE_RESET_STREAM3 | \ |
64 | ZYNQMP_DP_SOFTWARE_RESET_STREAM4 | \ |
65 | ZYNQMP_DP_SOFTWARE_RESET_AUX) |
66 | |
67 | /* Core enable registers */ |
68 | #define ZYNQMP_DP_TRANSMITTER_ENABLE 0x80 |
69 | #define ZYNQMP_DP_MAIN_STREAM_ENABLE 0x84 |
70 | #define ZYNQMP_DP_FORCE_SCRAMBLER_RESET 0xc0 |
71 | #define ZYNQMP_DP_VERSION 0xf8 |
72 | #define ZYNQMP_DP_VERSION_MAJOR_MASK GENMASK(31, 24) |
73 | #define ZYNQMP_DP_VERSION_MAJOR_SHIFT 24 |
74 | #define ZYNQMP_DP_VERSION_MINOR_MASK GENMASK(23, 16) |
75 | #define ZYNQMP_DP_VERSION_MINOR_SHIFT 16 |
76 | #define ZYNQMP_DP_VERSION_REVISION_MASK GENMASK(15, 12) |
77 | #define ZYNQMP_DP_VERSION_REVISION_SHIFT 12 |
78 | #define ZYNQMP_DP_VERSION_PATCH_MASK GENMASK(11, 8) |
79 | #define ZYNQMP_DP_VERSION_PATCH_SHIFT 8 |
80 | #define ZYNQMP_DP_VERSION_INTERNAL_MASK GENMASK(7, 0) |
81 | #define ZYNQMP_DP_VERSION_INTERNAL_SHIFT 0 |
82 | |
83 | /* Core ID registers */ |
84 | #define ZYNQMP_DP_CORE_ID 0xfc |
85 | #define ZYNQMP_DP_CORE_ID_MAJOR_MASK GENMASK(31, 24) |
86 | #define ZYNQMP_DP_CORE_ID_MAJOR_SHIFT 24 |
87 | #define ZYNQMP_DP_CORE_ID_MINOR_MASK GENMASK(23, 16) |
88 | #define ZYNQMP_DP_CORE_ID_MINOR_SHIFT 16 |
89 | #define ZYNQMP_DP_CORE_ID_REVISION_MASK GENMASK(15, 8) |
90 | #define ZYNQMP_DP_CORE_ID_REVISION_SHIFT 8 |
91 | #define ZYNQMP_DP_CORE_ID_DIRECTION GENMASK(1) |
92 | |
93 | /* AUX channel interface registers */ |
94 | #define ZYNQMP_DP_AUX_COMMAND 0x100 |
95 | #define ZYNQMP_DP_AUX_COMMAND_CMD_SHIFT 8 |
96 | #define ZYNQMP_DP_AUX_COMMAND_ADDRESS_ONLY BIT(12) |
97 | #define ZYNQMP_DP_AUX_COMMAND_BYTES_SHIFT 0 |
98 | #define ZYNQMP_DP_AUX_WRITE_FIFO 0x104 |
99 | #define ZYNQMP_DP_AUX_ADDRESS 0x108 |
100 | #define ZYNQMP_DP_AUX_CLK_DIVIDER 0x10c |
101 | #define ZYNQMP_DP_AUX_CLK_DIVIDER_AUX_FILTER_SHIFT 8 |
102 | #define ZYNQMP_DP_INTERRUPT_SIGNAL_STATE 0x130 |
103 | #define ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_HPD BIT(0) |
104 | #define ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REQUEST BIT(1) |
105 | #define ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY BIT(2) |
106 | #define ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT BIT(3) |
107 | #define ZYNQMP_DP_AUX_REPLY_DATA 0x134 |
108 | #define ZYNQMP_DP_AUX_REPLY_CODE 0x138 |
109 | #define ZYNQMP_DP_AUX_REPLY_CODE_AUX_ACK (0) |
110 | #define ZYNQMP_DP_AUX_REPLY_CODE_AUX_NACK BIT(0) |
111 | #define ZYNQMP_DP_AUX_REPLY_CODE_AUX_DEFER BIT(1) |
112 | #define ZYNQMP_DP_AUX_REPLY_CODE_I2C_ACK (0) |
113 | #define ZYNQMP_DP_AUX_REPLY_CODE_I2C_NACK BIT(2) |
114 | #define ZYNQMP_DP_AUX_REPLY_CODE_I2C_DEFER BIT(3) |
115 | #define ZYNQMP_DP_AUX_REPLY_COUNT 0x13c |
116 | #define ZYNQMP_DP_REPLY_DATA_COUNT 0x148 |
117 | #define ZYNQMP_DP_REPLY_DATA_COUNT_MASK 0xff |
118 | #define ZYNQMP_DP_INT_STATUS 0x3a0 |
119 | #define ZYNQMP_DP_INT_MASK 0x3a4 |
120 | #define ZYNQMP_DP_INT_EN 0x3a8 |
121 | #define ZYNQMP_DP_INT_DS 0x3ac |
122 | #define ZYNQMP_DP_INT_HPD_IRQ BIT(0) |
123 | #define ZYNQMP_DP_INT_HPD_EVENT BIT(1) |
124 | #define ZYNQMP_DP_INT_REPLY_RECEIVED BIT(2) |
125 | #define ZYNQMP_DP_INT_REPLY_TIMEOUT BIT(3) |
126 | #define ZYNQMP_DP_INT_HPD_PULSE_DET BIT(4) |
127 | #define ZYNQMP_DP_INT_EXT_PKT_TXD BIT(5) |
128 | #define ZYNQMP_DP_INT_LIV_ABUF_UNDRFLW BIT(12) |
129 | #define ZYNQMP_DP_INT_VBLANK_START BIT(13) |
130 | #define ZYNQMP_DP_INT_PIXEL1_MATCH BIT(14) |
131 | #define ZYNQMP_DP_INT_PIXEL0_MATCH BIT(15) |
132 | #define ZYNQMP_DP_INT_CHBUF_UNDERFLW_MASK 0x3f0000 |
133 | #define ZYNQMP_DP_INT_CHBUF_OVERFLW_MASK 0xfc00000 |
134 | #define ZYNQMP_DP_INT_CUST_TS_2 BIT(28) |
135 | #define ZYNQMP_DP_INT_CUST_TS BIT(29) |
136 | #define ZYNQMP_DP_INT_EXT_VSYNC_TS BIT(30) |
137 | #define ZYNQMP_DP_INT_VSYNC_TS BIT(31) |
138 | #define ZYNQMP_DP_INT_ALL (ZYNQMP_DP_INT_HPD_IRQ | \ |
139 | ZYNQMP_DP_INT_HPD_EVENT | \ |
140 | ZYNQMP_DP_INT_CHBUF_UNDERFLW_MASK | \ |
141 | ZYNQMP_DP_INT_CHBUF_OVERFLW_MASK) |
142 | |
143 | /* Main stream attribute registers */ |
144 | #define ZYNQMP_DP_MAIN_STREAM_HTOTAL 0x180 |
145 | #define ZYNQMP_DP_MAIN_STREAM_VTOTAL 0x184 |
146 | #define ZYNQMP_DP_MAIN_STREAM_POLARITY 0x188 |
147 | #define ZYNQMP_DP_MAIN_STREAM_POLARITY_HSYNC_SHIFT 0 |
148 | #define ZYNQMP_DP_MAIN_STREAM_POLARITY_VSYNC_SHIFT 1 |
149 | #define ZYNQMP_DP_MAIN_STREAM_HSWIDTH 0x18c |
150 | #define ZYNQMP_DP_MAIN_STREAM_VSWIDTH 0x190 |
151 | #define ZYNQMP_DP_MAIN_STREAM_HRES 0x194 |
152 | #define ZYNQMP_DP_MAIN_STREAM_VRES 0x198 |
153 | #define ZYNQMP_DP_MAIN_STREAM_HSTART 0x19c |
154 | #define ZYNQMP_DP_MAIN_STREAM_VSTART 0x1a0 |
155 | #define ZYNQMP_DP_MAIN_STREAM_MISC0 0x1a4 |
156 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK BIT(0) |
157 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_RGB (0 << 1) |
158 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_422 (5 << 1) |
159 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_444 (6 << 1) |
160 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_MASK (7 << 1) |
161 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_DYNAMIC_RANGE BIT(3) |
162 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_YCBCR_COLR BIT(4) |
163 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_6 (0 << 5) |
164 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8 (1 << 5) |
165 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_10 (2 << 5) |
166 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_12 (3 << 5) |
167 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_16 (4 << 5) |
168 | #define ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_MASK (7 << 5) |
169 | #define ZYNQMP_DP_MAIN_STREAM_MISC1 0x1a8 |
170 | #define ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN BIT(7) |
171 | #define ZYNQMP_DP_MAIN_STREAM_M_VID 0x1ac |
172 | #define ZYNQMP_DP_MSA_TRANSFER_UNIT_SIZE 0x1b0 |
173 | #define ZYNQMP_DP_MSA_TRANSFER_UNIT_SIZE_TU_SIZE_DEF 64 |
174 | #define ZYNQMP_DP_MAIN_STREAM_N_VID 0x1b4 |
175 | #define ZYNQMP_DP_USER_PIX_WIDTH 0x1b8 |
176 | #define ZYNQMP_DP_USER_DATA_COUNT_PER_LANE 0x1bc |
177 | #define ZYNQMP_DP_MIN_BYTES_PER_TU 0x1c4 |
178 | #define ZYNQMP_DP_FRAC_BYTES_PER_TU 0x1c8 |
179 | #define ZYNQMP_DP_INIT_WAIT 0x1cc |
180 | |
181 | /* PHY configuration and status registers */ |
182 | #define ZYNQMP_DP_PHY_RESET 0x200 |
183 | #define ZYNQMP_DP_PHY_RESET_PHY_RESET BIT(0) |
184 | #define ZYNQMP_DP_PHY_RESET_GTTX_RESET BIT(1) |
185 | #define ZYNQMP_DP_PHY_RESET_PHY_PMA_RESET BIT(8) |
186 | #define ZYNQMP_DP_PHY_RESET_PHY_PCS_RESET BIT(9) |
187 | #define ZYNQMP_DP_PHY_RESET_ALL_RESET (ZYNQMP_DP_PHY_RESET_PHY_RESET | \ |
188 | ZYNQMP_DP_PHY_RESET_GTTX_RESET | \ |
189 | ZYNQMP_DP_PHY_RESET_PHY_PMA_RESET | \ |
190 | ZYNQMP_DP_PHY_RESET_PHY_PCS_RESET) |
191 | #define ZYNQMP_DP_PHY_PREEMPHASIS_LANE_0 0x210 |
192 | #define ZYNQMP_DP_PHY_PREEMPHASIS_LANE_1 0x214 |
193 | #define ZYNQMP_DP_PHY_PREEMPHASIS_LANE_2 0x218 |
194 | #define ZYNQMP_DP_PHY_PREEMPHASIS_LANE_3 0x21c |
195 | #define ZYNQMP_DP_PHY_VOLTAGE_DIFF_LANE_0 0x220 |
196 | #define ZYNQMP_DP_PHY_VOLTAGE_DIFF_LANE_1 0x224 |
197 | #define ZYNQMP_DP_PHY_VOLTAGE_DIFF_LANE_2 0x228 |
198 | #define ZYNQMP_DP_PHY_VOLTAGE_DIFF_LANE_3 0x22c |
199 | #define ZYNQMP_DP_PHY_CLOCK_SELECT 0x234 |
200 | #define ZYNQMP_DP_PHY_CLOCK_SELECT_1_62G 0x1 |
201 | #define ZYNQMP_DP_PHY_CLOCK_SELECT_2_70G 0x3 |
202 | #define ZYNQMP_DP_PHY_CLOCK_SELECT_5_40G 0x5 |
203 | #define ZYNQMP_DP_TX_PHY_POWER_DOWN 0x238 |
204 | #define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_0 BIT(0) |
205 | #define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_1 BIT(1) |
206 | #define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_2 BIT(2) |
207 | #define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_3 BIT(3) |
208 | #define ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL 0xf |
209 | #define ZYNQMP_DP_PHY_PRECURSOR_LANE_0 0x23c |
210 | #define ZYNQMP_DP_PHY_PRECURSOR_LANE_1 0x240 |
211 | #define ZYNQMP_DP_PHY_PRECURSOR_LANE_2 0x244 |
212 | #define ZYNQMP_DP_PHY_PRECURSOR_LANE_3 0x248 |
213 | #define ZYNQMP_DP_PHY_POSTCURSOR_LANE_0 0x24c |
214 | #define ZYNQMP_DP_PHY_POSTCURSOR_LANE_1 0x250 |
215 | #define ZYNQMP_DP_PHY_POSTCURSOR_LANE_2 0x254 |
216 | #define ZYNQMP_DP_PHY_POSTCURSOR_LANE_3 0x258 |
217 | #define ZYNQMP_DP_SUB_TX_PHY_PRECURSOR_LANE_0 0x24c |
218 | #define ZYNQMP_DP_SUB_TX_PHY_PRECURSOR_LANE_1 0x250 |
219 | #define ZYNQMP_DP_PHY_STATUS 0x280 |
220 | #define ZYNQMP_DP_PHY_STATUS_PLL_LOCKED_SHIFT 4 |
221 | #define ZYNQMP_DP_PHY_STATUS_FPGA_PLL_LOCKED BIT(6) |
222 | |
223 | /* Audio registers */ |
224 | #define ZYNQMP_DP_TX_AUDIO_CONTROL 0x300 |
225 | #define ZYNQMP_DP_TX_AUDIO_CHANNELS 0x304 |
226 | #define ZYNQMP_DP_TX_AUDIO_INFO_DATA 0x308 |
227 | #define ZYNQMP_DP_TX_M_AUD 0x328 |
228 | #define ZYNQMP_DP_TX_N_AUD 0x32c |
229 | #define ZYNQMP_DP_TX_AUDIO_EXT_DATA 0x330 |
230 | |
231 | #define ZYNQMP_DP_MAX_LANES 2 |
232 | #define ZYNQMP_MAX_FREQ 3000000 |
233 | |
234 | #define DP_REDUCED_BIT_RATE 162000 |
235 | #define DP_HIGH_BIT_RATE 270000 |
236 | #define DP_HIGH_BIT_RATE2 540000 |
237 | #define DP_MAX_TRAINING_TRIES 5 |
238 | #define DP_V1_2 0x12 |
239 | |
240 | /** |
241 | * struct zynqmp_dp_link_config - Common link config between source and sink |
242 | * @max_rate: maximum link rate |
243 | * @max_lanes: maximum number of lanes |
244 | */ |
245 | struct zynqmp_dp_link_config { |
246 | int max_rate; |
247 | u8 max_lanes; |
248 | }; |
249 | |
250 | /** |
251 | * struct zynqmp_dp_mode - Configured mode of DisplayPort |
252 | * @bw_code: code for bandwidth(link rate) |
253 | * @lane_cnt: number of lanes |
254 | * @pclock: pixel clock frequency of current mode |
255 | * @fmt: format identifier string |
256 | */ |
257 | struct zynqmp_dp_mode { |
258 | u8 bw_code; |
259 | u8 lane_cnt; |
260 | int pclock; |
261 | const char *fmt; |
262 | }; |
263 | |
264 | /** |
265 | * struct zynqmp_dp_config - Configuration of DisplayPort from DTS |
266 | * @misc0: misc0 configuration (per DP v1.2 spec) |
267 | * @misc1: misc1 configuration (per DP v1.2 spec) |
268 | * @bpp: bits per pixel |
269 | */ |
270 | struct zynqmp_dp_config { |
271 | u8 misc0; |
272 | u8 misc1; |
273 | u8 bpp; |
274 | }; |
275 | |
276 | /** |
277 | * struct zynqmp_dp - Xilinx DisplayPort core |
278 | * @dev: device structure |
279 | * @dpsub: Display subsystem |
280 | * @iomem: device I/O memory for register access |
281 | * @reset: reset controller |
282 | * @irq: irq |
283 | * @bridge: DRM bridge for the DP encoder |
284 | * @next_bridge: The downstream bridge |
285 | * @config: IP core configuration from DTS |
286 | * @aux: aux channel |
287 | * @phy: PHY handles for DP lanes |
288 | * @num_lanes: number of enabled phy lanes |
289 | * @hpd_work: hot plug detection worker |
290 | * @status: connection status |
291 | * @enabled: flag to indicate if the device is enabled |
292 | * @dpcd: DP configuration data from currently connected sink device |
293 | * @link_config: common link configuration between IP core and sink device |
294 | * @mode: current mode between IP core and sink device |
295 | * @train_set: set of training data |
296 | */ |
297 | struct zynqmp_dp { |
298 | struct device *dev; |
299 | struct zynqmp_dpsub *dpsub; |
300 | void __iomem *iomem; |
301 | struct reset_control *reset; |
302 | int irq; |
303 | |
304 | struct drm_bridge bridge; |
305 | struct drm_bridge *next_bridge; |
306 | |
307 | struct zynqmp_dp_config config; |
308 | struct drm_dp_aux aux; |
309 | struct phy *phy[ZYNQMP_DP_MAX_LANES]; |
310 | u8 num_lanes; |
311 | struct delayed_work hpd_work; |
312 | enum drm_connector_status status; |
313 | bool enabled; |
314 | |
315 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
316 | struct zynqmp_dp_link_config link_config; |
317 | struct zynqmp_dp_mode mode; |
318 | u8 train_set[ZYNQMP_DP_MAX_LANES]; |
319 | }; |
320 | |
321 | static inline struct zynqmp_dp *bridge_to_dp(struct drm_bridge *bridge) |
322 | { |
323 | return container_of(bridge, struct zynqmp_dp, bridge); |
324 | } |
325 | |
326 | static void zynqmp_dp_write(struct zynqmp_dp *dp, int offset, u32 val) |
327 | { |
328 | writel(val, addr: dp->iomem + offset); |
329 | } |
330 | |
331 | static u32 zynqmp_dp_read(struct zynqmp_dp *dp, int offset) |
332 | { |
333 | return readl(addr: dp->iomem + offset); |
334 | } |
335 | |
336 | static void zynqmp_dp_clr(struct zynqmp_dp *dp, int offset, u32 clr) |
337 | { |
338 | zynqmp_dp_write(dp, offset, val: zynqmp_dp_read(dp, offset) & ~clr); |
339 | } |
340 | |
341 | static void zynqmp_dp_set(struct zynqmp_dp *dp, int offset, u32 set) |
342 | { |
343 | zynqmp_dp_write(dp, offset, val: zynqmp_dp_read(dp, offset) | set); |
344 | } |
345 | |
346 | /* ----------------------------------------------------------------------------- |
347 | * PHY Handling |
348 | */ |
349 | |
350 | #define RST_TIMEOUT_MS 1000 |
351 | |
352 | static int zynqmp_dp_reset(struct zynqmp_dp *dp, bool assert) |
353 | { |
354 | unsigned long timeout; |
355 | |
356 | if (assert) |
357 | reset_control_assert(rstc: dp->reset); |
358 | else |
359 | reset_control_deassert(rstc: dp->reset); |
360 | |
361 | /* Wait for the (de)assert to complete. */ |
362 | timeout = jiffies + msecs_to_jiffies(RST_TIMEOUT_MS); |
363 | while (!time_after_eq(jiffies, timeout)) { |
364 | bool status = !!reset_control_status(rstc: dp->reset); |
365 | |
366 | if (assert == status) |
367 | return 0; |
368 | |
369 | cpu_relax(); |
370 | } |
371 | |
372 | dev_err(dp->dev, "reset %s timeout\n" , assert ? "assert" : "deassert" ); |
373 | return -ETIMEDOUT; |
374 | } |
375 | |
376 | /** |
377 | * zynqmp_dp_phy_init - Initialize the phy |
378 | * @dp: DisplayPort IP core structure |
379 | * |
380 | * Initialize the phy. |
381 | * |
382 | * Return: 0 if the phy instances are initialized correctly, or the error code |
383 | * returned from the callee functions. |
384 | */ |
385 | static int zynqmp_dp_phy_init(struct zynqmp_dp *dp) |
386 | { |
387 | int ret; |
388 | int i; |
389 | |
390 | for (i = 0; i < dp->num_lanes; i++) { |
391 | ret = phy_init(phy: dp->phy[i]); |
392 | if (ret) { |
393 | dev_err(dp->dev, "failed to init phy lane %d\n" , i); |
394 | return ret; |
395 | } |
396 | } |
397 | |
398 | zynqmp_dp_clr(dp, ZYNQMP_DP_PHY_RESET, ZYNQMP_DP_PHY_RESET_ALL_RESET); |
399 | |
400 | /* |
401 | * Power on lanes in reverse order as only lane 0 waits for the PLL to |
402 | * lock. |
403 | */ |
404 | for (i = dp->num_lanes - 1; i >= 0; i--) { |
405 | ret = phy_power_on(phy: dp->phy[i]); |
406 | if (ret) { |
407 | dev_err(dp->dev, "failed to power on phy lane %d\n" , i); |
408 | return ret; |
409 | } |
410 | } |
411 | |
412 | return 0; |
413 | } |
414 | |
415 | /** |
416 | * zynqmp_dp_phy_exit - Exit the phy |
417 | * @dp: DisplayPort IP core structure |
418 | * |
419 | * Exit the phy. |
420 | */ |
421 | static void zynqmp_dp_phy_exit(struct zynqmp_dp *dp) |
422 | { |
423 | unsigned int i; |
424 | int ret; |
425 | |
426 | for (i = 0; i < dp->num_lanes; i++) { |
427 | ret = phy_power_off(phy: dp->phy[i]); |
428 | if (ret) |
429 | dev_err(dp->dev, "failed to power off phy(%d) %d\n" , i, |
430 | ret); |
431 | } |
432 | |
433 | for (i = 0; i < dp->num_lanes; i++) { |
434 | ret = phy_exit(phy: dp->phy[i]); |
435 | if (ret) |
436 | dev_err(dp->dev, "failed to exit phy(%d) %d\n" , i, ret); |
437 | } |
438 | } |
439 | |
440 | /** |
441 | * zynqmp_dp_phy_probe - Probe the PHYs |
442 | * @dp: DisplayPort IP core structure |
443 | * |
444 | * Probe PHYs for all lanes. Less PHYs may be available than the number of |
445 | * lanes, which is not considered an error as long as at least one PHY is |
446 | * found. The caller can check dp->num_lanes to check how many PHYs were found. |
447 | * |
448 | * Return: |
449 | * * 0 - Success |
450 | * * -ENXIO - No PHY found |
451 | * * -EPROBE_DEFER - Probe deferral requested |
452 | * * Other negative value - PHY retrieval failure |
453 | */ |
454 | static int zynqmp_dp_phy_probe(struct zynqmp_dp *dp) |
455 | { |
456 | unsigned int i; |
457 | |
458 | for (i = 0; i < ZYNQMP_DP_MAX_LANES; i++) { |
459 | char phy_name[16]; |
460 | struct phy *phy; |
461 | |
462 | snprintf(buf: phy_name, size: sizeof(phy_name), fmt: "dp-phy%d" , i); |
463 | phy = devm_phy_get(dev: dp->dev, string: phy_name); |
464 | |
465 | if (IS_ERR(ptr: phy)) { |
466 | switch (PTR_ERR(ptr: phy)) { |
467 | case -ENODEV: |
468 | if (dp->num_lanes) |
469 | return 0; |
470 | |
471 | dev_err(dp->dev, "no PHY found\n" ); |
472 | return -ENXIO; |
473 | |
474 | case -EPROBE_DEFER: |
475 | return -EPROBE_DEFER; |
476 | |
477 | default: |
478 | dev_err(dp->dev, "failed to get PHY lane %u\n" , |
479 | i); |
480 | return PTR_ERR(ptr: phy); |
481 | } |
482 | } |
483 | |
484 | dp->phy[i] = phy; |
485 | dp->num_lanes++; |
486 | } |
487 | |
488 | return 0; |
489 | } |
490 | |
491 | /** |
492 | * zynqmp_dp_phy_ready - Check if PHY is ready |
493 | * @dp: DisplayPort IP core structure |
494 | * |
495 | * Check if PHY is ready. If PHY is not ready, wait 1ms to check for 100 times. |
496 | * This amount of delay was suggested by IP designer. |
497 | * |
498 | * Return: 0 if PHY is ready, or -ENODEV if PHY is not ready. |
499 | */ |
500 | static int zynqmp_dp_phy_ready(struct zynqmp_dp *dp) |
501 | { |
502 | u32 i, reg, ready; |
503 | |
504 | ready = (1 << dp->num_lanes) - 1; |
505 | |
506 | /* Wait for 100 * 1ms. This should be enough time for PHY to be ready */ |
507 | for (i = 0; ; i++) { |
508 | reg = zynqmp_dp_read(dp, ZYNQMP_DP_PHY_STATUS); |
509 | if ((reg & ready) == ready) |
510 | return 0; |
511 | |
512 | if (i == 100) { |
513 | dev_err(dp->dev, "PHY isn't ready\n" ); |
514 | return -ENODEV; |
515 | } |
516 | |
517 | usleep_range(min: 1000, max: 1100); |
518 | } |
519 | |
520 | return 0; |
521 | } |
522 | |
523 | /* ----------------------------------------------------------------------------- |
524 | * DisplayPort Link Training |
525 | */ |
526 | |
527 | /** |
528 | * zynqmp_dp_max_rate - Calculate and return available max pixel clock |
529 | * @link_rate: link rate (Kilo-bytes / sec) |
530 | * @lane_num: number of lanes |
531 | * @bpp: bits per pixel |
532 | * |
533 | * Return: max pixel clock (KHz) supported by current link config. |
534 | */ |
535 | static inline int zynqmp_dp_max_rate(int link_rate, u8 lane_num, u8 bpp) |
536 | { |
537 | return link_rate * lane_num * 8 / bpp; |
538 | } |
539 | |
540 | /** |
541 | * zynqmp_dp_mode_configure - Configure the link values |
542 | * @dp: DisplayPort IP core structure |
543 | * @pclock: pixel clock for requested display mode |
544 | * @current_bw: current link rate |
545 | * |
546 | * Find the link configuration values, rate and lane count for requested pixel |
547 | * clock @pclock. The @pclock is stored in the mode to be used in other |
548 | * functions later. The returned rate is downshifted from the current rate |
549 | * @current_bw. |
550 | * |
551 | * Return: Current link rate code, or -EINVAL. |
552 | */ |
553 | static int zynqmp_dp_mode_configure(struct zynqmp_dp *dp, int pclock, |
554 | u8 current_bw) |
555 | { |
556 | int max_rate = dp->link_config.max_rate; |
557 | u8 bw_code; |
558 | u8 max_lanes = dp->link_config.max_lanes; |
559 | u8 max_link_rate_code = drm_dp_link_rate_to_bw_code(link_rate: max_rate); |
560 | u8 bpp = dp->config.bpp; |
561 | u8 lane_cnt; |
562 | |
563 | /* Downshift from current bandwidth */ |
564 | switch (current_bw) { |
565 | case DP_LINK_BW_5_4: |
566 | bw_code = DP_LINK_BW_2_7; |
567 | break; |
568 | case DP_LINK_BW_2_7: |
569 | bw_code = DP_LINK_BW_1_62; |
570 | break; |
571 | case DP_LINK_BW_1_62: |
572 | dev_err(dp->dev, "can't downshift. already lowest link rate\n" ); |
573 | return -EINVAL; |
574 | default: |
575 | /* If not given, start with max supported */ |
576 | bw_code = max_link_rate_code; |
577 | break; |
578 | } |
579 | |
580 | for (lane_cnt = 1; lane_cnt <= max_lanes; lane_cnt <<= 1) { |
581 | int bw; |
582 | u32 rate; |
583 | |
584 | bw = drm_dp_bw_code_to_link_rate(link_bw: bw_code); |
585 | rate = zynqmp_dp_max_rate(link_rate: bw, lane_num: lane_cnt, bpp); |
586 | if (pclock <= rate) { |
587 | dp->mode.bw_code = bw_code; |
588 | dp->mode.lane_cnt = lane_cnt; |
589 | dp->mode.pclock = pclock; |
590 | return dp->mode.bw_code; |
591 | } |
592 | } |
593 | |
594 | dev_err(dp->dev, "failed to configure link values\n" ); |
595 | |
596 | return -EINVAL; |
597 | } |
598 | |
599 | /** |
600 | * zynqmp_dp_adjust_train - Adjust train values |
601 | * @dp: DisplayPort IP core structure |
602 | * @link_status: link status from sink which contains requested training values |
603 | */ |
604 | static void zynqmp_dp_adjust_train(struct zynqmp_dp *dp, |
605 | u8 link_status[DP_LINK_STATUS_SIZE]) |
606 | { |
607 | u8 *train_set = dp->train_set; |
608 | u8 voltage = 0, preemphasis = 0; |
609 | u8 i; |
610 | |
611 | for (i = 0; i < dp->mode.lane_cnt; i++) { |
612 | u8 v = drm_dp_get_adjust_request_voltage(link_status, lane: i); |
613 | u8 p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane: i); |
614 | |
615 | if (v > voltage) |
616 | voltage = v; |
617 | |
618 | if (p > preemphasis) |
619 | preemphasis = p; |
620 | } |
621 | |
622 | if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) |
623 | voltage |= DP_TRAIN_MAX_SWING_REACHED; |
624 | |
625 | if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2) |
626 | preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; |
627 | |
628 | for (i = 0; i < dp->mode.lane_cnt; i++) |
629 | train_set[i] = voltage | preemphasis; |
630 | } |
631 | |
632 | /** |
633 | * zynqmp_dp_update_vs_emph - Update the training values |
634 | * @dp: DisplayPort IP core structure |
635 | * |
636 | * Update the training values based on the request from sink. The mapped values |
637 | * are predefined, and values(vs, pe, pc) are from the device manual. |
638 | * |
639 | * Return: 0 if vs and emph are updated successfully, or the error code returned |
640 | * by drm_dp_dpcd_write(). |
641 | */ |
642 | static int zynqmp_dp_update_vs_emph(struct zynqmp_dp *dp) |
643 | { |
644 | unsigned int i; |
645 | int ret; |
646 | |
647 | ret = drm_dp_dpcd_write(aux: &dp->aux, DP_TRAINING_LANE0_SET, buffer: dp->train_set, |
648 | size: dp->mode.lane_cnt); |
649 | if (ret < 0) |
650 | return ret; |
651 | |
652 | for (i = 0; i < dp->mode.lane_cnt; i++) { |
653 | u32 reg = ZYNQMP_DP_SUB_TX_PHY_PRECURSOR_LANE_0 + i * 4; |
654 | union phy_configure_opts opts = { 0 }; |
655 | u8 train = dp->train_set[i]; |
656 | |
657 | opts.dp.voltage[0] = (train & DP_TRAIN_VOLTAGE_SWING_MASK) |
658 | >> DP_TRAIN_VOLTAGE_SWING_SHIFT; |
659 | opts.dp.pre[0] = (train & DP_TRAIN_PRE_EMPHASIS_MASK) |
660 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT; |
661 | |
662 | phy_configure(phy: dp->phy[i], opts: &opts); |
663 | |
664 | zynqmp_dp_write(dp, offset: reg, val: 0x2); |
665 | } |
666 | |
667 | return 0; |
668 | } |
669 | |
670 | /** |
671 | * zynqmp_dp_link_train_cr - Train clock recovery |
672 | * @dp: DisplayPort IP core structure |
673 | * |
674 | * Return: 0 if clock recovery train is done successfully, or corresponding |
675 | * error code. |
676 | */ |
677 | static int zynqmp_dp_link_train_cr(struct zynqmp_dp *dp) |
678 | { |
679 | u8 link_status[DP_LINK_STATUS_SIZE]; |
680 | u8 lane_cnt = dp->mode.lane_cnt; |
681 | u8 vs = 0, tries = 0; |
682 | u16 max_tries, i; |
683 | bool cr_done; |
684 | int ret; |
685 | |
686 | zynqmp_dp_write(dp, ZYNQMP_DP_TRAINING_PATTERN_SET, |
687 | DP_TRAINING_PATTERN_1); |
688 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
689 | DP_TRAINING_PATTERN_1 | |
690 | DP_LINK_SCRAMBLING_DISABLE); |
691 | if (ret < 0) |
692 | return ret; |
693 | |
694 | /* |
695 | * 256 loops should be maximum iterations for 4 lanes and 4 values. |
696 | * So, This loop should exit before 512 iterations |
697 | */ |
698 | for (max_tries = 0; max_tries < 512; max_tries++) { |
699 | ret = zynqmp_dp_update_vs_emph(dp); |
700 | if (ret) |
701 | return ret; |
702 | |
703 | drm_dp_link_train_clock_recovery_delay(aux: &dp->aux, dpcd: dp->dpcd); |
704 | ret = drm_dp_dpcd_read_link_status(aux: &dp->aux, status: link_status); |
705 | if (ret < 0) |
706 | return ret; |
707 | |
708 | cr_done = drm_dp_clock_recovery_ok(link_status, lane_count: lane_cnt); |
709 | if (cr_done) |
710 | break; |
711 | |
712 | for (i = 0; i < lane_cnt; i++) |
713 | if (!(dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED)) |
714 | break; |
715 | if (i == lane_cnt) |
716 | break; |
717 | |
718 | if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == vs) |
719 | tries++; |
720 | else |
721 | tries = 0; |
722 | |
723 | if (tries == DP_MAX_TRAINING_TRIES) |
724 | break; |
725 | |
726 | vs = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
727 | zynqmp_dp_adjust_train(dp, link_status); |
728 | } |
729 | |
730 | if (!cr_done) |
731 | return -EIO; |
732 | |
733 | return 0; |
734 | } |
735 | |
736 | /** |
737 | * zynqmp_dp_link_train_ce - Train channel equalization |
738 | * @dp: DisplayPort IP core structure |
739 | * |
740 | * Return: 0 if channel equalization train is done successfully, or |
741 | * corresponding error code. |
742 | */ |
743 | static int zynqmp_dp_link_train_ce(struct zynqmp_dp *dp) |
744 | { |
745 | u8 link_status[DP_LINK_STATUS_SIZE]; |
746 | u8 lane_cnt = dp->mode.lane_cnt; |
747 | u32 pat, tries; |
748 | int ret; |
749 | bool ce_done; |
750 | |
751 | if (dp->dpcd[DP_DPCD_REV] >= DP_V1_2 && |
752 | dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) |
753 | pat = DP_TRAINING_PATTERN_3; |
754 | else |
755 | pat = DP_TRAINING_PATTERN_2; |
756 | |
757 | zynqmp_dp_write(dp, ZYNQMP_DP_TRAINING_PATTERN_SET, val: pat); |
758 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
759 | value: pat | DP_LINK_SCRAMBLING_DISABLE); |
760 | if (ret < 0) |
761 | return ret; |
762 | |
763 | for (tries = 0; tries < DP_MAX_TRAINING_TRIES; tries++) { |
764 | ret = zynqmp_dp_update_vs_emph(dp); |
765 | if (ret) |
766 | return ret; |
767 | |
768 | drm_dp_link_train_channel_eq_delay(aux: &dp->aux, dpcd: dp->dpcd); |
769 | ret = drm_dp_dpcd_read_link_status(aux: &dp->aux, status: link_status); |
770 | if (ret < 0) |
771 | return ret; |
772 | |
773 | ce_done = drm_dp_channel_eq_ok(link_status, lane_count: lane_cnt); |
774 | if (ce_done) |
775 | break; |
776 | |
777 | zynqmp_dp_adjust_train(dp, link_status); |
778 | } |
779 | |
780 | if (!ce_done) |
781 | return -EIO; |
782 | |
783 | return 0; |
784 | } |
785 | |
786 | /** |
787 | * zynqmp_dp_train - Train the link |
788 | * @dp: DisplayPort IP core structure |
789 | * |
790 | * Return: 0 if all trains are done successfully, or corresponding error code. |
791 | */ |
792 | static int zynqmp_dp_train(struct zynqmp_dp *dp) |
793 | { |
794 | u32 reg; |
795 | u8 bw_code = dp->mode.bw_code; |
796 | u8 lane_cnt = dp->mode.lane_cnt; |
797 | u8 aux_lane_cnt = lane_cnt; |
798 | bool enhanced; |
799 | int ret; |
800 | |
801 | zynqmp_dp_write(dp, ZYNQMP_DP_LANE_COUNT_SET, val: lane_cnt); |
802 | enhanced = drm_dp_enhanced_frame_cap(dpcd: dp->dpcd); |
803 | if (enhanced) { |
804 | zynqmp_dp_write(dp, ZYNQMP_DP_ENHANCED_FRAME_EN, val: 1); |
805 | aux_lane_cnt |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
806 | } |
807 | |
808 | if (dp->dpcd[3] & 0x1) { |
809 | zynqmp_dp_write(dp, ZYNQMP_DP_DOWNSPREAD_CTL, val: 1); |
810 | drm_dp_dpcd_writeb(aux: &dp->aux, DP_DOWNSPREAD_CTRL, |
811 | DP_SPREAD_AMP_0_5); |
812 | } else { |
813 | zynqmp_dp_write(dp, ZYNQMP_DP_DOWNSPREAD_CTL, val: 0); |
814 | drm_dp_dpcd_writeb(aux: &dp->aux, DP_DOWNSPREAD_CTRL, value: 0); |
815 | } |
816 | |
817 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_LANE_COUNT_SET, value: aux_lane_cnt); |
818 | if (ret < 0) { |
819 | dev_err(dp->dev, "failed to set lane count\n" ); |
820 | return ret; |
821 | } |
822 | |
823 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, |
824 | DP_SET_ANSI_8B10B); |
825 | if (ret < 0) { |
826 | dev_err(dp->dev, "failed to set ANSI 8B/10B encoding\n" ); |
827 | return ret; |
828 | } |
829 | |
830 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_LINK_BW_SET, value: bw_code); |
831 | if (ret < 0) { |
832 | dev_err(dp->dev, "failed to set DP bandwidth\n" ); |
833 | return ret; |
834 | } |
835 | |
836 | zynqmp_dp_write(dp, ZYNQMP_DP_LINK_BW_SET, val: bw_code); |
837 | switch (bw_code) { |
838 | case DP_LINK_BW_1_62: |
839 | reg = ZYNQMP_DP_PHY_CLOCK_SELECT_1_62G; |
840 | break; |
841 | case DP_LINK_BW_2_7: |
842 | reg = ZYNQMP_DP_PHY_CLOCK_SELECT_2_70G; |
843 | break; |
844 | case DP_LINK_BW_5_4: |
845 | default: |
846 | reg = ZYNQMP_DP_PHY_CLOCK_SELECT_5_40G; |
847 | break; |
848 | } |
849 | |
850 | zynqmp_dp_write(dp, ZYNQMP_DP_PHY_CLOCK_SELECT, val: reg); |
851 | ret = zynqmp_dp_phy_ready(dp); |
852 | if (ret < 0) |
853 | return ret; |
854 | |
855 | zynqmp_dp_write(dp, ZYNQMP_DP_SCRAMBLING_DISABLE, val: 1); |
856 | memset(dp->train_set, 0, sizeof(dp->train_set)); |
857 | ret = zynqmp_dp_link_train_cr(dp); |
858 | if (ret) |
859 | return ret; |
860 | |
861 | ret = zynqmp_dp_link_train_ce(dp); |
862 | if (ret) |
863 | return ret; |
864 | |
865 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_TRAINING_PATTERN_SET, |
866 | DP_TRAINING_PATTERN_DISABLE); |
867 | if (ret < 0) { |
868 | dev_err(dp->dev, "failed to disable training pattern\n" ); |
869 | return ret; |
870 | } |
871 | zynqmp_dp_write(dp, ZYNQMP_DP_TRAINING_PATTERN_SET, |
872 | DP_TRAINING_PATTERN_DISABLE); |
873 | |
874 | zynqmp_dp_write(dp, ZYNQMP_DP_SCRAMBLING_DISABLE, val: 0); |
875 | |
876 | return 0; |
877 | } |
878 | |
879 | /** |
880 | * zynqmp_dp_train_loop - Downshift the link rate during training |
881 | * @dp: DisplayPort IP core structure |
882 | * |
883 | * Train the link by downshifting the link rate if training is not successful. |
884 | */ |
885 | static void zynqmp_dp_train_loop(struct zynqmp_dp *dp) |
886 | { |
887 | struct zynqmp_dp_mode *mode = &dp->mode; |
888 | u8 bw = mode->bw_code; |
889 | int ret; |
890 | |
891 | do { |
892 | if (dp->status == connector_status_disconnected || |
893 | !dp->enabled) |
894 | return; |
895 | |
896 | ret = zynqmp_dp_train(dp); |
897 | if (!ret) |
898 | return; |
899 | |
900 | ret = zynqmp_dp_mode_configure(dp, pclock: mode->pclock, current_bw: bw); |
901 | if (ret < 0) |
902 | goto err_out; |
903 | |
904 | bw = ret; |
905 | } while (bw >= DP_LINK_BW_1_62); |
906 | |
907 | err_out: |
908 | dev_err(dp->dev, "failed to train the DP link\n" ); |
909 | } |
910 | |
911 | /* ----------------------------------------------------------------------------- |
912 | * DisplayPort AUX |
913 | */ |
914 | |
915 | #define AUX_READ_BIT 0x1 |
916 | |
917 | /** |
918 | * zynqmp_dp_aux_cmd_submit - Submit aux command |
919 | * @dp: DisplayPort IP core structure |
920 | * @cmd: aux command |
921 | * @addr: aux address |
922 | * @buf: buffer for command data |
923 | * @bytes: number of bytes for @buf |
924 | * @reply: reply code to be returned |
925 | * |
926 | * Submit an aux command. All aux related commands, native or i2c aux |
927 | * read/write, are submitted through this function. The function is mapped to |
928 | * the transfer function of struct drm_dp_aux. This function involves in |
929 | * multiple register reads/writes, thus synchronization is needed, and it is |
930 | * done by drm_dp_helper using @hw_mutex. The calling thread goes into sleep |
931 | * if there's no immediate reply to the command submission. The reply code is |
932 | * returned at @reply if @reply != NULL. |
933 | * |
934 | * Return: 0 if the command is submitted properly, or corresponding error code: |
935 | * -EBUSY when there is any request already being processed |
936 | * -ETIMEDOUT when receiving reply is timed out |
937 | * -EIO when received bytes are less than requested |
938 | */ |
939 | static int zynqmp_dp_aux_cmd_submit(struct zynqmp_dp *dp, u32 cmd, u16 addr, |
940 | u8 *buf, u8 bytes, u8 *reply) |
941 | { |
942 | bool is_read = (cmd & AUX_READ_BIT) ? true : false; |
943 | u32 reg, i; |
944 | |
945 | reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE); |
946 | if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REQUEST) |
947 | return -EBUSY; |
948 | |
949 | zynqmp_dp_write(dp, ZYNQMP_DP_AUX_ADDRESS, val: addr); |
950 | if (!is_read) |
951 | for (i = 0; i < bytes; i++) |
952 | zynqmp_dp_write(dp, ZYNQMP_DP_AUX_WRITE_FIFO, |
953 | val: buf[i]); |
954 | |
955 | reg = cmd << ZYNQMP_DP_AUX_COMMAND_CMD_SHIFT; |
956 | if (!buf || !bytes) |
957 | reg |= ZYNQMP_DP_AUX_COMMAND_ADDRESS_ONLY; |
958 | else |
959 | reg |= (bytes - 1) << ZYNQMP_DP_AUX_COMMAND_BYTES_SHIFT; |
960 | zynqmp_dp_write(dp, ZYNQMP_DP_AUX_COMMAND, val: reg); |
961 | |
962 | /* Wait for reply to be delivered upto 2ms */ |
963 | for (i = 0; ; i++) { |
964 | reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE); |
965 | if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY) |
966 | break; |
967 | |
968 | if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT || |
969 | i == 2) |
970 | return -ETIMEDOUT; |
971 | |
972 | usleep_range(min: 1000, max: 1100); |
973 | } |
974 | |
975 | reg = zynqmp_dp_read(dp, ZYNQMP_DP_AUX_REPLY_CODE); |
976 | if (reply) |
977 | *reply = reg; |
978 | |
979 | if (is_read && |
980 | (reg == ZYNQMP_DP_AUX_REPLY_CODE_AUX_ACK || |
981 | reg == ZYNQMP_DP_AUX_REPLY_CODE_I2C_ACK)) { |
982 | reg = zynqmp_dp_read(dp, ZYNQMP_DP_REPLY_DATA_COUNT); |
983 | if ((reg & ZYNQMP_DP_REPLY_DATA_COUNT_MASK) != bytes) |
984 | return -EIO; |
985 | |
986 | for (i = 0; i < bytes; i++) |
987 | buf[i] = zynqmp_dp_read(dp, ZYNQMP_DP_AUX_REPLY_DATA); |
988 | } |
989 | |
990 | return 0; |
991 | } |
992 | |
993 | static ssize_t |
994 | zynqmp_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
995 | { |
996 | struct zynqmp_dp *dp = container_of(aux, struct zynqmp_dp, aux); |
997 | int ret; |
998 | unsigned int i, iter; |
999 | |
1000 | /* Number of loops = timeout in msec / aux delay (400 usec) */ |
1001 | iter = zynqmp_dp_aux_timeout_ms * 1000 / 400; |
1002 | iter = iter ? iter : 1; |
1003 | |
1004 | for (i = 0; i < iter; i++) { |
1005 | ret = zynqmp_dp_aux_cmd_submit(dp, cmd: msg->request, addr: msg->address, |
1006 | buf: msg->buffer, bytes: msg->size, |
1007 | reply: &msg->reply); |
1008 | if (!ret) { |
1009 | dev_dbg(dp->dev, "aux %d retries\n" , i); |
1010 | return msg->size; |
1011 | } |
1012 | |
1013 | if (dp->status == connector_status_disconnected) { |
1014 | dev_dbg(dp->dev, "no connected aux device\n" ); |
1015 | return -ENODEV; |
1016 | } |
1017 | |
1018 | usleep_range(min: 400, max: 500); |
1019 | } |
1020 | |
1021 | dev_dbg(dp->dev, "failed to do aux transfer (%d)\n" , ret); |
1022 | |
1023 | return ret; |
1024 | } |
1025 | |
1026 | /** |
1027 | * zynqmp_dp_aux_init - Initialize and register the DP AUX |
1028 | * @dp: DisplayPort IP core structure |
1029 | * |
1030 | * Program the AUX clock divider and filter and register the DP AUX adapter. |
1031 | * |
1032 | * Return: 0 on success, error value otherwise |
1033 | */ |
1034 | static int zynqmp_dp_aux_init(struct zynqmp_dp *dp) |
1035 | { |
1036 | unsigned long rate; |
1037 | unsigned int w; |
1038 | |
1039 | /* |
1040 | * The AUX_SIGNAL_WIDTH_FILTER is the number of APB clock cycles |
1041 | * corresponding to the AUX pulse. Allowable values are 8, 16, 24, 32, |
1042 | * 40 and 48. The AUX pulse width must be between 0.4µs and 0.6µs, |
1043 | * compute the w / 8 value corresponding to 0.4µs rounded up, and make |
1044 | * sure it stays below 0.6µs and within the allowable values. |
1045 | */ |
1046 | rate = clk_get_rate(clk: dp->dpsub->apb_clk); |
1047 | w = DIV_ROUND_UP(4 * rate, 1000 * 1000 * 10 * 8) * 8; |
1048 | if (w > 6 * rate / (1000 * 1000 * 10) || w > 48) { |
1049 | dev_err(dp->dev, "aclk frequency too high\n" ); |
1050 | return -EINVAL; |
1051 | } |
1052 | |
1053 | zynqmp_dp_write(dp, ZYNQMP_DP_AUX_CLK_DIVIDER, |
1054 | val: (w << ZYNQMP_DP_AUX_CLK_DIVIDER_AUX_FILTER_SHIFT) | |
1055 | (rate / (1000 * 1000))); |
1056 | |
1057 | dp->aux.name = "ZynqMP DP AUX" ; |
1058 | dp->aux.dev = dp->dev; |
1059 | dp->aux.drm_dev = dp->bridge.dev; |
1060 | dp->aux.transfer = zynqmp_dp_aux_transfer; |
1061 | |
1062 | return drm_dp_aux_register(aux: &dp->aux); |
1063 | } |
1064 | |
1065 | /** |
1066 | * zynqmp_dp_aux_cleanup - Cleanup the DP AUX |
1067 | * @dp: DisplayPort IP core structure |
1068 | * |
1069 | * Unregister the DP AUX adapter. |
1070 | */ |
1071 | static void zynqmp_dp_aux_cleanup(struct zynqmp_dp *dp) |
1072 | { |
1073 | drm_dp_aux_unregister(aux: &dp->aux); |
1074 | } |
1075 | |
1076 | /* ----------------------------------------------------------------------------- |
1077 | * DisplayPort Generic Support |
1078 | */ |
1079 | |
1080 | /** |
1081 | * zynqmp_dp_update_misc - Write the misc registers |
1082 | * @dp: DisplayPort IP core structure |
1083 | * |
1084 | * The misc register values are stored in the structure, and this |
1085 | * function applies the values into the registers. |
1086 | */ |
1087 | static void zynqmp_dp_update_misc(struct zynqmp_dp *dp) |
1088 | { |
1089 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC0, val: dp->config.misc0); |
1090 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC1, val: dp->config.misc1); |
1091 | } |
1092 | |
1093 | /** |
1094 | * zynqmp_dp_set_format - Set the input format |
1095 | * @dp: DisplayPort IP core structure |
1096 | * @info: Display info |
1097 | * @format: input format |
1098 | * @bpc: bits per component |
1099 | * |
1100 | * Update misc register values based on input @format and @bpc. |
1101 | * |
1102 | * Return: 0 on success, or -EINVAL. |
1103 | */ |
1104 | static int zynqmp_dp_set_format(struct zynqmp_dp *dp, |
1105 | const struct drm_display_info *info, |
1106 | enum zynqmp_dpsub_format format, |
1107 | unsigned int bpc) |
1108 | { |
1109 | struct zynqmp_dp_config *config = &dp->config; |
1110 | unsigned int num_colors; |
1111 | |
1112 | config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_MASK; |
1113 | config->misc1 &= ~ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; |
1114 | |
1115 | switch (format) { |
1116 | case ZYNQMP_DPSUB_FORMAT_RGB: |
1117 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_RGB; |
1118 | num_colors = 3; |
1119 | break; |
1120 | |
1121 | case ZYNQMP_DPSUB_FORMAT_YCRCB444: |
1122 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_444; |
1123 | num_colors = 3; |
1124 | break; |
1125 | |
1126 | case ZYNQMP_DPSUB_FORMAT_YCRCB422: |
1127 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_422; |
1128 | num_colors = 2; |
1129 | break; |
1130 | |
1131 | case ZYNQMP_DPSUB_FORMAT_YONLY: |
1132 | config->misc1 |= ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; |
1133 | num_colors = 1; |
1134 | break; |
1135 | |
1136 | default: |
1137 | dev_err(dp->dev, "Invalid colormetry in DT\n" ); |
1138 | return -EINVAL; |
1139 | } |
1140 | |
1141 | if (info && info->bpc && bpc > info->bpc) { |
1142 | dev_warn(dp->dev, |
1143 | "downgrading requested %ubpc to display limit %ubpc\n" , |
1144 | bpc, info->bpc); |
1145 | bpc = info->bpc; |
1146 | } |
1147 | |
1148 | config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_MASK; |
1149 | |
1150 | switch (bpc) { |
1151 | case 6: |
1152 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_6; |
1153 | break; |
1154 | case 8: |
1155 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; |
1156 | break; |
1157 | case 10: |
1158 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_10; |
1159 | break; |
1160 | case 12: |
1161 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_12; |
1162 | break; |
1163 | case 16: |
1164 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_16; |
1165 | break; |
1166 | default: |
1167 | dev_warn(dp->dev, "Not supported bpc (%u). fall back to 8bpc\n" , |
1168 | bpc); |
1169 | config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; |
1170 | bpc = 8; |
1171 | break; |
1172 | } |
1173 | |
1174 | /* Update the current bpp based on the format. */ |
1175 | config->bpp = bpc * num_colors; |
1176 | |
1177 | return 0; |
1178 | } |
1179 | |
1180 | /** |
1181 | * zynqmp_dp_encoder_mode_set_transfer_unit - Set the transfer unit values |
1182 | * @dp: DisplayPort IP core structure |
1183 | * @mode: requested display mode |
1184 | * |
1185 | * Set the transfer unit, and calculate all transfer unit size related values. |
1186 | * Calculation is based on DP and IP core specification. |
1187 | */ |
1188 | static void |
1189 | zynqmp_dp_encoder_mode_set_transfer_unit(struct zynqmp_dp *dp, |
1190 | const struct drm_display_mode *mode) |
1191 | { |
1192 | u32 tu = ZYNQMP_DP_MSA_TRANSFER_UNIT_SIZE_TU_SIZE_DEF; |
1193 | u32 bw, vid_kbytes, avg_bytes_per_tu, init_wait; |
1194 | |
1195 | /* Use the max transfer unit size (default) */ |
1196 | zynqmp_dp_write(dp, ZYNQMP_DP_MSA_TRANSFER_UNIT_SIZE, val: tu); |
1197 | |
1198 | vid_kbytes = mode->clock * (dp->config.bpp / 8); |
1199 | bw = drm_dp_bw_code_to_link_rate(link_bw: dp->mode.bw_code); |
1200 | avg_bytes_per_tu = vid_kbytes * tu / (dp->mode.lane_cnt * bw / 1000); |
1201 | zynqmp_dp_write(dp, ZYNQMP_DP_MIN_BYTES_PER_TU, |
1202 | val: avg_bytes_per_tu / 1000); |
1203 | zynqmp_dp_write(dp, ZYNQMP_DP_FRAC_BYTES_PER_TU, |
1204 | val: avg_bytes_per_tu % 1000); |
1205 | |
1206 | /* Configure the initial wait cycle based on transfer unit size */ |
1207 | if (tu < (avg_bytes_per_tu / 1000)) |
1208 | init_wait = 0; |
1209 | else if ((avg_bytes_per_tu / 1000) <= 4) |
1210 | init_wait = tu; |
1211 | else |
1212 | init_wait = tu - avg_bytes_per_tu / 1000; |
1213 | |
1214 | zynqmp_dp_write(dp, ZYNQMP_DP_INIT_WAIT, val: init_wait); |
1215 | } |
1216 | |
1217 | /** |
1218 | * zynqmp_dp_encoder_mode_set_stream - Configure the main stream |
1219 | * @dp: DisplayPort IP core structure |
1220 | * @mode: requested display mode |
1221 | * |
1222 | * Configure the main stream based on the requested mode @mode. Calculation is |
1223 | * based on IP core specification. |
1224 | */ |
1225 | static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp, |
1226 | const struct drm_display_mode *mode) |
1227 | { |
1228 | u8 lane_cnt = dp->mode.lane_cnt; |
1229 | u32 reg, wpl; |
1230 | unsigned int rate; |
1231 | |
1232 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HTOTAL, val: mode->htotal); |
1233 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VTOTAL, val: mode->vtotal); |
1234 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_POLARITY, |
1235 | val: (!!(mode->flags & DRM_MODE_FLAG_PVSYNC) << |
1236 | ZYNQMP_DP_MAIN_STREAM_POLARITY_VSYNC_SHIFT) | |
1237 | (!!(mode->flags & DRM_MODE_FLAG_PHSYNC) << |
1238 | ZYNQMP_DP_MAIN_STREAM_POLARITY_HSYNC_SHIFT)); |
1239 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HSWIDTH, |
1240 | val: mode->hsync_end - mode->hsync_start); |
1241 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VSWIDTH, |
1242 | val: mode->vsync_end - mode->vsync_start); |
1243 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HRES, val: mode->hdisplay); |
1244 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VRES, val: mode->vdisplay); |
1245 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HSTART, |
1246 | val: mode->htotal - mode->hsync_start); |
1247 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VSTART, |
1248 | val: mode->vtotal - mode->vsync_start); |
1249 | |
1250 | /* In synchronous mode, set the dividers */ |
1251 | if (dp->config.misc0 & ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK) { |
1252 | reg = drm_dp_bw_code_to_link_rate(link_bw: dp->mode.bw_code); |
1253 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_N_VID, val: reg); |
1254 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_M_VID, val: mode->clock); |
1255 | rate = zynqmp_dpsub_get_audio_clk_rate(dpsub: dp->dpsub); |
1256 | if (rate) { |
1257 | dev_dbg(dp->dev, "Audio rate: %d\n" , rate / 512); |
1258 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_N_AUD, val: reg); |
1259 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_M_AUD, val: rate / 1000); |
1260 | } |
1261 | } |
1262 | |
1263 | /* Only 2 channel audio is supported now */ |
1264 | if (zynqmp_dpsub_audio_enabled(dpsub: dp->dpsub)) |
1265 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CHANNELS, val: 1); |
1266 | |
1267 | zynqmp_dp_write(dp, ZYNQMP_DP_USER_PIX_WIDTH, val: 1); |
1268 | |
1269 | /* Translate to the native 16 bit datapath based on IP core spec */ |
1270 | wpl = (mode->hdisplay * dp->config.bpp + 15) / 16; |
1271 | reg = wpl + wpl % lane_cnt - lane_cnt; |
1272 | zynqmp_dp_write(dp, ZYNQMP_DP_USER_DATA_COUNT_PER_LANE, val: reg); |
1273 | } |
1274 | |
1275 | /* ----------------------------------------------------------------------------- |
1276 | * DISP Configuration |
1277 | */ |
1278 | |
1279 | static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp, |
1280 | struct drm_bridge_state *old_bridge_state) |
1281 | { |
1282 | enum zynqmp_dpsub_layer_id layer_id; |
1283 | struct zynqmp_disp_layer *layer; |
1284 | const struct drm_format_info *info; |
1285 | |
1286 | if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) |
1287 | layer_id = ZYNQMP_DPSUB_LAYER_VID; |
1288 | else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) |
1289 | layer_id = ZYNQMP_DPSUB_LAYER_GFX; |
1290 | else |
1291 | return; |
1292 | |
1293 | layer = dp->dpsub->layers[layer_id]; |
1294 | |
1295 | /* TODO: Make the format configurable. */ |
1296 | info = drm_format_info(DRM_FORMAT_YUV422); |
1297 | zynqmp_disp_layer_set_format(layer, info); |
1298 | zynqmp_disp_layer_enable(layer, mode: ZYNQMP_DPSUB_LAYER_LIVE); |
1299 | |
1300 | if (layer_id == ZYNQMP_DPSUB_LAYER_GFX) |
1301 | zynqmp_disp_blend_set_global_alpha(disp: dp->dpsub->disp, enable: true, alpha: 255); |
1302 | else |
1303 | zynqmp_disp_blend_set_global_alpha(disp: dp->dpsub->disp, enable: false, alpha: 0); |
1304 | |
1305 | zynqmp_disp_enable(disp: dp->dpsub->disp); |
1306 | } |
1307 | |
1308 | static void zynqmp_dp_disp_disable(struct zynqmp_dp *dp, |
1309 | struct drm_bridge_state *old_bridge_state) |
1310 | { |
1311 | struct zynqmp_disp_layer *layer; |
1312 | |
1313 | if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) |
1314 | layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID]; |
1315 | else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) |
1316 | layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]; |
1317 | else |
1318 | return; |
1319 | |
1320 | zynqmp_disp_disable(disp: dp->dpsub->disp); |
1321 | zynqmp_disp_layer_disable(layer); |
1322 | } |
1323 | |
1324 | /* ----------------------------------------------------------------------------- |
1325 | * DRM Bridge |
1326 | */ |
1327 | |
1328 | static int zynqmp_dp_bridge_attach(struct drm_bridge *bridge, |
1329 | enum drm_bridge_attach_flags flags) |
1330 | { |
1331 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1332 | int ret; |
1333 | |
1334 | /* Initialize and register the AUX adapter. */ |
1335 | ret = zynqmp_dp_aux_init(dp); |
1336 | if (ret) { |
1337 | dev_err(dp->dev, "failed to initialize DP aux\n" ); |
1338 | return ret; |
1339 | } |
1340 | |
1341 | if (dp->next_bridge) { |
1342 | ret = drm_bridge_attach(encoder: bridge->encoder, bridge: dp->next_bridge, |
1343 | previous: bridge, flags); |
1344 | if (ret < 0) |
1345 | goto error; |
1346 | } |
1347 | |
1348 | /* Now that initialisation is complete, enable interrupts. */ |
1349 | zynqmp_dp_write(dp, ZYNQMP_DP_INT_EN, ZYNQMP_DP_INT_ALL); |
1350 | |
1351 | return 0; |
1352 | |
1353 | error: |
1354 | zynqmp_dp_aux_cleanup(dp); |
1355 | return ret; |
1356 | } |
1357 | |
1358 | static void zynqmp_dp_bridge_detach(struct drm_bridge *bridge) |
1359 | { |
1360 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1361 | |
1362 | zynqmp_dp_aux_cleanup(dp); |
1363 | } |
1364 | |
1365 | static enum drm_mode_status |
1366 | zynqmp_dp_bridge_mode_valid(struct drm_bridge *bridge, |
1367 | const struct drm_display_info *info, |
1368 | const struct drm_display_mode *mode) |
1369 | { |
1370 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1371 | int rate; |
1372 | |
1373 | if (mode->clock > ZYNQMP_MAX_FREQ) { |
1374 | dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n" , |
1375 | mode->name); |
1376 | drm_mode_debug_printmodeline(mode); |
1377 | return MODE_CLOCK_HIGH; |
1378 | } |
1379 | |
1380 | /* Check with link rate and lane count */ |
1381 | rate = zynqmp_dp_max_rate(link_rate: dp->link_config.max_rate, |
1382 | lane_num: dp->link_config.max_lanes, bpp: dp->config.bpp); |
1383 | if (mode->clock > rate) { |
1384 | dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n" , |
1385 | mode->name); |
1386 | drm_mode_debug_printmodeline(mode); |
1387 | return MODE_CLOCK_HIGH; |
1388 | } |
1389 | |
1390 | return MODE_OK; |
1391 | } |
1392 | |
1393 | static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge, |
1394 | struct drm_bridge_state *old_bridge_state) |
1395 | { |
1396 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1397 | struct drm_atomic_state *state = old_bridge_state->base.state; |
1398 | const struct drm_crtc_state *crtc_state; |
1399 | const struct drm_display_mode *adjusted_mode; |
1400 | const struct drm_display_mode *mode; |
1401 | struct drm_connector *connector; |
1402 | struct drm_crtc *crtc; |
1403 | unsigned int i; |
1404 | int rate; |
1405 | int ret; |
1406 | |
1407 | pm_runtime_get_sync(dev: dp->dev); |
1408 | |
1409 | zynqmp_dp_disp_enable(dp, old_bridge_state); |
1410 | |
1411 | /* |
1412 | * Retrieve the CRTC mode and adjusted mode. This requires a little |
1413 | * dance to go from the bridge to the encoder, to the connector and to |
1414 | * the CRTC. |
1415 | */ |
1416 | connector = drm_atomic_get_new_connector_for_encoder(state, |
1417 | encoder: bridge->encoder); |
1418 | crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; |
1419 | crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
1420 | adjusted_mode = &crtc_state->adjusted_mode; |
1421 | mode = &crtc_state->mode; |
1422 | |
1423 | zynqmp_dp_set_format(dp, info: &connector->display_info, |
1424 | format: ZYNQMP_DPSUB_FORMAT_RGB, bpc: 8); |
1425 | |
1426 | /* Check again as bpp or format might have been changed */ |
1427 | rate = zynqmp_dp_max_rate(link_rate: dp->link_config.max_rate, |
1428 | lane_num: dp->link_config.max_lanes, bpp: dp->config.bpp); |
1429 | if (mode->clock > rate) { |
1430 | dev_err(dp->dev, "mode %s has too high pixel rate\n" , |
1431 | mode->name); |
1432 | drm_mode_debug_printmodeline(mode); |
1433 | } |
1434 | |
1435 | /* Configure the mode */ |
1436 | ret = zynqmp_dp_mode_configure(dp, pclock: adjusted_mode->clock, current_bw: 0); |
1437 | if (ret < 0) { |
1438 | pm_runtime_put_sync(dev: dp->dev); |
1439 | return; |
1440 | } |
1441 | |
1442 | zynqmp_dp_encoder_mode_set_transfer_unit(dp, mode: adjusted_mode); |
1443 | zynqmp_dp_encoder_mode_set_stream(dp, mode: adjusted_mode); |
1444 | |
1445 | /* Enable the encoder */ |
1446 | dp->enabled = true; |
1447 | zynqmp_dp_update_misc(dp); |
1448 | if (zynqmp_dpsub_audio_enabled(dpsub: dp->dpsub)) |
1449 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, val: 1); |
1450 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, val: 0); |
1451 | if (dp->status == connector_status_connected) { |
1452 | for (i = 0; i < 3; i++) { |
1453 | ret = drm_dp_dpcd_writeb(aux: &dp->aux, DP_SET_POWER, |
1454 | DP_SET_POWER_D0); |
1455 | if (ret == 1) |
1456 | break; |
1457 | usleep_range(min: 300, max: 500); |
1458 | } |
1459 | /* Some monitors take time to wake up properly */ |
1460 | msleep(msecs: zynqmp_dp_power_on_delay_ms); |
1461 | } |
1462 | if (ret != 1) |
1463 | dev_dbg(dp->dev, "DP aux failed\n" ); |
1464 | else |
1465 | zynqmp_dp_train_loop(dp); |
1466 | zynqmp_dp_write(dp, ZYNQMP_DP_SOFTWARE_RESET, |
1467 | ZYNQMP_DP_SOFTWARE_RESET_ALL); |
1468 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_ENABLE, val: 1); |
1469 | } |
1470 | |
1471 | static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge, |
1472 | struct drm_bridge_state *old_bridge_state) |
1473 | { |
1474 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1475 | |
1476 | dp->enabled = false; |
1477 | cancel_delayed_work(dwork: &dp->hpd_work); |
1478 | zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_ENABLE, val: 0); |
1479 | drm_dp_dpcd_writeb(aux: &dp->aux, DP_SET_POWER, DP_SET_POWER_D3); |
1480 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, |
1481 | ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL); |
1482 | if (zynqmp_dpsub_audio_enabled(dpsub: dp->dpsub)) |
1483 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, val: 0); |
1484 | |
1485 | zynqmp_dp_disp_disable(dp, old_bridge_state); |
1486 | |
1487 | pm_runtime_put_sync(dev: dp->dev); |
1488 | } |
1489 | |
1490 | #define ZYNQMP_DP_MIN_H_BACKPORCH 20 |
1491 | |
1492 | static int zynqmp_dp_bridge_atomic_check(struct drm_bridge *bridge, |
1493 | struct drm_bridge_state *bridge_state, |
1494 | struct drm_crtc_state *crtc_state, |
1495 | struct drm_connector_state *conn_state) |
1496 | { |
1497 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1498 | struct drm_display_mode *mode = &crtc_state->mode; |
1499 | struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; |
1500 | int diff = mode->htotal - mode->hsync_end; |
1501 | |
1502 | /* |
1503 | * ZynqMP DP requires horizontal backporch to be greater than 12. |
1504 | * This limitation may not be compatible with the sink device. |
1505 | */ |
1506 | if (diff < ZYNQMP_DP_MIN_H_BACKPORCH) { |
1507 | int vrefresh = (adjusted_mode->clock * 1000) / |
1508 | (adjusted_mode->vtotal * adjusted_mode->htotal); |
1509 | |
1510 | dev_dbg(dp->dev, "hbackporch adjusted: %d to %d" , |
1511 | diff, ZYNQMP_DP_MIN_H_BACKPORCH - diff); |
1512 | diff = ZYNQMP_DP_MIN_H_BACKPORCH - diff; |
1513 | adjusted_mode->htotal += diff; |
1514 | adjusted_mode->clock = adjusted_mode->vtotal * |
1515 | adjusted_mode->htotal * vrefresh / 1000; |
1516 | } |
1517 | |
1518 | return 0; |
1519 | } |
1520 | |
1521 | static enum drm_connector_status zynqmp_dp_bridge_detect(struct drm_bridge *bridge) |
1522 | { |
1523 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1524 | struct zynqmp_dp_link_config *link_config = &dp->link_config; |
1525 | u32 state, i; |
1526 | int ret; |
1527 | |
1528 | /* |
1529 | * This is from heuristic. It takes some delay (ex, 100 ~ 500 msec) to |
1530 | * get the HPD signal with some monitors. |
1531 | */ |
1532 | for (i = 0; i < 10; i++) { |
1533 | state = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE); |
1534 | if (state & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_HPD) |
1535 | break; |
1536 | msleep(msecs: 100); |
1537 | } |
1538 | |
1539 | if (state & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_HPD) { |
1540 | ret = drm_dp_dpcd_read(aux: &dp->aux, offset: 0x0, buffer: dp->dpcd, |
1541 | size: sizeof(dp->dpcd)); |
1542 | if (ret < 0) { |
1543 | dev_dbg(dp->dev, "DPCD read failed" ); |
1544 | goto disconnected; |
1545 | } |
1546 | |
1547 | link_config->max_rate = min_t(int, |
1548 | drm_dp_max_link_rate(dp->dpcd), |
1549 | DP_HIGH_BIT_RATE2); |
1550 | link_config->max_lanes = min_t(u8, |
1551 | drm_dp_max_lane_count(dp->dpcd), |
1552 | dp->num_lanes); |
1553 | |
1554 | dp->status = connector_status_connected; |
1555 | return connector_status_connected; |
1556 | } |
1557 | |
1558 | disconnected: |
1559 | dp->status = connector_status_disconnected; |
1560 | return connector_status_disconnected; |
1561 | } |
1562 | |
1563 | static const struct drm_edid *zynqmp_dp_bridge_edid_read(struct drm_bridge *bridge, |
1564 | struct drm_connector *connector) |
1565 | { |
1566 | struct zynqmp_dp *dp = bridge_to_dp(bridge); |
1567 | |
1568 | return drm_edid_read_ddc(connector, adapter: &dp->aux.ddc); |
1569 | } |
1570 | |
1571 | static const struct drm_bridge_funcs zynqmp_dp_bridge_funcs = { |
1572 | .attach = zynqmp_dp_bridge_attach, |
1573 | .detach = zynqmp_dp_bridge_detach, |
1574 | .mode_valid = zynqmp_dp_bridge_mode_valid, |
1575 | .atomic_enable = zynqmp_dp_bridge_atomic_enable, |
1576 | .atomic_disable = zynqmp_dp_bridge_atomic_disable, |
1577 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
1578 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
1579 | .atomic_reset = drm_atomic_helper_bridge_reset, |
1580 | .atomic_check = zynqmp_dp_bridge_atomic_check, |
1581 | .detect = zynqmp_dp_bridge_detect, |
1582 | .edid_read = zynqmp_dp_bridge_edid_read, |
1583 | }; |
1584 | |
1585 | /* ----------------------------------------------------------------------------- |
1586 | * Interrupt Handling |
1587 | */ |
1588 | |
1589 | /** |
1590 | * zynqmp_dp_enable_vblank - Enable vblank |
1591 | * @dp: DisplayPort IP core structure |
1592 | * |
1593 | * Enable vblank interrupt |
1594 | */ |
1595 | void zynqmp_dp_enable_vblank(struct zynqmp_dp *dp) |
1596 | { |
1597 | zynqmp_dp_write(dp, ZYNQMP_DP_INT_EN, ZYNQMP_DP_INT_VBLANK_START); |
1598 | } |
1599 | |
1600 | /** |
1601 | * zynqmp_dp_disable_vblank - Disable vblank |
1602 | * @dp: DisplayPort IP core structure |
1603 | * |
1604 | * Disable vblank interrupt |
1605 | */ |
1606 | void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp) |
1607 | { |
1608 | zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_VBLANK_START); |
1609 | } |
1610 | |
1611 | static void zynqmp_dp_hpd_work_func(struct work_struct *work) |
1612 | { |
1613 | struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp, |
1614 | hpd_work.work); |
1615 | enum drm_connector_status status; |
1616 | |
1617 | status = zynqmp_dp_bridge_detect(bridge: &dp->bridge); |
1618 | drm_bridge_hpd_notify(bridge: &dp->bridge, status); |
1619 | } |
1620 | |
1621 | static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data) |
1622 | { |
1623 | struct zynqmp_dp *dp = (struct zynqmp_dp *)data; |
1624 | u32 status, mask; |
1625 | |
1626 | status = zynqmp_dp_read(dp, ZYNQMP_DP_INT_STATUS); |
1627 | /* clear status register as soon as we read it */ |
1628 | zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, val: status); |
1629 | mask = zynqmp_dp_read(dp, ZYNQMP_DP_INT_MASK); |
1630 | |
1631 | /* |
1632 | * Status register may report some events, which corresponding interrupts |
1633 | * have been disabled. Filter out those events against interrupts' mask. |
1634 | */ |
1635 | status &= ~mask; |
1636 | |
1637 | if (!status) |
1638 | return IRQ_NONE; |
1639 | |
1640 | /* dbg for diagnostic, but not much that the driver can do */ |
1641 | if (status & ZYNQMP_DP_INT_CHBUF_UNDERFLW_MASK) |
1642 | dev_dbg_ratelimited(dp->dev, "underflow interrupt\n" ); |
1643 | if (status & ZYNQMP_DP_INT_CHBUF_OVERFLW_MASK) |
1644 | dev_dbg_ratelimited(dp->dev, "overflow interrupt\n" ); |
1645 | |
1646 | if (status & ZYNQMP_DP_INT_VBLANK_START) |
1647 | zynqmp_dpsub_drm_handle_vblank(dpsub: dp->dpsub); |
1648 | |
1649 | if (status & ZYNQMP_DP_INT_HPD_EVENT) |
1650 | schedule_delayed_work(dwork: &dp->hpd_work, delay: 0); |
1651 | |
1652 | if (status & ZYNQMP_DP_INT_HPD_IRQ) { |
1653 | int ret; |
1654 | u8 status[DP_LINK_STATUS_SIZE + 2]; |
1655 | |
1656 | ret = drm_dp_dpcd_read(aux: &dp->aux, DP_SINK_COUNT, buffer: status, |
1657 | DP_LINK_STATUS_SIZE + 2); |
1658 | if (ret < 0) |
1659 | goto handled; |
1660 | |
1661 | if (status[4] & DP_LINK_STATUS_UPDATED || |
1662 | !drm_dp_clock_recovery_ok(link_status: &status[2], lane_count: dp->mode.lane_cnt) || |
1663 | !drm_dp_channel_eq_ok(link_status: &status[2], lane_count: dp->mode.lane_cnt)) { |
1664 | zynqmp_dp_train_loop(dp); |
1665 | } |
1666 | } |
1667 | |
1668 | handled: |
1669 | return IRQ_HANDLED; |
1670 | } |
1671 | |
1672 | /* ----------------------------------------------------------------------------- |
1673 | * Initialization & Cleanup |
1674 | */ |
1675 | |
1676 | int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) |
1677 | { |
1678 | struct platform_device *pdev = to_platform_device(dpsub->dev); |
1679 | struct drm_bridge *bridge; |
1680 | struct zynqmp_dp *dp; |
1681 | struct resource *res; |
1682 | int ret; |
1683 | |
1684 | dp = kzalloc(size: sizeof(*dp), GFP_KERNEL); |
1685 | if (!dp) |
1686 | return -ENOMEM; |
1687 | |
1688 | dp->dev = &pdev->dev; |
1689 | dp->dpsub = dpsub; |
1690 | dp->status = connector_status_disconnected; |
1691 | |
1692 | INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func); |
1693 | |
1694 | /* Acquire all resources (IOMEM, IRQ and PHYs). */ |
1695 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp" ); |
1696 | dp->iomem = devm_ioremap_resource(dev: dp->dev, res); |
1697 | if (IS_ERR(ptr: dp->iomem)) { |
1698 | ret = PTR_ERR(ptr: dp->iomem); |
1699 | goto err_free; |
1700 | } |
1701 | |
1702 | dp->irq = platform_get_irq(pdev, 0); |
1703 | if (dp->irq < 0) { |
1704 | ret = dp->irq; |
1705 | goto err_free; |
1706 | } |
1707 | |
1708 | dp->reset = devm_reset_control_get(dev: dp->dev, NULL); |
1709 | if (IS_ERR(ptr: dp->reset)) { |
1710 | if (PTR_ERR(ptr: dp->reset) != -EPROBE_DEFER) |
1711 | dev_err(dp->dev, "failed to get reset: %ld\n" , |
1712 | PTR_ERR(dp->reset)); |
1713 | ret = PTR_ERR(ptr: dp->reset); |
1714 | goto err_free; |
1715 | } |
1716 | |
1717 | ret = zynqmp_dp_reset(dp, assert: false); |
1718 | if (ret < 0) |
1719 | goto err_free; |
1720 | |
1721 | ret = zynqmp_dp_phy_probe(dp); |
1722 | if (ret) |
1723 | goto err_reset; |
1724 | |
1725 | /* Initialize the bridge. */ |
1726 | bridge = &dp->bridge; |
1727 | bridge->funcs = &zynqmp_dp_bridge_funcs; |
1728 | bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
1729 | | DRM_BRIDGE_OP_HPD; |
1730 | bridge->type = DRM_MODE_CONNECTOR_DisplayPort; |
1731 | bridge->of_node = dp->dev->of_node; |
1732 | dpsub->bridge = bridge; |
1733 | |
1734 | /* |
1735 | * Acquire the next bridge in the chain. Ignore errors caused by port@5 |
1736 | * not being connected for backward-compatibility with older DTs. |
1737 | */ |
1738 | ret = drm_of_find_panel_or_bridge(np: dp->dev->of_node, port: 5, endpoint: 0, NULL, |
1739 | bridge: &dp->next_bridge); |
1740 | if (ret < 0 && ret != -ENODEV) |
1741 | goto err_reset; |
1742 | |
1743 | /* Initialize the hardware. */ |
1744 | dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK; |
1745 | zynqmp_dp_set_format(dp, NULL, format: ZYNQMP_DPSUB_FORMAT_RGB, bpc: 8); |
1746 | |
1747 | zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, |
1748 | ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL); |
1749 | zynqmp_dp_set(dp, ZYNQMP_DP_PHY_RESET, ZYNQMP_DP_PHY_RESET_ALL_RESET); |
1750 | zynqmp_dp_write(dp, ZYNQMP_DP_FORCE_SCRAMBLER_RESET, val: 1); |
1751 | zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, val: 0); |
1752 | zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, val: 0xffffffff); |
1753 | |
1754 | ret = zynqmp_dp_phy_init(dp); |
1755 | if (ret) |
1756 | goto err_reset; |
1757 | |
1758 | zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, val: 1); |
1759 | |
1760 | /* |
1761 | * Now that the hardware is initialized and won't generate spurious |
1762 | * interrupts, request the IRQ. |
1763 | */ |
1764 | ret = devm_request_threaded_irq(dev: dp->dev, irq: dp->irq, NULL, |
1765 | thread_fn: zynqmp_dp_irq_handler, IRQF_ONESHOT, |
1766 | devname: dev_name(dev: dp->dev), dev_id: dp); |
1767 | if (ret < 0) |
1768 | goto err_phy_exit; |
1769 | |
1770 | dpsub->dp = dp; |
1771 | |
1772 | dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n" , |
1773 | dp->num_lanes); |
1774 | |
1775 | return 0; |
1776 | |
1777 | err_phy_exit: |
1778 | zynqmp_dp_phy_exit(dp); |
1779 | err_reset: |
1780 | zynqmp_dp_reset(dp, assert: true); |
1781 | err_free: |
1782 | kfree(objp: dp); |
1783 | return ret; |
1784 | } |
1785 | |
1786 | void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub) |
1787 | { |
1788 | struct zynqmp_dp *dp = dpsub->dp; |
1789 | |
1790 | zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_ALL); |
1791 | disable_irq(irq: dp->irq); |
1792 | |
1793 | cancel_delayed_work_sync(dwork: &dp->hpd_work); |
1794 | |
1795 | zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, val: 0); |
1796 | zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, val: 0xffffffff); |
1797 | |
1798 | zynqmp_dp_phy_exit(dp); |
1799 | zynqmp_dp_reset(dp, assert: true); |
1800 | } |
1801 | |