]> Git Repo - linux.git/blob - drivers/gpu/drm/ast/ast_dp.c
Merge tag 'ipsec-next-2023-07-19' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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_device *ast = to_ast_device(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)
123 {
124         u32 i = 0;
125         u8 bDPExecute = 1;
126         struct ast_device *ast = to_ast_device(dev);
127
128         // Wait one second then timeout.
129         while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) !=
130                 ASTDP_MCU_FW_EXECUTING) {
131                 i++;
132                 // wait 100 ms
133                 msleep(100);
134
135                 if (i >= 10) {
136                         // DP would not be ready.
137                         bDPExecute = 0;
138                         break;
139                 }
140         }
141
142         if (!bDPExecute)
143                 drm_err(dev, "Wait DPMCU executing timeout\n");
144
145         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
146                                (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
147                                ASTDP_HOST_EDID_READ_DONE);
148 }
149
150
151
152 void ast_dp_power_on_off(struct drm_device *dev, bool on)
153 {
154         struct ast_device *ast = to_ast_device(dev);
155         // Read and Turn off DP PHY sleep
156         u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
157
158         // Turn on DP PHY sleep
159         if (!on)
160                 bE3 |= AST_DP_PHY_SLEEP;
161
162         // DP Power on/off
163         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
164 }
165
166
167
168 void ast_dp_set_on_off(struct drm_device *dev, bool on)
169 {
170         struct ast_device *ast = to_ast_device(dev);
171         u8 video_on_off = on;
172
173         // Video On/Off
174         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
175
176         // If DP plug in and link successful then check video on / off status
177         if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
178                 ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
179                 video_on_off <<= 4;
180                 while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
181                                                 ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
182                         // wait 1 ms
183                         mdelay(1);
184                 }
185         }
186 }
187
188 void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
189 {
190         struct ast_device *ast = to_ast_device(crtc->dev);
191
192         u32 ulRefreshRateIndex;
193         u8 ModeIdx;
194
195         ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
196
197         switch (crtc->mode.crtc_hdisplay) {
198         case 320:
199                 ModeIdx = ASTDP_320x240_60;
200                 break;
201         case 400:
202                 ModeIdx = ASTDP_400x300_60;
203                 break;
204         case 512:
205                 ModeIdx = ASTDP_512x384_60;
206                 break;
207         case 640:
208                 ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
209                 break;
210         case 800:
211                 ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
212                 break;
213         case 1024:
214                 ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
215                 break;
216         case 1152:
217                 ModeIdx = ASTDP_1152x864_75;
218                 break;
219         case 1280:
220                 if (crtc->mode.crtc_vdisplay == 800)
221                         ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
222                 else            // 1024
223                         ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
224                 break;
225         case 1360:
226         case 1366:
227                 ModeIdx = ASTDP_1366x768_60;
228                 break;
229         case 1440:
230                 ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
231                 break;
232         case 1600:
233                 if (crtc->mode.crtc_vdisplay == 900)
234                         ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
235                 else            //1200
236                         ModeIdx = ASTDP_1600x1200_60;
237                 break;
238         case 1680:
239                 ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
240                 break;
241         case 1920:
242                 if (crtc->mode.crtc_vdisplay == 1080)
243                         ModeIdx = ASTDP_1920x1080_60;
244                 else            //1200
245                         ModeIdx = ASTDP_1920x1200_60;
246                 break;
247         default:
248                 return;
249         }
250
251         /*
252          * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
253          * CRE1[7:0]: MISC1 (default: 0x00)
254          * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
255          */
256         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, ASTDP_AND_CLEAR_MASK,
257                                ASTDP_MISC0_24bpp);
258         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
259         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
260 }
This page took 0.049602 seconds and 4 git commands to generate.