diff options
Diffstat (limited to 'drivers/gpu/drm/ast/ast_main.c')
-rw-r--r-- | drivers/gpu/drm/ast/ast_main.c | 235 |
1 files changed, 162 insertions, 73 deletions
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 2f3ad5f949fc..44b9b5f659fc 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -26,6 +26,7 @@ * Authors: Dave Airlie <airlied@redhat.com> */ +#include <linux/of.h> #include <linux/pci.h> #include <drm/drm_atomic_helper.h> @@ -35,105 +36,184 @@ #include "ast_drv.h" +/* Try to detect WSXGA+ on Gen2+ */ +static bool __ast_2100_detect_wsxga_p(struct ast_device *ast) +{ + u8 vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0); + + if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC)) + return true; + if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN) + return true; + + return false; +} + +/* Try to detect WUXGA on Gen2+ */ +static bool __ast_2100_detect_wuxga(struct ast_device *ast) +{ + u8 vgacrd1; + + if (ast->support_fullhd) { + vgacrd1 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd1); + if (!(vgacrd1 & AST_IO_VGACRD1_SUPPORTS_WUXGA)) + return true; + } + + return false; +} + static void ast_detect_widescreen(struct ast_device *ast) { - u8 jreg; + ast->support_wsxga_p = false; + ast->support_fullhd = false; + ast->support_wuxga = false; - /* Check if we support wide screen */ - switch (AST_GEN(ast)) { - case 1: - ast->support_wide_screen = false; - break; - default: - jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); - if (!(jreg & 0x80)) - ast->support_wide_screen = true; - else if (jreg & 0x01) - ast->support_wide_screen = true; - else { - ast->support_wide_screen = false; - if (ast->chip == AST1300) - ast->support_wide_screen = true; - if (ast->chip == AST1400) - ast->support_wide_screen = true; - if (ast->chip == AST2510) - ast->support_wide_screen = true; - if (IS_AST_GEN7(ast)) - ast->support_wide_screen = true; + if (AST_GEN(ast) >= 7) { + ast->support_wsxga_p = true; + ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; + } else if (AST_GEN(ast) >= 6) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + else if (ast->chip == AST2510) + ast->support_wsxga_p = true; + if (ast->support_wsxga_p) + ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; + } else if (AST_GEN(ast) >= 5) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + else if (ast->chip == AST1400) + ast->support_wsxga_p = true; + if (ast->support_wsxga_p) + ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; + } else if (AST_GEN(ast) >= 4) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + else if (ast->chip == AST1300) + ast->support_wsxga_p = true; + if (ast->support_wsxga_p) + ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; + } else if (AST_GEN(ast) >= 3) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + if (ast->support_wsxga_p) { + if (ast->chip == AST2200) + ast->support_fullhd = true; } - break; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; + } else if (AST_GEN(ast) >= 2) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + if (ast->support_wsxga_p) { + if (ast->chip == AST2100) + ast->support_fullhd = true; + } + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; } } static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) { + static const char * const info_str[] = { + "analog VGA", + "Sil164 TMDS transmitter", + "DP501 DisplayPort transmitter", + "ASPEED DisplayPort transmitter", + }; + struct drm_device *dev = &ast->base; - u8 jreg; + u8 vgacra3, vgacrd1; /* Check 3rd Tx option (digital output afaik) */ - ast->tx_chip_types |= AST_TX_NONE_BIT; - - /* - * VGACRA3 Enhanced Color Mode Register, check if DVO is already - * enabled, in that case, assume we have a SIL164 TMDS transmitter - * - * Don't make that assumption if we the chip wasn't enabled and - * is at power-on reset, otherwise we'll incorrectly "detect" a - * SIL164 when there is none. - */ - if (!need_post) { - jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); - if (jreg & 0x80) - ast->tx_chip_types = AST_TX_SIL164_BIT; - } + ast->tx_chip = AST_TX_NONE; - if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { + if (AST_GEN(ast) <= 3) { /* - * On AST GEN4+, look the configuration set by the SoC in + * VGACRA3 Enhanced Color Mode Register, check if DVO is already + * enabled, in that case, assume we have a SIL164 TMDS transmitter + * + * Don't make that assumption if we the chip wasn't enabled and + * is at power-on reset, otherwise we'll incorrectly "detect" a + * SIL164 when there is none. + */ + if (!need_post) { + vgacra3 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); + if (vgacra3 & AST_IO_VGACRA3_DVO_ENABLED) + ast->tx_chip = AST_TX_SIL164; + } + } else { + /* + * On AST GEN4+, look at the configuration set by the SoC in * the SOC scratch register #1 bits 11:8 (interestingly marked * as "reserved" in the spec) */ - jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff); - switch (jreg) { - case 0x04: - ast->tx_chip_types = AST_TX_SIL164_BIT; + vgacrd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, + AST_IO_VGACRD1_TX_TYPE_MASK); + switch (vgacrd1) { + /* + * GEN4 to GEN6 + */ + case AST_IO_VGACRD1_TX_SIL164_VBIOS: + ast->tx_chip = AST_TX_SIL164; break; - case 0x08: + case AST_IO_VGACRD1_TX_DP501_VBIOS: ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL); if (ast->dp501_fw_addr) { /* backup firmware */ - if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) { + if (ast_backup_fw(ast, ast->dp501_fw_addr, 32*1024)) { drmm_kfree(dev, ast->dp501_fw_addr); ast->dp501_fw_addr = NULL; } } fallthrough; - case 0x0c: - ast->tx_chip_types = AST_TX_DP501_BIT; - } - } else if (IS_AST_GEN7(ast)) { - if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, TX_TYPE_MASK) == - ASTDP_DPMCU_TX) { - ast->tx_chip_types = AST_TX_ASTDP_BIT; - ast_dp_launch(&ast->base); + case AST_IO_VGACRD1_TX_FW_EMBEDDED_FW: + ast->tx_chip = AST_TX_DP501; + break; + /* + * GEN7+ + */ + case AST_IO_VGACRD1_TX_ASTDP: + ast->tx_chip = AST_TX_ASTDP; + break; + /* + * Several of the listed TX chips are not explicitly supported + * by the ast driver. If these exist in real-world devices, they + * are most likely reported as VGA or SIL164 outputs. We warn here + * to get bug reports for these devices. If none come in for some + * time, we can begin to fail device probing on these values. + */ + case AST_IO_VGACRD1_TX_ITE66121_VBIOS: + drm_warn(dev, "ITE IT66121 detected, 0x%x, Gen%lu\n", + vgacrd1, AST_GEN(ast)); + break; + case AST_IO_VGACRD1_TX_CH7003_VBIOS: + drm_warn(dev, "Chrontel CH7003 detected, 0x%x, Gen%lu\n", + vgacrd1, AST_GEN(ast)); + break; + case AST_IO_VGACRD1_TX_ANX9807_VBIOS: + drm_warn(dev, "Analogix ANX9807 detected, 0x%x, Gen%lu\n", + vgacrd1, AST_GEN(ast)); + break; } } - /* Print stuff for diagnostic purposes */ - if (ast->tx_chip_types & AST_TX_NONE_BIT) - drm_info(dev, "Using analog VGA\n"); - if (ast->tx_chip_types & AST_TX_SIL164_BIT) - drm_info(dev, "Using Sil164 TMDS transmitter\n"); - if (ast->tx_chip_types & AST_TX_DP501_BIT) - drm_info(dev, "Using DP501 DisplayPort transmitter\n"); - if (ast->tx_chip_types & AST_TX_ASTDP_BIT) - drm_info(dev, "Using ASPEED DisplayPort transmitter\n"); + drm_info(dev, "Using %s\n", info_str[ast->tx_chip]); } -static int ast_get_dram_info(struct drm_device *dev) +static int ast_get_dram_info(struct ast_device *ast) { + struct drm_device *dev = &ast->base; struct device_node *np = dev->dev->of_node; - struct ast_device *ast = to_ast_device(dev); uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap; uint32_t denum, num, div, ref_pll, dsel; @@ -272,18 +352,25 @@ struct drm_device *ast_device_create(struct pci_dev *pdev, ast->regs = regs; ast->ioregs = ioregs; - ast_detect_widescreen(ast); - ast_detect_tx_chip(ast, need_post); - - ret = ast_get_dram_info(dev); + ret = ast_get_dram_info(ast); if (ret) return ERR_PTR(ret); - drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n", ast->mclk, ast->dram_type, ast->dram_bus_width); - if (need_post) - ast_post_gpu(dev); + ast_detect_tx_chip(ast, need_post); + switch (ast->tx_chip) { + case AST_TX_ASTDP: + ret = ast_post_gpu(ast); + break; + default: + ret = 0; + if (need_post) + ret = ast_post_gpu(ast); + break; + } + if (ret) + return ERR_PTR(ret); ret = ast_mm_init(ast); if (ret) @@ -297,6 +384,8 @@ struct drm_device *ast_device_create(struct pci_dev *pdev, drm_info(dev, "failed to map reserved buffer!\n"); } + ast_detect_widescreen(ast); + ret = ast_mode_config_init(ast); if (ret) return ERR_PTR(ret); |