1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Cadence MHDP8546 DP bridge driver. |
4 | * |
5 | * Copyright (C) 2020 Cadence Design Systems, Inc. |
6 | * |
7 | * Author: Quentin Schulz <quentin.schulz@free-electrons.com> |
8 | * Swapnil Jakhade <sjakhade@cadence.com> |
9 | */ |
10 | |
11 | #ifndef CDNS_MHDP8546_CORE_H |
12 | #define CDNS_MHDP8546_CORE_H |
13 | |
14 | #include <linux/bits.h> |
15 | #include <linux/mutex.h> |
16 | #include <linux/spinlock.h> |
17 | |
18 | #include <drm/display/drm_dp_helper.h> |
19 | #include <drm/drm_bridge.h> |
20 | #include <drm/drm_connector.h> |
21 | |
22 | struct clk; |
23 | struct device; |
24 | struct phy; |
25 | |
26 | /* Register offsets */ |
27 | #define CDNS_APB_CTRL 0x00000 |
28 | #define CDNS_CPU_STALL BIT(3) |
29 | |
30 | #define CDNS_MAILBOX_FULL 0x00008 |
31 | #define CDNS_MAILBOX_EMPTY 0x0000c |
32 | #define CDNS_MAILBOX_TX_DATA 0x00010 |
33 | #define CDNS_MAILBOX_RX_DATA 0x00014 |
34 | #define CDNS_KEEP_ALIVE 0x00018 |
35 | #define CDNS_KEEP_ALIVE_MASK GENMASK(7, 0) |
36 | |
37 | #define CDNS_VER_L 0x0001C |
38 | #define CDNS_VER_H 0x00020 |
39 | #define CDNS_LIB_L_ADDR 0x00024 |
40 | #define CDNS_LIB_H_ADDR 0x00028 |
41 | |
42 | #define CDNS_MB_INT_MASK 0x00034 |
43 | #define CDNS_MB_INT_STATUS 0x00038 |
44 | |
45 | #define CDNS_SW_CLK_L 0x0003c |
46 | #define CDNS_SW_CLK_H 0x00040 |
47 | |
48 | #define CDNS_SW_EVENT0 0x00044 |
49 | #define CDNS_DPTX_HPD BIT(0) |
50 | #define CDNS_HDCP_TX_STATUS BIT(4) |
51 | #define CDNS_HDCP2_TX_IS_KM_STORED BIT(5) |
52 | #define CDNS_HDCP2_TX_STORE_KM BIT(6) |
53 | #define CDNS_HDCP_TX_IS_RCVR_ID_VALID BIT(7) |
54 | |
55 | #define CDNS_SW_EVENT1 0x00048 |
56 | #define CDNS_SW_EVENT2 0x0004c |
57 | #define CDNS_SW_EVENT3 0x00050 |
58 | |
59 | #define CDNS_APB_INT_MASK 0x0006C |
60 | #define CDNS_APB_INT_MASK_MAILBOX_INT BIT(0) |
61 | #define CDNS_APB_INT_MASK_SW_EVENT_INT BIT(1) |
62 | |
63 | #define CDNS_APB_INT_STATUS 0x00070 |
64 | |
65 | #define CDNS_DPTX_CAR 0x00904 |
66 | #define CDNS_VIF_CLK_EN BIT(0) |
67 | #define CDNS_VIF_CLK_RSTN BIT(1) |
68 | |
69 | #define CDNS_SOURCE_VIDEO_IF(s) (0x00b00 + ((s) * 0x20)) |
70 | #define CDNS_BND_HSYNC2VSYNC(s) (CDNS_SOURCE_VIDEO_IF(s) + \ |
71 | 0x00) |
72 | #define CDNS_IP_DTCT_WIN GENMASK(11, 0) |
73 | #define CDNS_IP_DET_INTERLACE_FORMAT BIT(12) |
74 | #define CDNS_IP_BYPASS_V_INTERFACE BIT(13) |
75 | |
76 | #define CDNS_HSYNC2VSYNC_POL_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + \ |
77 | 0x10) |
78 | #define CDNS_H2V_HSYNC_POL_ACTIVE_LOW BIT(1) |
79 | #define CDNS_H2V_VSYNC_POL_ACTIVE_LOW BIT(2) |
80 | |
81 | #define CDNS_DPTX_PHY_CONFIG 0x02000 |
82 | #define CDNS_PHY_TRAINING_EN BIT(0) |
83 | #define CDNS_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1) |
84 | #define CDNS_PHY_SCRAMBLER_BYPASS BIT(5) |
85 | #define CDNS_PHY_ENCODER_BYPASS BIT(6) |
86 | #define CDNS_PHY_SKEW_BYPASS BIT(7) |
87 | #define CDNS_PHY_TRAINING_AUTO BIT(8) |
88 | #define CDNS_PHY_LANE0_SKEW(x) (((x) & GENMASK(2, 0)) << 9) |
89 | #define CDNS_PHY_LANE1_SKEW(x) (((x) & GENMASK(2, 0)) << 12) |
90 | #define CDNS_PHY_LANE2_SKEW(x) (((x) & GENMASK(2, 0)) << 15) |
91 | #define CDNS_PHY_LANE3_SKEW(x) (((x) & GENMASK(2, 0)) << 18) |
92 | #define CDNS_PHY_COMMON_CONFIG (CDNS_PHY_LANE1_SKEW(1) | \ |
93 | CDNS_PHY_LANE2_SKEW(2) | \ |
94 | CDNS_PHY_LANE3_SKEW(3)) |
95 | #define CDNS_PHY_10BIT_EN BIT(21) |
96 | |
97 | #define CDNS_DP_FRAMER_GLOBAL_CONFIG 0x02200 |
98 | #define CDNS_DP_NUM_LANES(x) ((x) - 1) |
99 | #define CDNS_DP_MST_EN BIT(2) |
100 | #define CDNS_DP_FRAMER_EN BIT(3) |
101 | #define CDNS_DP_RATE_GOVERNOR_EN BIT(4) |
102 | #define CDNS_DP_NO_VIDEO_MODE BIT(5) |
103 | #define CDNS_DP_DISABLE_PHY_RST BIT(6) |
104 | #define CDNS_DP_WR_FAILING_EDGE_VSYNC BIT(7) |
105 | |
106 | #define CDNS_DP_FRAMER_TU 0x02208 |
107 | #define CDNS_DP_FRAMER_TU_SIZE(x) (((x) & GENMASK(6, 0)) << 8) |
108 | #define CDNS_DP_FRAMER_TU_VS(x) ((x) & GENMASK(5, 0)) |
109 | #define CDNS_DP_FRAMER_TU_CNT_RST_EN BIT(15) |
110 | |
111 | #define CDNS_DP_MTPH_CONTROL 0x02264 |
112 | #define CDNS_DP_MTPH_ECF_EN BIT(0) |
113 | #define CDNS_DP_MTPH_ACT_EN BIT(1) |
114 | #define CDNS_DP_MTPH_LVP_EN BIT(2) |
115 | |
116 | #define CDNS_DP_MTPH_STATUS 0x0226C |
117 | #define CDNS_DP_MTPH_ACT_STATUS BIT(0) |
118 | |
119 | #define CDNS_DP_LANE_EN 0x02300 |
120 | #define CDNS_DP_LANE_EN_LANES(x) GENMASK((x) - 1, 0) |
121 | |
122 | #define CDNS_DP_ENHNCD 0x02304 |
123 | |
124 | #define CDNS_DPTX_STREAM(s) (0x03000 + (s) * 0x80) |
125 | #define CDNS_DP_MSA_HORIZONTAL_0(s) (CDNS_DPTX_STREAM(s) + 0x00) |
126 | #define CDNS_DP_MSAH0_H_TOTAL(x) (x) |
127 | #define CDNS_DP_MSAH0_HSYNC_START(x) ((x) << 16) |
128 | |
129 | #define CDNS_DP_MSA_HORIZONTAL_1(s) (CDNS_DPTX_STREAM(s) + 0x04) |
130 | #define CDNS_DP_MSAH1_HSYNC_WIDTH(x) (x) |
131 | #define CDNS_DP_MSAH1_HSYNC_POL_LOW BIT(15) |
132 | #define CDNS_DP_MSAH1_HDISP_WIDTH(x) ((x) << 16) |
133 | |
134 | #define CDNS_DP_MSA_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x08) |
135 | #define CDNS_DP_MSAV0_V_TOTAL(x) (x) |
136 | #define CDNS_DP_MSAV0_VSYNC_START(x) ((x) << 16) |
137 | |
138 | #define CDNS_DP_MSA_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x0c) |
139 | #define CDNS_DP_MSAV1_VSYNC_WIDTH(x) (x) |
140 | #define CDNS_DP_MSAV1_VSYNC_POL_LOW BIT(15) |
141 | #define CDNS_DP_MSAV1_VDISP_WIDTH(x) ((x) << 16) |
142 | |
143 | #define CDNS_DP_MSA_MISC(s) (CDNS_DPTX_STREAM(s) + 0x10) |
144 | #define CDNS_DP_STREAM_CONFIG(s) (CDNS_DPTX_STREAM(s) + 0x14) |
145 | #define CDNS_DP_STREAM_CONFIG_2(s) (CDNS_DPTX_STREAM(s) + 0x2c) |
146 | #define CDNS_DP_SC2_TU_VS_DIFF(x) ((x) << 8) |
147 | |
148 | #define CDNS_DP_HORIZONTAL(s) (CDNS_DPTX_STREAM(s) + 0x30) |
149 | #define CDNS_DP_H_HSYNC_WIDTH(x) (x) |
150 | #define CDNS_DP_H_H_TOTAL(x) ((x) << 16) |
151 | |
152 | #define CDNS_DP_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x34) |
153 | #define CDNS_DP_V0_VHEIGHT(x) (x) |
154 | #define CDNS_DP_V0_VSTART(x) ((x) << 16) |
155 | |
156 | #define CDNS_DP_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x38) |
157 | #define CDNS_DP_V1_VTOTAL(x) (x) |
158 | #define CDNS_DP_V1_VTOTAL_EVEN BIT(16) |
159 | |
160 | #define CDNS_DP_MST_SLOT_ALLOCATE(s) (CDNS_DPTX_STREAM(s) + 0x44) |
161 | #define CDNS_DP_S_ALLOC_START_SLOT(x) (x) |
162 | #define CDNS_DP_S_ALLOC_END_SLOT(x) ((x) << 8) |
163 | |
164 | #define CDNS_DP_RATE_GOVERNING(s) (CDNS_DPTX_STREAM(s) + 0x48) |
165 | #define CDNS_DP_RG_TARG_AV_SLOTS_Y(x) (x) |
166 | #define CDNS_DP_RG_TARG_AV_SLOTS_X(x) ((x) << 4) |
167 | #define CDNS_DP_RG_ENABLE BIT(10) |
168 | |
169 | #define CDNS_DP_FRAMER_PXL_REPR(s) (CDNS_DPTX_STREAM(s) + 0x4c) |
170 | #define CDNS_DP_FRAMER_6_BPC BIT(0) |
171 | #define CDNS_DP_FRAMER_8_BPC BIT(1) |
172 | #define CDNS_DP_FRAMER_10_BPC BIT(2) |
173 | #define CDNS_DP_FRAMER_12_BPC BIT(3) |
174 | #define CDNS_DP_FRAMER_16_BPC BIT(4) |
175 | #define CDNS_DP_FRAMER_PXL_FORMAT 0x8 |
176 | #define CDNS_DP_FRAMER_RGB BIT(0) |
177 | #define CDNS_DP_FRAMER_YCBCR444 BIT(1) |
178 | #define CDNS_DP_FRAMER_YCBCR422 BIT(2) |
179 | #define CDNS_DP_FRAMER_YCBCR420 BIT(3) |
180 | #define CDNS_DP_FRAMER_Y_ONLY BIT(4) |
181 | |
182 | #define CDNS_DP_FRAMER_SP(s) (CDNS_DPTX_STREAM(s) + 0x50) |
183 | #define CDNS_DP_FRAMER_VSYNC_POL_LOW BIT(0) |
184 | #define CDNS_DP_FRAMER_HSYNC_POL_LOW BIT(1) |
185 | #define CDNS_DP_FRAMER_INTERLACE BIT(2) |
186 | |
187 | #define CDNS_DP_LINE_THRESH(s) (CDNS_DPTX_STREAM(s) + 0x64) |
188 | #define CDNS_DP_ACTIVE_LINE_THRESH(x) (x) |
189 | |
190 | #define CDNS_DP_VB_ID(s) (CDNS_DPTX_STREAM(s) + 0x68) |
191 | #define CDNS_DP_VB_ID_INTERLACED BIT(2) |
192 | #define CDNS_DP_VB_ID_COMPRESSED BIT(6) |
193 | |
194 | #define CDNS_DP_FRONT_BACK_PORCH(s) (CDNS_DPTX_STREAM(s) + 0x78) |
195 | #define CDNS_DP_BACK_PORCH(x) (x) |
196 | #define CDNS_DP_FRONT_PORCH(x) ((x) << 16) |
197 | |
198 | #define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c) |
199 | #define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16 |
200 | |
201 | /* mailbox */ |
202 | #define MAILBOX_RETRY_US 1000 |
203 | #define MAILBOX_TIMEOUT_US 2000000 |
204 | |
205 | #define MB_OPCODE_ID 0 |
206 | #define MB_MODULE_ID 1 |
207 | #define MB_SIZE_MSB_ID 2 |
208 | #define MB_SIZE_LSB_ID 3 |
209 | #define MB_DATA_ID 4 |
210 | |
211 | #define MB_MODULE_ID_DP_TX 0x01 |
212 | #define MB_MODULE_ID_HDCP_TX 0x07 |
213 | #define MB_MODULE_ID_HDCP_RX 0x08 |
214 | #define MB_MODULE_ID_HDCP_GENERAL 0x09 |
215 | #define MB_MODULE_ID_GENERAL 0x0a |
216 | |
217 | /* firmware and opcodes */ |
218 | #define FW_NAME "cadence/mhdp8546.bin" |
219 | #define CDNS_MHDP_IMEM 0x10000 |
220 | |
221 | #define GENERAL_MAIN_CONTROL 0x01 |
222 | #define GENERAL_TEST_ECHO 0x02 |
223 | #define GENERAL_BUS_SETTINGS 0x03 |
224 | #define GENERAL_TEST_ACCESS 0x04 |
225 | #define GENERAL_REGISTER_READ 0x07 |
226 | |
227 | #define DPTX_SET_POWER_MNG 0x00 |
228 | #define DPTX_GET_EDID 0x02 |
229 | #define DPTX_READ_DPCD 0x03 |
230 | #define DPTX_WRITE_DPCD 0x04 |
231 | #define DPTX_ENABLE_EVENT 0x05 |
232 | #define DPTX_WRITE_REGISTER 0x06 |
233 | #define DPTX_READ_REGISTER 0x07 |
234 | #define DPTX_WRITE_FIELD 0x08 |
235 | #define DPTX_READ_EVENT 0x0a |
236 | #define DPTX_GET_LAST_AUX_STAUS 0x0e |
237 | #define DPTX_HPD_STATE 0x11 |
238 | #define DPTX_ADJUST_LT 0x12 |
239 | |
240 | #define FW_STANDBY 0 |
241 | #define FW_ACTIVE 1 |
242 | |
243 | /* HPD */ |
244 | #define DPTX_READ_EVENT_HPD_TO_HIGH BIT(0) |
245 | #define DPTX_READ_EVENT_HPD_TO_LOW BIT(1) |
246 | #define DPTX_READ_EVENT_HPD_PULSE BIT(2) |
247 | #define DPTX_READ_EVENT_HPD_STATE BIT(3) |
248 | |
249 | /* general */ |
250 | #define CDNS_DP_TRAINING_PATTERN_4 0x7 |
251 | |
252 | #define CDNS_KEEP_ALIVE_TIMEOUT 2000 |
253 | |
254 | #define CDNS_VOLT_SWING(x) ((x) & GENMASK(1, 0)) |
255 | #define CDNS_FORCE_VOLT_SWING BIT(2) |
256 | |
257 | #define CDNS_PRE_EMPHASIS(x) ((x) & GENMASK(1, 0)) |
258 | #define CDNS_FORCE_PRE_EMPHASIS BIT(2) |
259 | |
260 | #define CDNS_SUPPORT_TPS(x) BIT((x) - 1) |
261 | |
262 | #define CDNS_FAST_LINK_TRAINING BIT(0) |
263 | |
264 | #define CDNS_LANE_MAPPING_TYPE_C_LANE_0(x) ((x) & GENMASK(1, 0)) |
265 | #define CDNS_LANE_MAPPING_TYPE_C_LANE_1(x) ((x) & GENMASK(3, 2)) |
266 | #define CDNS_LANE_MAPPING_TYPE_C_LANE_2(x) ((x) & GENMASK(5, 4)) |
267 | #define CDNS_LANE_MAPPING_TYPE_C_LANE_3(x) ((x) & GENMASK(7, 6)) |
268 | #define CDNS_LANE_MAPPING_NORMAL 0xe4 |
269 | #define CDNS_LANE_MAPPING_FLIPPED 0x1b |
270 | |
271 | #define CDNS_DP_MAX_NUM_LANES 4 |
272 | #define CDNS_DP_TEST_VSC_SDP BIT(6) /* 1.3+ */ |
273 | #define CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY BIT(7) |
274 | |
275 | #define CDNS_MHDP_MAX_STREAMS 4 |
276 | |
277 | #define DP_LINK_CAP_ENHANCED_FRAMING BIT(0) |
278 | |
279 | struct cdns_mhdp_link { |
280 | unsigned char revision; |
281 | unsigned int rate; |
282 | unsigned int num_lanes; |
283 | unsigned long capabilities; |
284 | }; |
285 | |
286 | struct cdns_mhdp_host { |
287 | unsigned int link_rate; |
288 | u8 lanes_cnt; |
289 | u8 volt_swing; |
290 | u8 pre_emphasis; |
291 | u8 pattern_supp; |
292 | u8 lane_mapping; |
293 | bool fast_link; |
294 | bool enhanced; |
295 | bool scrambler; |
296 | bool ssc; |
297 | }; |
298 | |
299 | struct cdns_mhdp_sink { |
300 | unsigned int link_rate; |
301 | u8 lanes_cnt; |
302 | u8 pattern_supp; |
303 | bool fast_link; |
304 | bool enhanced; |
305 | bool ssc; |
306 | }; |
307 | |
308 | struct cdns_mhdp_display_fmt { |
309 | u32 color_format; |
310 | u32 bpc; |
311 | bool y_only; |
312 | }; |
313 | |
314 | /* |
315 | * These enums present MHDP hw initialization state |
316 | * Legal state transitions are: |
317 | * MHDP_HW_READY <-> MHDP_HW_STOPPED |
318 | */ |
319 | enum mhdp_hw_state { |
320 | MHDP_HW_READY = 1, /* HW ready, FW active */ |
321 | MHDP_HW_STOPPED /* Driver removal FW to be stopped */ |
322 | }; |
323 | |
324 | struct cdns_mhdp_device; |
325 | |
326 | struct mhdp_platform_ops { |
327 | int (*init)(struct cdns_mhdp_device *mhdp); |
328 | void (*exit)(struct cdns_mhdp_device *mhdp); |
329 | void (*enable)(struct cdns_mhdp_device *mhdp); |
330 | void (*disable)(struct cdns_mhdp_device *mhdp); |
331 | }; |
332 | |
333 | struct cdns_mhdp_bridge_state { |
334 | struct drm_bridge_state base; |
335 | struct drm_display_mode *current_mode; |
336 | }; |
337 | |
338 | struct cdns_mhdp_platform_info { |
339 | const u32 *input_bus_flags; |
340 | const struct mhdp_platform_ops *ops; |
341 | }; |
342 | |
343 | #define to_cdns_mhdp_bridge_state(s) \ |
344 | container_of(s, struct cdns_mhdp_bridge_state, base) |
345 | |
346 | struct cdns_mhdp_hdcp { |
347 | struct delayed_work check_work; |
348 | struct work_struct prop_work; |
349 | struct mutex mutex; /* mutex to protect hdcp.value */ |
350 | u32 value; |
351 | u8 hdcp_content_type; |
352 | }; |
353 | |
354 | struct cdns_mhdp_device { |
355 | void __iomem *regs; |
356 | void __iomem *sapb_regs; |
357 | void __iomem *j721e_regs; |
358 | |
359 | struct device *dev; |
360 | struct clk *clk; |
361 | struct phy *phy; |
362 | |
363 | const struct cdns_mhdp_platform_info *info; |
364 | |
365 | /* This is to protect mailbox communications with the firmware */ |
366 | struct mutex mbox_mutex; |
367 | |
368 | /* |
369 | * "link_mutex" protects the access to all the link parameters |
370 | * including the link training process. Link training will be |
371 | * invoked both from threaded interrupt handler and from atomic |
372 | * callbacks when link_up is not set. So this mutex protects |
373 | * flags such as link_up, bridge_enabled, link.num_lanes, |
374 | * link.rate etc. |
375 | */ |
376 | struct mutex link_mutex; |
377 | |
378 | struct drm_connector connector; |
379 | struct drm_bridge bridge; |
380 | |
381 | struct cdns_mhdp_link link; |
382 | struct drm_dp_aux aux; |
383 | |
384 | struct cdns_mhdp_host host; |
385 | struct cdns_mhdp_sink sink; |
386 | struct cdns_mhdp_display_fmt display_fmt; |
387 | u8 stream_id; |
388 | |
389 | bool link_up; |
390 | bool plugged; |
391 | |
392 | /* |
393 | * "start_lock" protects the access to bridge_attached and |
394 | * hw_state data members that control the delayed firmware |
395 | * loading and attaching the bridge. They are accessed from |
396 | * both the DRM core and cdns_mhdp_fw_cb(). In most cases just |
397 | * protecting the data members is enough, but the irq mask |
398 | * setting needs to be protected when enabling the FW. |
399 | */ |
400 | spinlock_t start_lock; |
401 | bool bridge_attached; |
402 | bool bridge_enabled; |
403 | enum mhdp_hw_state hw_state; |
404 | wait_queue_head_t fw_load_wq; |
405 | |
406 | /* Work struct to schedule a uevent on link train failure */ |
407 | struct work_struct modeset_retry_work; |
408 | struct work_struct hpd_work; |
409 | |
410 | wait_queue_head_t sw_events_wq; |
411 | u32 sw_events; |
412 | |
413 | struct cdns_mhdp_hdcp hdcp; |
414 | bool hdcp_supported; |
415 | }; |
416 | |
417 | #define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector) |
418 | #define bridge_to_mhdp(x) container_of(x, struct cdns_mhdp_device, bridge) |
419 | |
420 | u32 cdns_mhdp_wait_for_sw_event(struct cdns_mhdp_device *mhdp, uint32_t event); |
421 | |
422 | #endif |
423 | |