MAINTAINERS: update the LSM maintainer info
[platform/kernel/linux-starfive.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 <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 }