1 /* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 18 * USE OR OTHER DEALINGS IN THE SOFTWARE. 19 * 20 * The above copyright notice and this permission notice (including the 21 * next paragraph) shall be included in all copies or substantial portions 22 * of the Software. 23 * 24 */ 25 /* 26 * Authors: Dave Airlie <airlied@redhat.com> 27 */ 28 29 #include <linux/of.h> 30 #include <linux/pci.h> 31 32 #include <drm/drm_atomic_helper.h> 33 #include <drm/drm_drv.h> 34 #include <drm/drm_gem.h> 35 #include <drm/drm_managed.h> 36 37 #include "ast_drv.h" 38 39 /* Try to detect WSXGA+ on Gen2+ */ 40 static bool __ast_2100_detect_wsxga_p(struct ast_device *ast) 41 { 42 u8 vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0); 43 44 if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC)) 45 return true; 46 if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN) 47 return true; 48 49 return false; 50 } 51 52 /* Try to detect WUXGA on Gen2+ */ 53 static bool __ast_2100_detect_wuxga(struct ast_device *ast) 54 { 55 u8 vgacrd1; 56 57 if (ast->support_fullhd) { 58 vgacrd1 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd1); 59 if (!(vgacrd1 & AST_IO_VGACRD1_SUPPORTS_WUXGA)) 60 return true; 61 } 62 63 return false; 64 } 65 66 static void ast_detect_widescreen(struct ast_device *ast) 67 { 68 ast->support_wsxga_p = false; 69 ast->support_fullhd = false; 70 ast->support_wuxga = false; 71 72 if (AST_GEN(ast) >= 7) { 73 ast->support_wsxga_p = true; 74 ast->support_fullhd = true; 75 if (__ast_2100_detect_wuxga(ast)) 76 ast->support_wuxga = true; 77 } else if (AST_GEN(ast) >= 6) { 78 if (__ast_2100_detect_wsxga_p(ast)) 79 ast->support_wsxga_p = true; 80 else if (ast->chip == AST2510) 81 ast->support_wsxga_p = true; 82 if (ast->support_wsxga_p) 83 ast->support_fullhd = true; 84 if (__ast_2100_detect_wuxga(ast)) 85 ast->support_wuxga = true; 86 } else if (AST_GEN(ast) >= 5) { 87 if (__ast_2100_detect_wsxga_p(ast)) 88 ast->support_wsxga_p = true; 89 else if (ast->chip == AST1400) 90 ast->support_wsxga_p = true; 91 if (ast->support_wsxga_p) 92 ast->support_fullhd = true; 93 if (__ast_2100_detect_wuxga(ast)) 94 ast->support_wuxga = true; 95 } else if (AST_GEN(ast) >= 4) { 96 if (__ast_2100_detect_wsxga_p(ast)) 97 ast->support_wsxga_p = true; 98 else if (ast->chip == AST1300) 99 ast->support_wsxga_p = true; 100 if (ast->support_wsxga_p) 101 ast->support_fullhd = true; 102 if (__ast_2100_detect_wuxga(ast)) 103 ast->support_wuxga = true; 104 } else if (AST_GEN(ast) >= 3) { 105 if (__ast_2100_detect_wsxga_p(ast)) 106 ast->support_wsxga_p = true; 107 if (ast->support_wsxga_p) { 108 if (ast->chip == AST2200) 109 ast->support_fullhd = true; 110 } 111 if (__ast_2100_detect_wuxga(ast)) 112 ast->support_wuxga = true; 113 } else if (AST_GEN(ast) >= 2) { 114 if (__ast_2100_detect_wsxga_p(ast)) 115 ast->support_wsxga_p = true; 116 if (ast->support_wsxga_p) { 117 if (ast->chip == AST2100) 118 ast->support_fullhd = true; 119 } 120 if (__ast_2100_detect_wuxga(ast)) 121 ast->support_wuxga = true; 122 } 123 } 124 125 static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) 126 { 127 static const char * const info_str[] = { 128 "analog VGA", 129 "Sil164 TMDS transmitter", 130 "DP501 DisplayPort transmitter", 131 "ASPEED DisplayPort transmitter", 132 }; 133 134 struct drm_device *dev = &ast->base; 135 u8 vgacra3, vgacrd1; 136 137 /* Check 3rd Tx option (digital output afaik) */ 138 ast->tx_chip = AST_TX_NONE; 139 140 if (AST_GEN(ast) <= 3) { 141 /* 142 * VGACRA3 Enhanced Color Mode Register, check if DVO is already 143 * enabled, in that case, assume we have a SIL164 TMDS transmitter 144 * 145 * Don't make that assumption if we the chip wasn't enabled and 146 * is at power-on reset, otherwise we'll incorrectly "detect" a 147 * SIL164 when there is none. 148 */ 149 if (!need_post) { 150 vgacra3 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); 151 if (vgacra3 & AST_IO_VGACRA3_DVO_ENABLED) 152 ast->tx_chip = AST_TX_SIL164; 153 } 154 } else { 155 /* 156 * On AST GEN4+, look at the configuration set by the SoC in 157 * the SOC scratch register #1 bits 11:8 (interestingly marked 158 * as "reserved" in the spec) 159 */ 160 vgacrd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 161 AST_IO_VGACRD1_TX_TYPE_MASK); 162 switch (vgacrd1) { 163 /* 164 * GEN4 to GEN6 165 */ 166 case AST_IO_VGACRD1_TX_SIL164_VBIOS: 167 ast->tx_chip = AST_TX_SIL164; 168 break; 169 case AST_IO_VGACRD1_TX_DP501_VBIOS: 170 ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL); 171 if (ast->dp501_fw_addr) { 172 /* backup firmware */ 173 if (ast_backup_fw(ast, ast->dp501_fw_addr, 32*1024)) { 174 drmm_kfree(dev, ast->dp501_fw_addr); 175 ast->dp501_fw_addr = NULL; 176 } 177 } 178 fallthrough; 179 case AST_IO_VGACRD1_TX_FW_EMBEDDED_FW: 180 ast->tx_chip = AST_TX_DP501; 181 break; 182 /* 183 * GEN7+ 184 */ 185 case AST_IO_VGACRD1_TX_ASTDP: 186 ast->tx_chip = AST_TX_ASTDP; 187 break; 188 /* 189 * Several of the listed TX chips are not explicitly supported 190 * by the ast driver. If these exist in real-world devices, they 191 * are most likely reported as VGA or SIL164 outputs. We warn here 192 * to get bug reports for these devices. If none come in for some 193 * time, we can begin to fail device probing on these values. 194 */ 195 case AST_IO_VGACRD1_TX_ITE66121_VBIOS: 196 drm_warn(dev, "ITE IT66121 detected, 0x%x, Gen%lu\n", 197 vgacrd1, AST_GEN(ast)); 198 break; 199 case AST_IO_VGACRD1_TX_CH7003_VBIOS: 200 drm_warn(dev, "Chrontel CH7003 detected, 0x%x, Gen%lu\n", 201 vgacrd1, AST_GEN(ast)); 202 break; 203 case AST_IO_VGACRD1_TX_ANX9807_VBIOS: 204 drm_warn(dev, "Analogix ANX9807 detected, 0x%x, Gen%lu\n", 205 vgacrd1, AST_GEN(ast)); 206 break; 207 } 208 } 209 210 drm_info(dev, "Using %s\n", info_str[ast->tx_chip]); 211 } 212 213 struct drm_device *ast_device_create(struct pci_dev *pdev, 214 const struct drm_driver *drv, 215 enum ast_chip chip, 216 enum ast_config_mode config_mode, 217 void __iomem *regs, 218 void __iomem *ioregs, 219 bool need_post) 220 { 221 struct drm_device *dev; 222 struct ast_device *ast; 223 int ret; 224 225 ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base); 226 if (IS_ERR(ast)) 227 return ERR_CAST(ast); 228 dev = &ast->base; 229 230 ast->chip = chip; 231 ast->config_mode = config_mode; 232 ast->regs = regs; 233 ast->ioregs = ioregs; 234 235 ast_detect_tx_chip(ast, need_post); 236 switch (ast->tx_chip) { 237 case AST_TX_ASTDP: 238 ret = ast_post_gpu(ast); 239 break; 240 default: 241 ret = 0; 242 if (need_post) 243 ret = ast_post_gpu(ast); 244 break; 245 } 246 if (ret) 247 return ERR_PTR(ret); 248 249 ret = ast_mm_init(ast); 250 if (ret) 251 return ERR_PTR(ret); 252 253 /* map reserved buffer */ 254 ast->dp501_fw_buf = NULL; 255 if (ast->vram_size < pci_resource_len(pdev, 0)) { 256 ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0); 257 if (!ast->dp501_fw_buf) 258 drm_info(dev, "failed to map reserved buffer!\n"); 259 } 260 261 ast_detect_widescreen(ast); 262 263 ret = ast_mode_config_init(ast); 264 if (ret) 265 return ERR_PTR(ret); 266 267 return dev; 268 } 269