617 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include <linux/delay.h>4#include <linux/firmware.h>5#include <linux/module.h>6 7#include <drm/drm_atomic_state_helper.h>8#include <drm/drm_edid.h>9#include <drm/drm_modeset_helper_vtables.h>10#include <drm/drm_probe_helper.h>11 12#include "ast_drv.h"13 14MODULE_FIRMWARE("ast_dp501_fw.bin");15 16static void ast_release_firmware(void *data)17{18 struct ast_device *ast = data;19 20 release_firmware(ast->dp501_fw);21 ast->dp501_fw = NULL;22}23 24static int ast_load_dp501_microcode(struct drm_device *dev)25{26 struct ast_device *ast = to_ast_device(dev);27 int ret;28 29 ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev);30 if (ret)31 return ret;32 33 return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast);34}35 36static void send_ack(struct ast_device *ast)37{38 u8 sendack;39 sendack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0xff);40 sendack |= 0x80;41 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0x00, sendack);42}43 44static void send_nack(struct ast_device *ast)45{46 u8 sendack;47 sendack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0xff);48 sendack &= ~0x80;49 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0x00, sendack);50}51 52static bool wait_ack(struct ast_device *ast)53{54 u8 waitack;55 u32 retry = 0;56 do {57 waitack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff);58 waitack &= 0x80;59 udelay(100);60 } while ((!waitack) && (retry++ < 1000));61 62 if (retry < 1000)63 return true;64 else65 return false;66}67 68static bool wait_nack(struct ast_device *ast)69{70 u8 waitack;71 u32 retry = 0;72 do {73 waitack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff);74 waitack &= 0x80;75 udelay(100);76 } while ((waitack) && (retry++ < 1000));77 78 if (retry < 1000)79 return true;80 else81 return false;82}83 84static void set_cmd_trigger(struct ast_device *ast)85{86 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, ~0x40, 0x40);87}88 89static void clear_cmd_trigger(struct ast_device *ast)90{91 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, ~0x40, 0x00);92}93 94#if 095static bool wait_fw_ready(struct ast_device *ast)96{97 u8 waitready;98 u32 retry = 0;99 do {100 waitready = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff);101 waitready &= 0x40;102 udelay(100);103 } while ((!waitready) && (retry++ < 1000));104 105 if (retry < 1000)106 return true;107 else108 return false;109}110#endif111 112static bool ast_write_cmd(struct drm_device *dev, u8 data)113{114 struct ast_device *ast = to_ast_device(dev);115 int retry = 0;116 if (wait_nack(ast)) {117 send_nack(ast);118 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, data);119 send_ack(ast);120 set_cmd_trigger(ast);121 do {122 if (wait_ack(ast)) {123 clear_cmd_trigger(ast);124 send_nack(ast);125 return true;126 }127 } while (retry++ < 100);128 }129 clear_cmd_trigger(ast);130 send_nack(ast);131 return false;132}133 134static bool ast_write_data(struct drm_device *dev, u8 data)135{136 struct ast_device *ast = to_ast_device(dev);137 138 if (wait_nack(ast)) {139 send_nack(ast);140 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, data);141 send_ack(ast);142 if (wait_ack(ast)) {143 send_nack(ast);144 return true;145 }146 }147 send_nack(ast);148 return false;149}150 151#if 0152static bool ast_read_data(struct drm_device *dev, u8 *data)153{154 struct ast_device *ast = to_ast_device(dev);155 u8 tmp;156 157 *data = 0;158 159 if (wait_ack(ast) == false)160 return false;161 tmp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd3, 0xff);162 *data = tmp;163 if (wait_nack(ast) == false) {164 send_nack(ast);165 return false;166 }167 send_nack(ast);168 return true;169}170 171static void clear_cmd(struct ast_device *ast)172{173 send_nack(ast);174 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, 0x00);175}176#endif177 178static void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)179{180 ast_write_cmd(dev, 0x40);181 ast_write_data(dev, mode);182 183 msleep(10);184}185 186static u32 get_fw_base(struct ast_device *ast)187{188 return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;189}190 191bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)192{193 struct ast_device *ast = to_ast_device(dev);194 u32 i, data;195 u32 boot_address;196 197 if (ast->config_mode != ast_use_p2a)198 return false;199 200 data = ast_mindwm(ast, 0x1e6e2100) & 0x01;201 if (data) {202 boot_address = get_fw_base(ast);203 for (i = 0; i < size; i += 4)204 *(u32 *)(addr + i) = ast_mindwm(ast, boot_address + i);205 return true;206 }207 return false;208}209 210static bool ast_launch_m68k(struct drm_device *dev)211{212 struct ast_device *ast = to_ast_device(dev);213 u32 i, data, len = 0;214 u32 boot_address;215 u8 *fw_addr = NULL;216 u8 jreg;217 218 if (ast->config_mode != ast_use_p2a)219 return false;220 221 data = ast_mindwm(ast, 0x1e6e2100) & 0x01;222 if (!data) {223 224 if (ast->dp501_fw_addr) {225 fw_addr = ast->dp501_fw_addr;226 len = 32*1024;227 } else {228 if (!ast->dp501_fw &&229 ast_load_dp501_microcode(dev) < 0)230 return false;231 232 fw_addr = (u8 *)ast->dp501_fw->data;233 len = ast->dp501_fw->size;234 }235 /* Get BootAddress */236 ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);237 data = ast_mindwm(ast, 0x1e6e0004);238 switch (data & 0x03) {239 case 0:240 boot_address = 0x44000000;241 break;242 default:243 case 1:244 boot_address = 0x48000000;245 break;246 case 2:247 boot_address = 0x50000000;248 break;249 case 3:250 boot_address = 0x60000000;251 break;252 }253 boot_address -= 0x200000; /* -2MB */254 255 /* copy image to buffer */256 for (i = 0; i < len; i += 4) {257 data = *(u32 *)(fw_addr + i);258 ast_moutdwm(ast, boot_address + i, data);259 }260 261 /* Init SCU */262 ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);263 264 /* Launch FW */265 ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);266 ast_moutdwm(ast, 0x1e6e2100, 1);267 268 /* Update Scratch */269 data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff; /* D[11:9] = 100b: UEFI handling */270 data |= 0x800;271 ast_moutdwm(ast, 0x1e6e2040, data);272 273 jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */274 jreg |= 0x02;275 ast_set_index_reg(ast, AST_IO_VGACRI, 0x99, jreg);276 }277 return true;278}279 280static bool ast_dp501_is_connected(struct ast_device *ast)281{282 u32 boot_address, offset, data;283 284 if (ast->config_mode == ast_use_p2a) {285 boot_address = get_fw_base(ast);286 287 /* validate FW version */288 offset = AST_DP501_GBL_VERSION;289 data = ast_mindwm(ast, boot_address + offset);290 if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)291 return false;292 293 /* validate PnP Monitor */294 offset = AST_DP501_PNPMONITOR;295 data = ast_mindwm(ast, boot_address + offset);296 if (!(data & AST_DP501_PNP_CONNECTED))297 return false;298 } else {299 if (!ast->dp501_fw_buf)300 return false;301 302 /* dummy read */303 offset = 0x0000;304 data = readl(ast->dp501_fw_buf + offset);305 306 /* validate FW version */307 offset = AST_DP501_GBL_VERSION;308 data = readl(ast->dp501_fw_buf + offset);309 if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)310 return false;311 312 /* validate PnP Monitor */313 offset = AST_DP501_PNPMONITOR;314 data = readl(ast->dp501_fw_buf + offset);315 if (!(data & AST_DP501_PNP_CONNECTED))316 return false;317 }318 return true;319}320 321static int ast_dp512_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len)322{323 struct ast_device *ast = data;324 size_t rdlen = round_up(len, 4);325 u32 i, boot_address, offset, ediddata;326 327 if (block > (512 / EDID_LENGTH))328 return -EIO;329 330 offset = AST_DP501_EDID_DATA + block * EDID_LENGTH;331 332 if (ast->config_mode == ast_use_p2a) {333 boot_address = get_fw_base(ast);334 335 for (i = 0; i < rdlen; i += 4) {336 ediddata = ast_mindwm(ast, boot_address + offset + i);337 memcpy(buf, &ediddata, min((len - i), 4));338 buf += 4;339 }340 } else {341 for (i = 0; i < rdlen; i += 4) {342 ediddata = readl(ast->dp501_fw_buf + offset + i);343 memcpy(buf, &ediddata, min((len - i), 4));344 buf += 4;345 }346 }347 348 return true;349}350 351static bool ast_init_dvo(struct drm_device *dev)352{353 struct ast_device *ast = to_ast_device(dev);354 u8 jreg;355 u32 data;356 ast_write32(ast, 0xf004, 0x1e6e0000);357 ast_write32(ast, 0xf000, 0x1);358 ast_write32(ast, 0x12000, 0x1688a8a8);359 360 jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);361 if (!(jreg & 0x80)) {362 /* Init SCU DVO Settings */363 data = ast_read32(ast, 0x12008);364 /* delay phase */365 data &= 0xfffff8ff;366 data |= 0x00000500;367 ast_write32(ast, 0x12008, data);368 369 if (IS_AST_GEN4(ast)) {370 data = ast_read32(ast, 0x12084);371 /* multi-pins for DVO single-edge */372 data |= 0xfffe0000;373 ast_write32(ast, 0x12084, data);374 375 data = ast_read32(ast, 0x12088);376 /* multi-pins for DVO single-edge */377 data |= 0x000fffff;378 ast_write32(ast, 0x12088, data);379 380 data = ast_read32(ast, 0x12090);381 /* multi-pins for DVO single-edge */382 data &= 0xffffffcf;383 data |= 0x00000020;384 ast_write32(ast, 0x12090, data);385 } else { /* AST GEN5+ */386 data = ast_read32(ast, 0x12088);387 /* multi-pins for DVO single-edge */388 data |= 0x30000000;389 ast_write32(ast, 0x12088, data);390 391 data = ast_read32(ast, 0x1208c);392 /* multi-pins for DVO single-edge */393 data |= 0x000000cf;394 ast_write32(ast, 0x1208c, data);395 396 data = ast_read32(ast, 0x120a4);397 /* multi-pins for DVO single-edge */398 data |= 0xffff0000;399 ast_write32(ast, 0x120a4, data);400 401 data = ast_read32(ast, 0x120a8);402 /* multi-pins for DVO single-edge */403 data |= 0x0000000f;404 ast_write32(ast, 0x120a8, data);405 406 data = ast_read32(ast, 0x12094);407 /* multi-pins for DVO single-edge */408 data |= 0x00000002;409 ast_write32(ast, 0x12094, data);410 }411 }412 413 /* Force to DVO */414 data = ast_read32(ast, 0x1202c);415 data &= 0xfffbffff;416 ast_write32(ast, 0x1202c, data);417 418 /* Init VGA DVO Settings */419 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80);420 return true;421}422 423 424static void ast_init_analog(struct drm_device *dev)425{426 struct ast_device *ast = to_ast_device(dev);427 u32 data;428 429 /*430 * Set DAC source to VGA mode in SCU2C via the P2A431 * bridge. First configure the P2U to target the SCU432 * in case it isn't at this stage.433 */434 ast_write32(ast, 0xf004, 0x1e6e0000);435 ast_write32(ast, 0xf000, 0x1);436 437 /* Then unlock the SCU with the magic password */438 ast_write32(ast, 0x12000, 0x1688a8a8);439 ast_write32(ast, 0x12000, 0x1688a8a8);440 ast_write32(ast, 0x12000, 0x1688a8a8);441 442 /* Finally, clear bits [17:16] of SCU2c */443 data = ast_read32(ast, 0x1202c);444 data &= 0xfffcffff;445 ast_write32(ast, 0, data);446 447 /* Disable DVO */448 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x00);449}450 451void ast_init_3rdtx(struct drm_device *dev)452{453 struct ast_device *ast = to_ast_device(dev);454 u8 jreg;455 456 if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) {457 jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff);458 switch (jreg & 0x0e) {459 case 0x04:460 ast_init_dvo(dev);461 break;462 case 0x08:463 ast_launch_m68k(dev);464 break;465 case 0x0c:466 ast_init_dvo(dev);467 break;468 default:469 if (ast->tx_chip_types & BIT(AST_TX_SIL164))470 ast_init_dvo(dev);471 else472 ast_init_analog(dev);473 }474 }475}476 477/*478 * Encoder479 */480 481static const struct drm_encoder_funcs ast_dp501_encoder_funcs = {482 .destroy = drm_encoder_cleanup,483};484 485static void ast_dp501_encoder_helper_atomic_enable(struct drm_encoder *encoder,486 struct drm_atomic_state *state)487{488 struct drm_device *dev = encoder->dev;489 490 ast_set_dp501_video_output(dev, 1);491}492 493static void ast_dp501_encoder_helper_atomic_disable(struct drm_encoder *encoder,494 struct drm_atomic_state *state)495{496 struct drm_device *dev = encoder->dev;497 498 ast_set_dp501_video_output(dev, 0);499}500 501static const struct drm_encoder_helper_funcs ast_dp501_encoder_helper_funcs = {502 .atomic_enable = ast_dp501_encoder_helper_atomic_enable,503 .atomic_disable = ast_dp501_encoder_helper_atomic_disable,504};505 506/*507 * Connector508 */509 510static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)511{512 struct ast_connector *ast_connector = to_ast_connector(connector);513 int count;514 515 if (ast_connector->physical_status == connector_status_connected) {516 struct ast_device *ast = to_ast_device(connector->dev);517 const struct drm_edid *drm_edid;518 519 drm_edid = drm_edid_read_custom(connector, ast_dp512_read_edid_block, ast);520 drm_edid_connector_update(connector, drm_edid);521 count = drm_edid_connector_add_modes(connector);522 drm_edid_free(drm_edid);523 } else {524 drm_edid_connector_update(connector, NULL);525 526 /*527 * There's no EDID data without a connected monitor. Set BMC-528 * compatible modes in this case. The XGA default resolution529 * should work well for all BMCs.530 */531 count = drm_add_modes_noedid(connector, 4096, 4096);532 if (count)533 drm_set_preferred_mode(connector, 1024, 768);534 }535 536 return count;537}538 539static int ast_dp501_connector_helper_detect_ctx(struct drm_connector *connector,540 struct drm_modeset_acquire_ctx *ctx,541 bool force)542{543 struct ast_connector *ast_connector = to_ast_connector(connector);544 struct ast_device *ast = to_ast_device(connector->dev);545 enum drm_connector_status status = connector_status_disconnected;546 547 if (ast_dp501_is_connected(ast))548 status = connector_status_connected;549 550 if (status != ast_connector->physical_status)551 ++connector->epoch_counter;552 ast_connector->physical_status = status;553 554 return connector_status_connected;555}556 557static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {558 .get_modes = ast_dp501_connector_helper_get_modes,559 .detect_ctx = ast_dp501_connector_helper_detect_ctx,560};561 562static const struct drm_connector_funcs ast_dp501_connector_funcs = {563 .reset = drm_atomic_helper_connector_reset,564 .fill_modes = drm_helper_probe_single_connector_modes,565 .destroy = drm_connector_cleanup,566 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,567 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,568};569 570static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector)571{572 int ret;573 574 ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs,575 DRM_MODE_CONNECTOR_DisplayPort);576 if (ret)577 return ret;578 579 drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs);580 581 connector->interlace_allowed = 0;582 connector->doublescan_allowed = 0;583 584 connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;585 586 return 0;587}588 589int ast_dp501_output_init(struct ast_device *ast)590{591 struct drm_device *dev = &ast->base;592 struct drm_crtc *crtc = &ast->crtc;593 struct drm_encoder *encoder = &ast->output.dp501.encoder;594 struct ast_connector *ast_connector = &ast->output.dp501.connector;595 struct drm_connector *connector = &ast_connector->base;596 int ret;597 598 ret = drm_encoder_init(dev, encoder, &ast_dp501_encoder_funcs,599 DRM_MODE_ENCODER_TMDS, NULL);600 if (ret)601 return ret;602 drm_encoder_helper_add(encoder, &ast_dp501_encoder_helper_funcs);603 604 encoder->possible_crtcs = drm_crtc_mask(crtc);605 606 ret = ast_dp501_connector_init(dev, connector);607 if (ret)608 return ret;609 ast_connector->physical_status = connector->status;610 611 ret = drm_connector_attach_encoder(connector, encoder);612 if (ret)613 return ret;614 615 return 0;616}617