]> Git Repo - linux.git/blob - drivers/gpu/drm/ast/ast_dp.c
Merge tag 'ucount-rlimits-cleanups-for-v5.19' of git://git.kernel.org/pub/scm/linux...
[linux.git] / drivers / gpu / drm / ast / ast_dp.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2021, ASPEED Technology Inc.
3 // Authors: KuoHsiang Chou <[email protected]>
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                                        ASTDP_AND_CLEAR_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_types |= BIT(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         }
169 }
170
171
172
173 void ast_dp_power_on_off(struct drm_device *dev, bool on)
174 {
175         struct ast_private *ast = to_ast_private(dev);
176         // Read and Turn off DP PHY sleep
177         u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
178
179         // Turn on DP PHY sleep
180         if (!on)
181                 bE3 |= AST_DP_PHY_SLEEP;
182
183         // DP Power on/off
184         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
185 }
186
187
188
189 void ast_dp_set_on_off(struct drm_device *dev, bool on)
190 {
191         struct ast_private *ast = to_ast_private(dev);
192         u8 video_on_off = on;
193
194         // Video On/Off
195         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
196
197         // If DP plug in and link successful then check video on / off status
198         if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
199                 ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
200                 video_on_off <<= 4;
201                 while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
202                                                 ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
203                         // wait 1 ms
204                         mdelay(1);
205                 }
206         }
207 }
208
209 void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
210 {
211         struct ast_private *ast = to_ast_private(crtc->dev);
212
213         u32 ulRefreshRateIndex;
214         u8 ModeIdx;
215
216         ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
217
218         switch (crtc->mode.crtc_hdisplay) {
219         case 320:
220                 ModeIdx = ASTDP_320x240_60;
221                 break;
222         case 400:
223                 ModeIdx = ASTDP_400x300_60;
224                 break;
225         case 512:
226                 ModeIdx = ASTDP_512x384_60;
227                 break;
228         case 640:
229                 ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
230                 break;
231         case 800:
232                 ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
233                 break;
234         case 1024:
235                 ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
236                 break;
237         case 1152:
238                 ModeIdx = ASTDP_1152x864_75;
239                 break;
240         case 1280:
241                 if (crtc->mode.crtc_vdisplay == 800)
242                         ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
243                 else            // 1024
244                         ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
245                 break;
246         case 1360:
247         case 1366:
248                 ModeIdx = ASTDP_1366x768_60;
249                 break;
250         case 1440:
251                 ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
252                 break;
253         case 1600:
254                 if (crtc->mode.crtc_vdisplay == 900)
255                         ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
256                 else            //1200
257                         ModeIdx = ASTDP_1600x1200_60;
258                 break;
259         case 1680:
260                 ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
261                 break;
262         case 1920:
263                 if (crtc->mode.crtc_vdisplay == 1080)
264                         ModeIdx = ASTDP_1920x1080_60;
265                 else            //1200
266                         ModeIdx = ASTDP_1920x1200_60;
267                 break;
268         default:
269                 return;
270         }
271
272         /*
273          * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
274          * CRE1[7:0]: MISC1 (default: 0x00)
275          * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
276          */
277         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, ASTDP_AND_CLEAR_MASK,
278                                ASTDP_MISC0_24bpp);
279         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
280         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
281 }
This page took 0.04997 seconds and 4 git commands to generate.