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