1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2012 Red Hat Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19 * USE OR OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * The above copyright notice and this permission notice (including the 22 * next paragraph) shall be included in all copies or substantial portions 23 * of the Software. 24 */ 25 /* 26 * Authors: Dave Airlie <airlied@redhat.com> 27 */ 28 29 #include <linux/delay.h> 30 #include <linux/pci.h> 31 32 #include <drm/drm_drv.h> 33 34 #include "ast_drv.h" 35 #include "ast_post.h" 36 37 /* 38 * DRAM type 39 */ 40 41 static enum ast_dram_layout ast_2100_get_dram_layout_p2a(struct ast_device *ast) 42 { 43 u32 mcr04; 44 enum ast_dram_layout dram_layout; 45 46 mcr04 = ast_mindwm(ast, AST_REG_MCR04); 47 48 switch (mcr04 & GENMASK(3, 2)) { 49 case 0: 50 case 4: 51 default: 52 dram_layout = AST_DRAM_512Mx16; 53 break; 54 case 8: 55 if (mcr04 & 0x40) 56 dram_layout = AST_DRAM_1Gx16; 57 else 58 dram_layout = AST_DRAM_512Mx32; 59 break; 60 case 0xc: 61 dram_layout = AST_DRAM_1Gx32; 62 break; 63 } 64 65 return dram_layout; 66 } 67 68 /* 69 * POST 70 */ 71 72 static const struct ast_dramstruct ast1100_dram_table_data[] = { 73 AST_DRAMSTRUCT_REG(AST_REG_SCU000, AST_REG_SCU000_PROTECTION_KEY), 74 AST_DRAMSTRUCT_REG(AST_REG_SCU020, 0x000041f0), 75 AST_DRAMSTRUCT_UDELAY(67u), 76 AST_DRAMSTRUCT_REG(AST_REG_MCR00, AST_REG_MCR00_PROTECTION_KEY), 77 AST_DRAMSTRUCT_REG(AST_REG_MCR6C, 0x00909090), 78 AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x00050000), 79 AST_DRAMSTRUCT_REG(AST_REG_MCR04, 0x00000585), // DRAM type 80 AST_DRAMSTRUCT_REG(AST_REG_MCR08, 0x0011030f), 81 AST_DRAMSTRUCT_REG(AST_REG_MCR10, 0x22201724), 82 AST_DRAMSTRUCT_REG(AST_REG_MCR18, 0x1e29011a), 83 AST_DRAMSTRUCT_REG(AST_REG_MCR20, 0x00c82222), 84 AST_DRAMSTRUCT_REG(AST_REG_MCR14, 0x01001523), 85 AST_DRAMSTRUCT_REG(AST_REG_MCR1C, 0x1024010d), 86 AST_DRAMSTRUCT_REG(AST_REG_MCR24, 0x00cb2522), 87 AST_DRAMSTRUCT_REG(AST_REG_MCR38, 0xffffff82), 88 AST_DRAMSTRUCT_REG(AST_REG_MCR3C, 0x00000000), 89 AST_DRAMSTRUCT_REG(AST_REG_MCR40, 0x00000000), 90 AST_DRAMSTRUCT_REG(AST_REG_MCR44, 0x00000000), 91 AST_DRAMSTRUCT_REG(AST_REG_MCR48, 0x00000000), 92 AST_DRAMSTRUCT_REG(AST_REG_MCR4C, 0x00000000), 93 AST_DRAMSTRUCT_REG(AST_REG_MCR50, 0x00000000), 94 AST_DRAMSTRUCT_REG(AST_REG_MCR54, 0x00000000), 95 AST_DRAMSTRUCT_REG(AST_REG_MCR58, 0x00000000), 96 AST_DRAMSTRUCT_REG(AST_REG_MCR5C, 0x00000000), 97 AST_DRAMSTRUCT_REG(AST_REG_MCR60, 0x032aa02a), 98 AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x002d3000), 99 AST_DRAMSTRUCT_REG(AST_REG_MCR68, 0x00000000), 100 AST_DRAMSTRUCT_REG(AST_REG_MCR70, 0x00000000), 101 AST_DRAMSTRUCT_REG(AST_REG_MCR74, 0x00000000), 102 AST_DRAMSTRUCT_REG(AST_REG_MCR78, 0x00000000), 103 AST_DRAMSTRUCT_REG(AST_REG_MCR7C, 0x00000000), 104 AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00000001), 105 AST_DRAMSTRUCT_UDELAY(67u), 106 AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000732), 107 AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040), 108 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000005), 109 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000007), 110 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003), 111 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001), 112 AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a08), 113 AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000632), 114 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001), 115 AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x000003c0), 116 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003), 117 AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040), 118 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003), 119 AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a21), 120 AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00007c03), 121 AST_DRAMSTRUCT_REG(AST_REG_MCR120, 0x00004c41), 122 AST_DRAMSTRUCT_INVALID, 123 }; 124 125 static const struct ast_dramstruct ast2100_dram_table_data[] = { 126 AST_DRAMSTRUCT_REG(AST_REG_SCU000, AST_REG_SCU000_PROTECTION_KEY), 127 AST_DRAMSTRUCT_REG(AST_REG_SCU020, 0x00004120), 128 AST_DRAMSTRUCT_UDELAY(67u), 129 AST_DRAMSTRUCT_REG(AST_REG_MCR00, AST_REG_MCR00_PROTECTION_KEY), 130 AST_DRAMSTRUCT_REG(AST_REG_MCR6C, 0x00909090), 131 AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x00070000), 132 AST_DRAMSTRUCT_REG(AST_REG_MCR04, 0x00000489), // DRAM type 133 AST_DRAMSTRUCT_REG(AST_REG_MCR08, 0x0011030f), 134 AST_DRAMSTRUCT_REG(AST_REG_MCR10, 0x32302926), 135 AST_DRAMSTRUCT_REG(AST_REG_MCR18, 0x274c0122), 136 AST_DRAMSTRUCT_REG(AST_REG_MCR20, 0x00ce2222), 137 AST_DRAMSTRUCT_REG(AST_REG_MCR14, 0x01001523), 138 AST_DRAMSTRUCT_REG(AST_REG_MCR1C, 0x1024010d), 139 AST_DRAMSTRUCT_REG(AST_REG_MCR24, 0x00cb2522), 140 AST_DRAMSTRUCT_REG(AST_REG_MCR38, 0xffffff82), 141 AST_DRAMSTRUCT_REG(AST_REG_MCR3C, 0x00000000), 142 AST_DRAMSTRUCT_REG(AST_REG_MCR40, 0x00000000), 143 AST_DRAMSTRUCT_REG(AST_REG_MCR44, 0x00000000), 144 AST_DRAMSTRUCT_REG(AST_REG_MCR48, 0x00000000), 145 AST_DRAMSTRUCT_REG(AST_REG_MCR4C, 0x00000000), 146 AST_DRAMSTRUCT_REG(AST_REG_MCR50, 0x00000000), 147 AST_DRAMSTRUCT_REG(AST_REG_MCR54, 0x00000000), 148 AST_DRAMSTRUCT_REG(AST_REG_MCR58, 0x00000000), 149 AST_DRAMSTRUCT_REG(AST_REG_MCR5C, 0x00000000), 150 AST_DRAMSTRUCT_REG(AST_REG_MCR60, 0x0f2aa02a), 151 AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x003f3005), 152 AST_DRAMSTRUCT_REG(AST_REG_MCR68, 0x02020202), 153 AST_DRAMSTRUCT_REG(AST_REG_MCR70, 0x00000000), 154 AST_DRAMSTRUCT_REG(AST_REG_MCR74, 0x00000000), 155 AST_DRAMSTRUCT_REG(AST_REG_MCR78, 0x00000000), 156 AST_DRAMSTRUCT_REG(AST_REG_MCR7C, 0x00000000), 157 AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00000001), 158 AST_DRAMSTRUCT_UDELAY(67u), 159 AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000942), 160 AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040), 161 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000005), 162 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000007), 163 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003), 164 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001), 165 AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a08), 166 AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000842), 167 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001), 168 AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x000003c0), 169 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003), 170 AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040), 171 AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003), 172 AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a21), 173 AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00007c03), 174 AST_DRAMSTRUCT_REG(AST_REG_MCR120, 0x00005061), 175 AST_DRAMSTRUCT_INVALID, 176 }; 177 178 /* 179 * AST2100/2150 DLL CBR Setting 180 */ 181 #define CBR_SIZE_AST2150 ((16 << 10) - 1) 182 #define CBR_PASSNUM_AST2150 5 183 #define CBR_THRESHOLD_AST2150 10 184 #define CBR_THRESHOLD2_AST2150 10 185 #define TIMEOUT_AST2150 5000000 186 187 #define CBR_PATNUM_AST2150 8 188 189 static const u32 pattern_AST2150[14] = { 190 0xFF00FF00, 191 0xCC33CC33, 192 0xAA55AA55, 193 0xFFFE0001, 194 0x683501FE, 195 0x0F1929B0, 196 0x2D0B4346, 197 0x60767F02, 198 0x6FBE36A6, 199 0x3A253035, 200 0x3019686D, 201 0x41C6167E, 202 0x620152BF, 203 0x20F050E0 204 }; 205 206 static u32 mmctestburst2_ast2150(struct ast_device *ast, u32 datagen) 207 { 208 u32 data, timeout; 209 210 ast_moutdwm(ast, AST_REG_MCR70, 0x00000000); 211 ast_moutdwm(ast, AST_REG_MCR70, 0x00000001 | (datagen << 3)); 212 timeout = 0; 213 do { 214 data = ast_mindwm(ast, AST_REG_MCR70) & 0x40; 215 if (++timeout > TIMEOUT_AST2150) { 216 ast_moutdwm(ast, AST_REG_MCR70, 0x00000000); 217 return 0xffffffff; 218 } 219 } while (!data); 220 ast_moutdwm(ast, AST_REG_MCR70, 0x00000000); 221 ast_moutdwm(ast, AST_REG_MCR70, 0x00000003 | (datagen << 3)); 222 timeout = 0; 223 do { 224 data = ast_mindwm(ast, AST_REG_MCR70) & 0x40; 225 if (++timeout > TIMEOUT_AST2150) { 226 ast_moutdwm(ast, AST_REG_MCR70, 0x00000000); 227 return 0xffffffff; 228 } 229 } while (!data); 230 data = (ast_mindwm(ast, AST_REG_MCR70) & 0x80) >> 7; 231 ast_moutdwm(ast, AST_REG_MCR70, 0x00000000); 232 return data; 233 } 234 235 static int cbrtest_ast2150(struct ast_device *ast) 236 { 237 int i; 238 239 for (i = 0; i < 8; i++) 240 if (mmctestburst2_ast2150(ast, i)) 241 return 0; 242 return 1; 243 } 244 245 static int cbrscan_ast2150(struct ast_device *ast, int busw) 246 { 247 u32 patcnt, loop; 248 249 for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) { 250 ast_moutdwm(ast, AST_REG_MCR7C, pattern_AST2150[patcnt]); 251 for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) { 252 if (cbrtest_ast2150(ast)) 253 break; 254 } 255 if (loop == CBR_PASSNUM_AST2150) 256 return 0; 257 } 258 return 1; 259 } 260 261 static void cbrdlli_ast2150(struct ast_device *ast, int busw) 262 { 263 u32 dll_min[4], dll_max[4], dlli, data, passcnt; 264 265 cbr_start: 266 dll_min[0] = 0xff; 267 dll_min[1] = 0xff; 268 dll_min[2] = 0xff; 269 dll_min[3] = 0xff; 270 dll_max[0] = 0x00; 271 dll_max[1] = 0x00; 272 dll_max[2] = 0x00; 273 dll_max[3] = 0x00; 274 passcnt = 0; 275 276 for (dlli = 0; dlli < 100; dlli++) { 277 ast_moutdwm(ast, AST_REG_MCR68, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 278 data = cbrscan_ast2150(ast, busw); 279 if (data != 0) { 280 if (data & 0x1) { 281 if (dll_min[0] > dlli) 282 dll_min[0] = dlli; 283 if (dll_max[0] < dlli) 284 dll_max[0] = dlli; 285 } 286 passcnt++; 287 } else if (passcnt >= CBR_THRESHOLD_AST2150) { 288 goto cbr_start; 289 } 290 } 291 if (dll_max[0] == 0 || (dll_max[0] - dll_min[0]) < CBR_THRESHOLD_AST2150) 292 goto cbr_start; 293 294 dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4); 295 ast_moutdwm(ast, AST_REG_MCR68, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 296 } 297 298 static void ast_post_chip_2100(struct ast_device *ast) 299 { 300 u8 j; 301 u32 i; 302 enum ast_dram_layout dram_layout = ast_2100_get_dram_layout_p2a(ast); 303 u32 mcr120; 304 u32 scu00c, scu040; 305 306 j = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); 307 308 if ((j & 0x80) == 0) { /* VGA only */ 309 const struct ast_dramstruct *dram_reg_info; 310 311 if (ast->chip == AST2100 || ast->chip == AST2200) 312 dram_reg_info = ast2100_dram_table_data; 313 else 314 dram_reg_info = ast1100_dram_table_data; 315 316 ast_moutdwm_poll(ast, AST_REG_SCU000, AST_REG_SCU000_PROTECTION_KEY, 0x01); 317 ast_moutdwm_poll(ast, AST_REG_MCR00, AST_REG_MCR00_PROTECTION_KEY, 0x01); 318 319 while (!AST_DRAMSTRUCT_IS(dram_reg_info, INVALID)) { 320 if (AST_DRAMSTRUCT_IS(dram_reg_info, UDELAY)) { 321 for (i = 0; i < 15; i++) 322 udelay(dram_reg_info->data); 323 } else if (AST_DRAMSTRUCT_IS_REG(dram_reg_info, AST_REG_MCR04)) { 324 u32 mcr04; 325 u32 scu070; 326 327 switch (dram_layout) { 328 case AST_DRAM_1Gx16: 329 mcr04 = 0x00000d89; 330 break; 331 case AST_DRAM_1Gx32: 332 mcr04 = 0x00000c8d; 333 break; 334 default: 335 mcr04 = dram_reg_info->data; 336 break; 337 } 338 339 /* 340 * FIXME: There might be bits already in MCR04[5:4]. Should 341 * we only do this in the default case? 342 */ 343 scu070 = ast_mindwm(ast, AST_REG_SCU070); 344 mcr04 |= (scu070 & GENMASK(3, 2)) << 2; 345 346 ast_moutdwm(ast, dram_reg_info->index, mcr04); 347 } else { 348 ast_moutdwm(ast, dram_reg_info->index, dram_reg_info->data); 349 } 350 dram_reg_info++; 351 } 352 353 /* AST 2100/2150 DRAM calibration */ 354 mcr120 = ast_mindwm(ast, AST_REG_MCR120); 355 if (mcr120 == 0x5061) { /* 266Mhz */ 356 u32 mcr04 = ast_mindwm(ast, AST_REG_MCR04); 357 358 if (mcr04 & 0x40) 359 cbrdlli_ast2150(ast, 16); /* 16 bits */ 360 else 361 cbrdlli_ast2150(ast, 32); /* 32 bits */ 362 } 363 364 scu00c = ast_mindwm(ast, AST_REG_SCU00C); 365 scu00c &= 0xfffffffd; 366 ast_moutdwm(ast, AST_REG_SCU00C, scu00c); 367 368 scu040 = ast_mindwm(ast, AST_REG_SCU040); 369 scu040 |= 0x00000040; 370 ast_moutdwm(ast, AST_REG_SCU040, scu040); 371 } 372 373 /* wait ready */ 374 do { 375 j = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); 376 } while ((j & 0x40) == 0); 377 } 378 379 int ast_2100_post(struct ast_device *ast) 380 { 381 ast_2000_set_def_ext_reg(ast); 382 383 if (ast->config_mode == ast_use_p2a) { 384 ast_post_chip_2100(ast); 385 } else { 386 if (ast->tx_chip == AST_TX_SIL164) { 387 /* Enable DVO */ 388 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); 389 } 390 } 391 392 return 0; 393 } 394 395 /* 396 * Widescreen detection 397 */ 398 399 /* Try to detect WSXGA+ on Gen2+ */ 400 bool __ast_2100_detect_wsxga_p(struct ast_device *ast) 401 { 402 u8 vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0); 403 404 if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC)) 405 return true; 406 if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN) 407 return true; 408 409 return false; 410 } 411 412 /* Try to detect WUXGA on Gen2+ */ 413 bool __ast_2100_detect_wuxga(struct ast_device *ast) 414 { 415 u8 vgacrd1; 416 417 if (ast->support_fullhd) { 418 vgacrd1 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd1); 419 if (!(vgacrd1 & AST_IO_VGACRD1_SUPPORTS_WUXGA)) 420 return true; 421 } 422 423 return false; 424 } 425 426 static void ast_2100_detect_widescreen(struct ast_device *ast) 427 { 428 if (__ast_2100_detect_wsxga_p(ast)) { 429 ast->support_wsxga_p = true; 430 if (ast->chip == AST2100) 431 ast->support_fullhd = true; 432 } 433 if (__ast_2100_detect_wuxga(ast)) 434 ast->support_wuxga = true; 435 } 436 437 static const struct ast_device_quirks ast_2100_device_quirks = { 438 .crtc_mem_req_threshold_low = 47, 439 .crtc_mem_req_threshold_high = 63, 440 }; 441 442 struct drm_device *ast_2100_device_create(struct pci_dev *pdev, 443 const struct drm_driver *drv, 444 enum ast_chip chip, 445 enum ast_config_mode config_mode, 446 void __iomem *regs, 447 void __iomem *ioregs, 448 bool need_post) 449 { 450 struct drm_device *dev; 451 struct ast_device *ast; 452 int ret; 453 454 ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base); 455 if (IS_ERR(ast)) 456 return ERR_CAST(ast); 457 dev = &ast->base; 458 459 ast_device_init(ast, chip, config_mode, regs, ioregs, &ast_2100_device_quirks); 460 461 ast->dclk_table = ast_2000_dclk_table; 462 463 ast_2000_detect_tx_chip(ast, need_post); 464 465 if (need_post) { 466 ret = ast_post_gpu(ast); 467 if (ret) 468 return ERR_PTR(ret); 469 } 470 471 ret = ast_mm_init(ast); 472 if (ret) 473 return ERR_PTR(ret); 474 475 ast_2100_detect_widescreen(ast); 476 477 ret = ast_mode_config_init(ast); 478 if (ret) 479 return ERR_PTR(ret); 480 481 return dev; 482 } 483