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