summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/ast/ast_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/ast/ast_main.c')
-rw-r--r--drivers/gpu/drm/ast/ast_main.c235
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);