xref: /openbmc/linux/drivers/gpu/drm/ast/ast_dp.c (revision 16c8d76a)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2021, ASPEED Technology Inc.
3 // Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
4 
5 #include <linux/firmware.h>
6 #include <linux/delay.h>
7 #include <drm/drm_print.h>
8 #include "ast_drv.h"
9 
10 int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
11 {
12 	struct ast_private *ast = to_ast_private(dev);
13 	u8 i = 0, j = 0;
14 
15 	/*
16 	 * CRD1[b5]: DP MCU FW is executing
17 	 * CRDC[b0]: DP link success
18 	 * CRDF[b0]: DP HPD
19 	 * CRE5[b0]: Host reading EDID process is done
20 	 */
21 	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
22 		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
23 		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
24 		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
25 								ASTDP_HOST_EDID_READ_DONE_MASK))) {
26 		goto err_astdp_edid_not_ready;
27 	}
28 
29 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
30 							0x00);
31 
32 	for (i = 0; i < 32; i++) {
33 		/*
34 		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
35 		 */
36 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
37 					(u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
38 		j = 0;
39 
40 		/*
41 		 * CRD7[b0]: valid flag for EDID
42 		 * CRD6[b0]: mirror read pointer for EDID
43 		 */
44 		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
45 				ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
46 			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
47 						ASTDP_EDID_READ_POINTER_MASK) != i)) {
48 			/*
49 			 * Delay are getting longer with each retry.
50 			 * 1. The Delays are often 2 loops when users request "Display Settings"
51 			 *	  of right-click of mouse.
52 			 * 2. The Delays are often longer a lot when system resume from S3/S4.
53 			 */
54 			mdelay(j+1);
55 
56 			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
57 							ASTDP_MCU_FW_EXECUTING) &&
58 				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
59 							ASTDP_LINK_SUCCESS) &&
60 				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
61 				goto err_astdp_jump_out_loop_of_edid;
62 			}
63 
64 			j++;
65 			if (j > 200)
66 				goto err_astdp_jump_out_loop_of_edid;
67 		}
68 
69 		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
70 							0xD8, ASTDP_EDID_READ_DATA_MASK);
71 		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
72 								ASTDP_EDID_READ_DATA_MASK);
73 		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
74 								ASTDP_EDID_READ_DATA_MASK);
75 		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
76 								ASTDP_EDID_READ_DATA_MASK);
77 
78 		if (i == 31) {
79 			/*
80 			 * For 128-bytes EDID_1.3,
81 			 * 1. Add the value of Bytes-126 to Bytes-127.
82 			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
83 			 *		equal 0	(mod 256).
84 			 * 2. Modify Bytes-126 to be 0.
85 			 *		The Bytes-126 indicates the Number of extensions to
86 			 *		follow. 0 represents noextensions.
87 			 */
88 			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
89 			*(ediddata + 2) = 0;
90 		}
91 
92 		ediddata += 4;
93 	}
94 
95 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
96 							ASTDP_HOST_EDID_READ_DONE);
97 
98 	return 0;
99 
100 err_astdp_jump_out_loop_of_edid:
101 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
102 							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
103 							ASTDP_HOST_EDID_READ_DONE);
104 	return (~(j+256) + 1);
105 
106 err_astdp_edid_not_ready:
107 	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)))
108 		return (~0xD1 + 1);
109 	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)))
110 		return (~0xDC + 1);
111 	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)))
112 		return (~0xDF + 1);
113 	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
114 		return (~0xE5 + 1);
115 
116 	return	0;
117 }
118 
119 /*
120  * Launch Aspeed DP
121  */
122 void ast_dp_launch(struct drm_device *dev, u8 bPower)
123 {
124 	u32 i = 0, j = 0, WaitCount = 1;
125 	u8 bDPTX = 0;
126 	u8 bDPExecute = 1;
127 
128 	struct ast_private *ast = to_ast_private(dev);
129 	// S3 come back, need more time to wait BMC ready.
130 	if (bPower)
131 		WaitCount = 300;
132 
133 
134 	// Wait total count by different condition.
135 	for (j = 0; j < WaitCount; j++) {
136 		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);
137 
138 		if (bDPTX)
139 			break;
140 
141 		msleep(100);
142 	}
143 
144 	// 0xE : ASTDP with DPMCU FW handling
145 	if (bDPTX == ASTDP_DPMCU_TX) {
146 		// Wait one second then timeout.
147 		i = 0;
148 
149 		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
150 			COPROCESSOR_LAUNCH) {
151 			i++;
152 			// wait 100 ms
153 			msleep(100);
154 
155 			if (i >= 10) {
156 				// DP would not be ready.
157 				bDPExecute = 0;
158 				break;
159 			}
160 		}
161 
162 		if (bDPExecute)
163 			ast->tx_chip_type = AST_TX_ASTDP;
164 
165 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
166 							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
167 							ASTDP_HOST_EDID_READ_DONE);
168 	} else
169 		ast->tx_chip_type = AST_TX_NONE;
170 }
171 
172 
173 
174 void ast_dp_power_on_off(struct drm_device *dev, bool on)
175 {
176 	struct ast_private *ast = to_ast_private(dev);
177 	// Read and Turn off DP PHY sleep
178 	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
179 
180 	// Turn on DP PHY sleep
181 	if (!on)
182 		bE3 |= AST_DP_PHY_SLEEP;
183 
184 	// DP Power on/off
185 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
186 }
187 
188 
189 
190 void ast_dp_set_on_off(struct drm_device *dev, bool on)
191 {
192 	struct ast_private *ast = to_ast_private(dev);
193 	u8 video_on_off = on;
194 
195 	// Video On/Off
196 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
197 
198 	// If DP plug in and link successful then check video on / off status
199 	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
200 		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
201 		video_on_off <<= 4;
202 		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
203 						ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
204 			// wait 1 ms
205 			mdelay(1);
206 		}
207 	}
208 }
209 
210 void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
211 {
212 	struct ast_private *ast = to_ast_private(crtc->dev);
213 
214 	u32 ulRefreshRateIndex;
215 	u8 ModeIdx;
216 
217 	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
218 
219 	switch (crtc->mode.crtc_hdisplay) {
220 	case 320:
221 		ModeIdx = ASTDP_320x240_60;
222 		break;
223 	case 400:
224 		ModeIdx = ASTDP_400x300_60;
225 		break;
226 	case 512:
227 		ModeIdx = ASTDP_512x384_60;
228 		break;
229 	case 640:
230 		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
231 		break;
232 	case 800:
233 		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
234 		break;
235 	case 1024:
236 		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
237 		break;
238 	case 1152:
239 		ModeIdx = ASTDP_1152x864_75;
240 		break;
241 	case 1280:
242 		if (crtc->mode.crtc_vdisplay == 800)
243 			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
244 		else		// 1024
245 			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
246 		break;
247 	case 1360:
248 	case 1366:
249 		ModeIdx = ASTDP_1366x768_60;
250 		break;
251 	case 1440:
252 		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
253 		break;
254 	case 1600:
255 		if (crtc->mode.crtc_vdisplay == 900)
256 			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
257 		else		//1200
258 			ModeIdx = ASTDP_1600x1200_60;
259 		break;
260 	case 1680:
261 		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
262 		break;
263 	case 1920:
264 		if (crtc->mode.crtc_vdisplay == 1080)
265 			ModeIdx = ASTDP_1920x1080_60;
266 		else		//1200
267 			ModeIdx = ASTDP_1920x1200_60;
268 		break;
269 	default:
270 		return;
271 	}
272 
273 	/*
274 	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
275 	 * CRE1[7:0]: MISC1 (default: 0x00)
276 	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
277 	 */
278 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
279 				ASTDP_MISC0_24bpp);
280 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
281 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) ~ASTDP_CLEAR_MASK, ModeIdx);
282 }
283