Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2021, ASPEED Technology Inc.
0003 // Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
0004 
0005 #include <linux/firmware.h>
0006 #include <linux/delay.h>
0007 #include <drm/drm_print.h>
0008 #include "ast_drv.h"
0009 
0010 int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
0011 {
0012     struct ast_private *ast = to_ast_private(dev);
0013     u8 i = 0, j = 0;
0014 
0015     /*
0016      * CRD1[b5]: DP MCU FW is executing
0017      * CRDC[b0]: DP link success
0018      * CRDF[b0]: DP HPD
0019      * CRE5[b0]: Host reading EDID process is done
0020      */
0021     if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
0022         ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
0023         ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
0024         ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
0025                                 ASTDP_HOST_EDID_READ_DONE_MASK))) {
0026         goto err_astdp_edid_not_ready;
0027     }
0028 
0029     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
0030                             0x00);
0031 
0032     for (i = 0; i < 32; i++) {
0033         /*
0034          * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
0035          */
0036         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
0037                        ASTDP_AND_CLEAR_MASK, (u8)i);
0038         j = 0;
0039 
0040         /*
0041          * CRD7[b0]: valid flag for EDID
0042          * CRD6[b0]: mirror read pointer for EDID
0043          */
0044         while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
0045                 ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
0046             (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
0047                         ASTDP_EDID_READ_POINTER_MASK) != i)) {
0048             /*
0049              * Delay are getting longer with each retry.
0050              * 1. The Delays are often 2 loops when users request "Display Settings"
0051              *    of right-click of mouse.
0052              * 2. The Delays are often longer a lot when system resume from S3/S4.
0053              */
0054             mdelay(j+1);
0055 
0056             if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
0057                             ASTDP_MCU_FW_EXECUTING) &&
0058                 ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
0059                             ASTDP_LINK_SUCCESS) &&
0060                 ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
0061                 goto err_astdp_jump_out_loop_of_edid;
0062             }
0063 
0064             j++;
0065             if (j > 200)
0066                 goto err_astdp_jump_out_loop_of_edid;
0067         }
0068 
0069         *(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
0070                             0xD8, ASTDP_EDID_READ_DATA_MASK);
0071         *(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
0072                                 ASTDP_EDID_READ_DATA_MASK);
0073         *(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
0074                                 ASTDP_EDID_READ_DATA_MASK);
0075         *(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
0076                                 ASTDP_EDID_READ_DATA_MASK);
0077 
0078         if (i == 31) {
0079             /*
0080              * For 128-bytes EDID_1.3,
0081              * 1. Add the value of Bytes-126 to Bytes-127.
0082              *      The Bytes-127 is Checksum. Sum of all 128bytes should
0083              *      equal 0 (mod 256).
0084              * 2. Modify Bytes-126 to be 0.
0085              *      The Bytes-126 indicates the Number of extensions to
0086              *      follow. 0 represents noextensions.
0087              */
0088             *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
0089             *(ediddata + 2) = 0;
0090         }
0091 
0092         ediddata += 4;
0093     }
0094 
0095     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
0096                             ASTDP_HOST_EDID_READ_DONE);
0097 
0098     return 0;
0099 
0100 err_astdp_jump_out_loop_of_edid:
0101     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
0102                             (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
0103                             ASTDP_HOST_EDID_READ_DONE);
0104     return (~(j+256) + 1);
0105 
0106 err_astdp_edid_not_ready:
0107     if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)))
0108         return (~0xD1 + 1);
0109     if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)))
0110         return (~0xDC + 1);
0111     if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)))
0112         return (~0xDF + 1);
0113     if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
0114         return (~0xE5 + 1);
0115 
0116     return  0;
0117 }
0118 
0119 /*
0120  * Launch Aspeed DP
0121  */
0122 void ast_dp_launch(struct drm_device *dev, u8 bPower)
0123 {
0124     u32 i = 0, j = 0, WaitCount = 1;
0125     u8 bDPTX = 0;
0126     u8 bDPExecute = 1;
0127 
0128     struct ast_private *ast = to_ast_private(dev);
0129     // S3 come back, need more time to wait BMC ready.
0130     if (bPower)
0131         WaitCount = 300;
0132 
0133 
0134     // Wait total count by different condition.
0135     for (j = 0; j < WaitCount; j++) {
0136         bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);
0137 
0138         if (bDPTX)
0139             break;
0140 
0141         msleep(100);
0142     }
0143 
0144     // 0xE : ASTDP with DPMCU FW handling
0145     if (bDPTX == ASTDP_DPMCU_TX) {
0146         // Wait one second then timeout.
0147         i = 0;
0148 
0149         while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
0150             COPROCESSOR_LAUNCH) {
0151             i++;
0152             // wait 100 ms
0153             msleep(100);
0154 
0155             if (i >= 10) {
0156                 // DP would not be ready.
0157                 bDPExecute = 0;
0158                 break;
0159             }
0160         }
0161 
0162         if (bDPExecute)
0163             ast->tx_chip_types |= BIT(AST_TX_ASTDP);
0164 
0165         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
0166                             (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
0167                             ASTDP_HOST_EDID_READ_DONE);
0168     }
0169 }
0170 
0171 
0172 
0173 void ast_dp_power_on_off(struct drm_device *dev, bool on)
0174 {
0175     struct ast_private *ast = to_ast_private(dev);
0176     // Read and Turn off DP PHY sleep
0177     u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
0178 
0179     // Turn on DP PHY sleep
0180     if (!on)
0181         bE3 |= AST_DP_PHY_SLEEP;
0182 
0183     // DP Power on/off
0184     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
0185 }
0186 
0187 
0188 
0189 void ast_dp_set_on_off(struct drm_device *dev, bool on)
0190 {
0191     struct ast_private *ast = to_ast_private(dev);
0192     u8 video_on_off = on;
0193 
0194     // Video On/Off
0195     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
0196 
0197     // If DP plug in and link successful then check video on / off status
0198     if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
0199         ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
0200         video_on_off <<= 4;
0201         while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
0202                         ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
0203             // wait 1 ms
0204             mdelay(1);
0205         }
0206     }
0207 }
0208 
0209 void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
0210 {
0211     struct ast_private *ast = to_ast_private(crtc->dev);
0212 
0213     u32 ulRefreshRateIndex;
0214     u8 ModeIdx;
0215 
0216     ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
0217 
0218     switch (crtc->mode.crtc_hdisplay) {
0219     case 320:
0220         ModeIdx = ASTDP_320x240_60;
0221         break;
0222     case 400:
0223         ModeIdx = ASTDP_400x300_60;
0224         break;
0225     case 512:
0226         ModeIdx = ASTDP_512x384_60;
0227         break;
0228     case 640:
0229         ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
0230         break;
0231     case 800:
0232         ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
0233         break;
0234     case 1024:
0235         ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
0236         break;
0237     case 1152:
0238         ModeIdx = ASTDP_1152x864_75;
0239         break;
0240     case 1280:
0241         if (crtc->mode.crtc_vdisplay == 800)
0242             ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
0243         else        // 1024
0244             ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
0245         break;
0246     case 1360:
0247     case 1366:
0248         ModeIdx = ASTDP_1366x768_60;
0249         break;
0250     case 1440:
0251         ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
0252         break;
0253     case 1600:
0254         if (crtc->mode.crtc_vdisplay == 900)
0255             ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
0256         else        //1200
0257             ModeIdx = ASTDP_1600x1200_60;
0258         break;
0259     case 1680:
0260         ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
0261         break;
0262     case 1920:
0263         if (crtc->mode.crtc_vdisplay == 1080)
0264             ModeIdx = ASTDP_1920x1080_60;
0265         else        //1200
0266             ModeIdx = ASTDP_1920x1200_60;
0267         break;
0268     default:
0269         return;
0270     }
0271 
0272     /*
0273      * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
0274      * CRE1[7:0]: MISC1 (default: 0x00)
0275      * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
0276      */
0277     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, ASTDP_AND_CLEAR_MASK,
0278                    ASTDP_MISC0_24bpp);
0279     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
0280     ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
0281 }