From 437f285cf41c87a6c46c35ef70bbcee6c45bd9be Mon Sep 17 00:00:00 2001 From: wangkaiyuan Date: Fri, 4 Jul 2025 14:30:38 +0800 Subject: [PATCH] anolis: drm/ast: support 1.15.1-4 Signed-off-by: wangkaiyuan --- kmod-ast.spec | 2 +- src/Kconfig | 13 + src/Makefile | 2 +- src/ast_cursor.c | 289 ------------ src/ast_dp.c | 161 +++++-- src/ast_dp501.c | 117 ++--- src/ast_dram_2500.c | 4 +- src/ast_drv.c | 121 ++--- src/ast_drv.h | 260 ++++------ src/ast_hdmitx.c | 679 -------------------------- src/ast_hdmitx.h | 710 ---------------------------- src/ast_i2c.c | 147 ++++++ src/ast_main.c | 277 +++++------ src/ast_mm.c | 44 +- src/ast_mode.c | 1099 ++++++++++++++++++++++++------------------- src/ast_post.c | 44 +- src/ast_reg.h | 152 ++++++ src/ast_tables.h | 4 +- 18 files changed, 1418 insertions(+), 2707 deletions(-) create mode 100644 src/Kconfig delete mode 100644 src/ast_cursor.c delete mode 100644 src/ast_hdmitx.c delete mode 100644 src/ast_hdmitx.h create mode 100644 src/ast_i2c.c create mode 100644 src/ast_reg.h diff --git a/kmod-ast.spec b/kmod-ast.spec index acf7701..e239f6a 100644 --- a/kmod-ast.spec +++ b/kmod-ast.spec @@ -1,6 +1,6 @@ %global pkg ast %global kernel kernel version -%define pkg_version 1.14.4 +%define pkg_version 1.15.1_4 %define anolis_release 1 %global debug_package %{nil} diff --git a/src/Kconfig b/src/Kconfig new file mode 100644 index 0000000..d367a90 --- /dev/null +++ b/src/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only +config DRM_AST + tristate "AST server chips" + depends on DRM && PCI && MMU + select DRM_GEM_SHMEM_HELPER + select DRM_KMS_HELPER + help + Say yes for experimental AST GPU driver. Do not enable + this driver without having a working -modesetting, + and a version of AST that knows to fail if KMS + is bound to the driver. These GPUs are commonly found + in server chipsets. + diff --git a/src/Makefile b/src/Makefile index db8a609..246719e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,7 +28,7 @@ clean: else # called from kernel build system: just declare what our modules are obj-m += ast.o - ast-objs := ast_cursor.o ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o ast_hdmitx.o ast_dram_2500.o + ast-objs := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o ast_dram_2500.o endif diff --git a/src/ast_cursor.c b/src/ast_cursor.c deleted file mode 100644 index acf0d23..0000000 --- a/src/ast_cursor.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * Parts based on xf86-video-ast - * Copyright (c) 2005 ASPEED Technology Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - */ -/* - * Authors: Dave Airlie - */ - -#include -#include - -#include "ast_drv.h" - -static void ast_cursor_fini(struct ast_private *ast) -{ - size_t i; - struct drm_gem_vram_object *gbo; - - for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { - gbo = ast->cursor.gbo[i]; - drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]); - drm_gem_vram_unpin(gbo); - drm_gem_vram_put(gbo); - } -} - -static void ast_cursor_release(struct drm_device *dev, void *ptr) -{ - struct ast_private *ast = dev->dev_private; - - ast_cursor_fini(ast); -} - -/* - * Allocate cursor BOs and pins them at the end of VRAM. - */ -int ast_cursor_init(struct ast_private *ast) -{ - struct drm_device *dev = ast->dev; - size_t size, i; - struct drm_gem_vram_object *gbo; - void __iomem *vaddr; - int ret; - - size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); - - for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { - gbo = drm_gem_vram_create(dev, size, 0); - if (IS_ERR(gbo)) { - ret = PTR_ERR(gbo); - goto err_drm_gem_vram_put; - } - ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM | - DRM_GEM_VRAM_PL_FLAG_TOPDOWN); - if (ret) { - drm_gem_vram_put(gbo); - goto err_drm_gem_vram_put; - } - vaddr = drm_gem_vram_vmap(gbo); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - drm_gem_vram_unpin(gbo); - drm_gem_vram_put(gbo); - goto err_drm_gem_vram_put; - } - - ast->cursor.gbo[i] = gbo; - ast->cursor.vaddr[i] = vaddr; - } - - return drmm_add_action_or_reset(dev, ast_cursor_release, NULL); - -err_drm_gem_vram_put: - while (i) { - --i; - gbo = ast->cursor.gbo[i]; - drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]); - drm_gem_vram_unpin(gbo); - drm_gem_vram_put(gbo); - } - return ret; -} - -static void update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height) -{ - union { - u32 ul; - u8 b[4]; - } srcdata32[2], data32; - union { - u16 us; - u8 b[2]; - } data16; - u32 csum = 0; - s32 alpha_dst_delta, last_alpha_dst_delta; - u8 __iomem *dstxor; - const u8 *srcxor; - int i, j; - u32 per_pixel_copy, two_pixel_copy; - - alpha_dst_delta = AST_MAX_HWC_WIDTH << 1; - last_alpha_dst_delta = alpha_dst_delta - (width << 1); - - srcxor = src; - dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; - per_pixel_copy = width & 1; - two_pixel_copy = width >> 1; - - for (j = 0; j < height; j++) { - for (i = 0; i < two_pixel_copy; i++) { - srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; - srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; - data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); - data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); - data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); - data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); - - writel(data32.ul, dstxor); - csum += data32.ul; - - dstxor += 4; - srcxor += 8; - - } - - for (i = 0; i < per_pixel_copy; i++) { - srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; - data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); - data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); - writew(data16.us, dstxor); - csum += (u32)data16.us; - - dstxor += 2; - srcxor += 4; - } - dstxor += last_alpha_dst_delta; - } - - /* write checksum + signature */ - dst += AST_HWC_SIZE; - writel(csum, dst); - writel(width, dst + AST_HWC_SIGNATURE_SizeX); - writel(height, dst + AST_HWC_SIGNATURE_SizeY); - writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); - writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); -} - -int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) -{ - struct drm_device *dev = ast->dev; - struct drm_gem_vram_object *gbo; - int ret; - void *src; - void __iomem *dst; - - if (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) || - drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT)) - return -EINVAL; - - gbo = drm_gem_vram_of_gem(fb->obj[0]); - - ret = drm_gem_vram_pin(gbo, 0); - if (ret) - return ret; - src = drm_gem_vram_vmap(gbo); - if (IS_ERR(src)) { - ret = PTR_ERR(src); - goto err_drm_gem_vram_unpin; - } - - dst = ast->cursor.vaddr[ast->cursor.next_index]; - - /* do data transfer to cursor BO */ - update_cursor_image(dst, src, fb->width, fb->height); - - drm_gem_vram_vunmap(gbo, src); - drm_gem_vram_unpin(gbo); - - return 0; - -err_drm_gem_vram_unpin: - drm_gem_vram_unpin(gbo); - return ret; -} - -static void ast_cursor_set_base(struct ast_private *ast, u64 address) -{ - u8 addr0 = (address >> 3) & 0xff; - u8 addr1 = (address >> 11) & 0xff; - u8 addr2 = (address >> 19) & 0xff; - - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); -} - -void ast_cursor_page_flip(struct ast_private *ast) -{ - struct drm_device *dev = ast->dev; - struct drm_gem_vram_object *gbo; - s64 off; - - gbo = ast->cursor.gbo[ast->cursor.next_index]; - - off = drm_gem_vram_offset(gbo); - if (drm_WARN_ON_ONCE(dev, off < 0)) - return; /* Bug: we didn't pin the cursor HW BO to VRAM. */ - - ast_cursor_set_base(ast, off); - - ++ast->cursor.next_index; - ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo); -} - -static void ast_cursor_set_location(struct ast_private *ast, u16 x, u16 y, - u8 x_offset, u8 y_offset) -{ - u8 x0 = (x & 0x00ff); - u8 x1 = (x & 0x0f00) >> 8; - u8 y0 = (y & 0x00ff); - u8 y1 = (y & 0x0700) >> 8; - - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, x0); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, x1); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, y0); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); -} - -void ast_cursor_show(struct ast_private *ast, int x, int y, - unsigned int offset_x, unsigned int offset_y) -{ - u8 x_offset, y_offset; - u8 __iomem *dst, __iomem *sig; - u8 jreg; - - dst = ast->cursor.vaddr[ast->cursor.next_index]; - - sig = dst + AST_HWC_SIZE; - writel(x, sig + AST_HWC_SIGNATURE_X); - writel(y, sig + AST_HWC_SIGNATURE_Y); - - if (x < 0) { - x_offset = (-x) + offset_x; - x = 0; - } else { - x_offset = offset_x; - } - if (y < 0) { - y_offset = (-y) + offset_y; - y = 0; - } else { - y_offset = offset_y; - } - - ast_cursor_set_location(ast, x, y, x_offset, y_offset); - - /* dummy write to fire HWC */ - jreg = 0x02 | - 0x01; /* enable ARGB4444 cursor */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg); -} - -void ast_cursor_hide(struct ast_private *ast) -{ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00); -} diff --git a/src/ast_dp.c b/src/ast_dp.c index 0dfca0f..3aed12f 100644 --- a/src/ast_dp.c +++ b/src/ast_dp.c @@ -18,31 +18,31 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) * CRDF[b0]: DP HPD * CRE5[b0]: Host reading EDID process is done */ - while (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) && - ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) && - ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) && - ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK))) { - if (i++ > 10) + while (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, ASTDP_MCU_FW_EXECUTING) && + ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS) && + ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, ASTDP_HPD) && + ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK))) { + if (i++ > 4) goto err_astdp_edid_not_ready; mdelay(50); } - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8)~ASTDP_HOST_EDID_READ_DONE_MASK, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, (u8)~ASTDP_HOST_EDID_READ_DONE_MASK, 0x00); for (i = 0; i < 32; i++) { /* * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64 */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4, ASTDP_AND_CLEAR_MASK, (u8)i); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE4, ASTDP_AND_CLEAR_MASK, (u8)i); j = 0; /* * CRD7[b0]: valid flag for EDID * CRD6[b0]: mirror read pointer for EDID */ - while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7, + while ((ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD7, ASTDP_EDID_VALID_FLAG_MASK) != 0x01) || - (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6, + (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD6, ASTDP_EDID_READ_POINTER_MASK) != i)) { /* * Delay are getting longer with each retry. @@ -52,24 +52,24 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) */ mdelay(j+1); - if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, + if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, ASTDP_MCU_FW_EXECUTING) && - ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) { + ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, ASTDP_HPD))) { goto err_astdp_jump_out_loop_of_edid; } j++; - if (j > 200) + if (j > 100) goto err_astdp_jump_out_loop_of_edid; } - *(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, + *(ediddata) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD8, ASTDP_EDID_READ_DATA_MASK); - *(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9, + *(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD9, ASTDP_EDID_READ_DATA_MASK); - *(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA, + *(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDA, ASTDP_EDID_READ_DATA_MASK); - *(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB, + *(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDB, ASTDP_EDID_READ_DATA_MASK); if (i == 31) { @@ -89,25 +89,120 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) ediddata += 4; } - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK, + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK, ASTDP_HOST_EDID_READ_DONE); return 0; err_astdp_jump_out_loop_of_edid: - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK, ASTDP_HOST_EDID_READ_DONE); return (~(j+256) + 1); err_astdp_edid_not_ready: - if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING))) + if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, ASTDP_MCU_FW_EXECUTING))) return (~0xD1 + 1); - if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS))) + if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS))) return (~0xDC + 1); - if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) + if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, ASTDP_HPD))) return (~0xDF + 1); - if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK))) + if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK))) + return (~0xE5 + 1); + + return 0; +} + +int ast_vga_read_edid(struct drm_device *dev, u8 *ediddata) +{ + struct ast_private *ast = to_ast_private(dev); + u8 i = 0, j = 0; + + /* + * CRD1[b5]: DP MCU FW is executing + * CRE5[b0]: Host reading EDID process is done + */ + while (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, ASTDP_MCU_FW_EXECUTING) && + ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK))) { + if (i++ > 4) + goto err_vga_edid_not_ready; + mdelay(50); + } + + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, 0xfc, 0x02); + + for (i = 0; i < 32; i++) { + /* + * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64 + */ + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE4, ASTDP_AND_CLEAR_MASK, (u8)i); + j = 0; + + /* + * CRD7[b0]: valid flag for EDID + * CRD6[b0]: mirror read pointer for EDID + */ + while ((ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD7, + ASTDP_EDID_VALID_FLAG_MASK) != 0x01) || + (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD6, + ASTDP_EDID_READ_POINTER_MASK) != i)) { + /* + * Delay are getting longer with each retry. + * 1. The Delays are often 2 loops when users request "Display Settings" + * of right-click of mouse. + * 2. The Delays are often longer a lot when system resume from S3/S4. + */ + mdelay(j+1); + + if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, ASTDP_MCU_FW_EXECUTING)) { + drm_info(dev, "%s: mcu not exec\n", __func__); + goto err_vga_jump_out_loop_of_edid; + } + + j++; + if (j > 20) { + goto err_vga_jump_out_loop_of_edid; + } + } + + *(ediddata) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, + 0xD8, ASTDP_EDID_READ_DATA_MASK); + *(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD9, + ASTDP_EDID_READ_DATA_MASK); + *(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDA, + ASTDP_EDID_READ_DATA_MASK); + *(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDB, + ASTDP_EDID_READ_DATA_MASK); + + if (i == 31) { + /* + * For 128-bytes EDID_1.3, + * 1. Add the value of Bytes-126 to Bytes-127. + * The Bytes-127 is Checksum. Sum of all 128bytes should + * equal 0 (mod 256). + * 2. Modify Bytes-126 to be 0. + * The Bytes-126 indicates the Number of extensions to + * follow. 0 represents noextensions. + */ + *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2); + *(ediddata + 2) = 0; + } + + ediddata += 4; + } + + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, 0xfc, ASTDP_HOST_EDID_READ_DONE); + + return 0; + +err_vga_jump_out_loop_of_edid: + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, 0xfc, ASTDP_HOST_EDID_READ_DONE); + return (~(j+256) + 1); + +err_vga_edid_not_ready: + if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, ASTDP_MCU_FW_EXECUTING))) + return (~0xD1 + 1); + if (!(ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK))) return (~0xE5 + 1); return 0; @@ -123,7 +218,7 @@ void ast_dp_launch(struct drm_device *dev) struct ast_private *ast = to_ast_private(dev); // Wait one second then timeout. - while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) != + while (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, ASTDP_MCU_FW_EXECUTING) != ASTDP_MCU_FW_EXECUTING) { i++; // wait 100 ms @@ -136,7 +231,7 @@ void ast_dp_launch(struct drm_device *dev) } } - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE5, (u8)~ASTDP_HOST_EDID_READ_DONE_MASK, ASTDP_HOST_EDID_READ_DONE); } @@ -147,14 +242,14 @@ void ast_dp_power_on_off(struct drm_device *dev, bool on) { struct ast_private *ast = to_ast_private(dev); // Read and Turn off DP PHY sleep - u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE); + u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, AST_DP_VIDEO_ENABLE); // Turn on DP PHY sleep if (!on) bE3 |= AST_DP_PHY_SLEEP; // DP Power on/off - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3); } @@ -166,13 +261,13 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) u32 i = 0; // Video On/Off - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on); // If DP plug in and link successful then check video on / off status - if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) && - ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) { + if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, ASTDP_LINK_SUCCESS) && + ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, ASTDP_HPD)) { video_on_off <<= 4; - while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, + while (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) { // wait 1 ms mdelay(1); @@ -257,8 +352,8 @@ void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mo * CRE1[7:0]: MISC1 (default: 0x00) * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50) */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, ASTDP_AND_CLEAR_MASK, + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE0, ASTDP_AND_CLEAR_MASK, ASTDP_MISC0_24bpp); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx); } diff --git a/src/ast_dp501.c b/src/ast_dp501.c index 9fda67b..d9504b7 100644 --- a/src/ast_dp501.c +++ b/src/ast_dp501.c @@ -5,31 +5,43 @@ #include #include "ast_drv.h" -#include "ast_hdmitx.h" MODULE_FIRMWARE("ast_dp501_fw.bin"); +static void ast_release_firmware(void *data) +{ + struct ast_private *ast = data; + + release_firmware(ast->dp501_fw); + ast->dp501_fw = NULL; +} + static int ast_load_dp501_microcode(struct drm_device *dev) { struct ast_private *ast = to_ast_private(dev); + int ret; + + ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); + if (ret) + return ret; - return request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); + return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast); } static void send_ack(struct ast_private *ast) { u8 sendack; - sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff); + sendack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0xff); sendack |= 0x80; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0x00, sendack); } static void send_nack(struct ast_private *ast) { u8 sendack; - sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff); + sendack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0xff); sendack &= ~0x80; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, 0x00, sendack); } static bool wait_ack(struct ast_private *ast) @@ -37,7 +49,7 @@ static bool wait_ack(struct ast_private *ast) u8 waitack; u32 retry = 0; do { - waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff); + waitack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff); waitack &= 0x80; udelay(100); } while ((!waitack) && (retry++ < 1000)); @@ -53,7 +65,7 @@ static bool wait_nack(struct ast_private *ast) u8 waitack; u32 retry = 0; do { - waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff); + waitack = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff); waitack &= 0x80; udelay(100); } while ((waitack) && (retry++ < 1000)); @@ -66,12 +78,12 @@ static bool wait_nack(struct ast_private *ast) static void set_cmd_trigger(struct ast_private *ast) { - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, ~0x40, 0x40); } static void clear_cmd_trigger(struct ast_private *ast) { - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9b, ~0x40, 0x00); } #if 0 @@ -80,7 +92,7 @@ static bool wait_fw_ready(struct ast_private *ast) u8 waitready; u32 retry = 0; do { - waitready = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff); + waitready = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd2, 0xff); waitready &= 0x40; udelay(100); } while ((!waitready) && (retry++ < 1000)); @@ -98,7 +110,7 @@ static bool ast_write_cmd(struct drm_device *dev, u8 data) int retry = 0; if (wait_nack(ast)) { send_nack(ast); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, data); send_ack(ast); set_cmd_trigger(ast); do { @@ -120,7 +132,7 @@ static bool ast_write_data(struct drm_device *dev, u8 data) if (wait_nack(ast)) { send_nack(ast); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, data); send_ack(ast); if (wait_ack(ast)) { send_nack(ast); @@ -141,7 +153,7 @@ static bool ast_read_data(struct drm_device *dev, u8 *data) if (wait_ack(ast) == false) return false; - tmp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd3, 0xff); + tmp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd3, 0xff); *data = tmp; if (wait_nack(ast) == false) { send_nack(ast); @@ -154,7 +166,7 @@ static bool ast_read_data(struct drm_device *dev, u8 *data) static void clear_cmd(struct ast_private *ast) { send_nack(ast); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x9a, 0x00, 0x00); } #endif @@ -253,9 +265,9 @@ static bool ast_launch_m68k(struct drm_device *dev) data |= 0x800; ast_moutdwm(ast, 0x1e6e2040, data); - jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */ + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */ jreg |= 0x02; - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x99, jreg); } return true; } @@ -264,53 +276,56 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) { struct ast_private *ast = to_ast_private(dev); u32 i, boot_address, offset, data; + u32 *pEDIDidx; if (ast->config_mode == ast_use_p2a) { boot_address = get_fw_base(ast); /* validate FW version */ - offset = 0xf000; + offset = AST_DP501_GBL_VERSION; data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) return false; /* validate PnP Monitor */ - offset = 0xf010; + offset = AST_DP501_PNPMONITOR; data = ast_mindwm(ast, boot_address + offset); - if (!(data & 0x01)) + if (!(data & AST_DP501_PNP_CONNECTED)) return false; /* Read EDID */ - offset = 0xf020; - for (i = 0; i < 128; i+=4) { + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { data = ast_mindwm(ast, boot_address + offset + i); - *(u32 *)(ediddata + i) = data; + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; } - } - else { - if (!ast->reservedbuffer) return false; + } else { + if (!ast->dp501_fw_buf) + return false; - /* dummy read */ - offset = 0x0000; - data = *(u32 *) (ast->reservedbuffer + offset); + /* dummy read */ + offset = 0x0000; + data = readl(ast->dp501_fw_buf + offset); /* validate FW version */ - offset = 0xf000; - data = *(u32 *) (ast->reservedbuffer + offset); - if ((data & 0xf0) != 0x10) + offset = AST_DP501_GBL_VERSION; + data = readl(ast->dp501_fw_buf + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) return false; /* validate PnP Monitor */ - offset = 0xf010; - data = *(u32 *) (ast->reservedbuffer + offset); - if (!(data & 0x01)) + offset = AST_DP501_PNPMONITOR; + data = readl(ast->dp501_fw_buf + offset); + if (!(data & AST_DP501_PNP_CONNECTED)) return false; /* Read EDID */ - offset = 0xf020; - for (i = 0; i < 128; i+=4) { - data = *(u32 *) (ast->reservedbuffer + offset + i); - *(u32 *)(ediddata + i) = data; + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { + data = readl(ast->dp501_fw_buf + offset + i); + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; } } @@ -326,7 +341,7 @@ static bool ast_init_dvo(struct drm_device *dev) ast_write32(ast, 0xf000, 0x1); ast_write32(ast, 0x12000, 0x1688a8a8); - jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); if (!(jreg & 0x80)) { /* Init SCU DVO Settings */ data = ast_read32(ast, 0x12008); @@ -385,7 +400,7 @@ static bool ast_init_dvo(struct drm_device *dev) ast_write32(ast, 0x1202c, data); /* Init VGA DVO Settings */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); return true; } @@ -414,7 +429,7 @@ static void ast_init_analog(struct drm_device *dev) ast_write32(ast, 0, data); /* Disable DVO */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x00); } void ast_init_3rdtx(struct drm_device *dev) @@ -423,14 +438,8 @@ void ast_init_3rdtx(struct drm_device *dev) u8 jreg; if (ast->chip == AST2300 || ast->chip == AST2400 || ast->chip == AST2500) { - jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff); switch (jreg & 0x0e) { - case 0x02: /* /ITE66121 */ - if (ast_hdmi_check(dev)){ - ast_init_dvo(dev); - ast_hdmi_init(dev); - } - break; case 0x04: ast_init_dvo(dev); break; @@ -449,11 +458,3 @@ void ast_init_3rdtx(struct drm_device *dev) } } } - -void ast_release_firmware(struct drm_device *dev) -{ - struct ast_private *ast = to_ast_private(dev); - - release_firmware(ast->dp501_fw); - ast->dp501_fw = NULL; -} diff --git a/src/ast_dram_2500.c b/src/ast_dram_2500.c index 2b783a5..634ddd9 100644 --- a/src/ast_dram_2500.c +++ b/src/ast_dram_2500.c @@ -464,7 +464,7 @@ void ast_post_chip_2500(struct drm_device *dev) u32 temp; u8 reg; - reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); + reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); if ((reg & AST_VRAM_INIT_STATUS_MASK) == 0) {/* vga only */ /* Clear bus lock condition */ ast_patch_ahb_2500(ast); @@ -512,6 +512,6 @@ void ast_post_chip_2500(struct drm_device *dev) /* wait ready */ do { - reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); + reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); } while ((reg & 0x40) == 0); } diff --git a/src/ast_drv.c b/src/ast_drv.c index 019f738..b3b28bc 100644 --- a/src/ast_drv.c +++ b/src/ast_drv.c @@ -26,14 +26,15 @@ * Authors: Dave Airlie */ -#include #include #include -#include +#include +#include #include -#include -#include +#include +#include +#include #include #include "ast_drv.h" @@ -47,9 +48,33 @@ static int ast_modeset = -1; MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); module_param_named(modeset, ast_modeset, int, 0400); -#define PCI_VENDOR_ASPEED 0x1a03 +/* + * DRM driver + */ + +DEFINE_DRM_GEM_FOPS(ast_fops); + +static const struct drm_driver ast_driver = { + .driver_features = DRIVER_ATOMIC | + DRIVER_GEM | + DRIVER_MODESET, + + .fops = &ast_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, + + DRM_GEM_SHMEM_DRIVER_OPS +}; + +/* + * PCI driver + */ -static struct drm_driver driver; +#define PCI_VENDOR_ASPEED 0x1a03 #define AST_VGA_DEVICE(id, info) { \ .class = PCI_BASE_CLASS_DISPLAY << 16, \ @@ -60,63 +85,53 @@ static struct drm_driver driver; .subdevice = PCI_ANY_ID, \ .driver_data = (unsigned long) info } -static const struct pci_device_id pciidlist[] = { +static const struct pci_device_id ast_pciidlist[] = { AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL), AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL), - AST_VGA_DEVICE(PCI_CHIP_AIP200, NULL), {0, 0, 0}, }; -MODULE_DEVICE_TABLE(pci, pciidlist); +MODULE_DEVICE_TABLE(pci, ast_pciidlist); static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { + struct ast_private *ast; struct drm_device *dev; int ret; - ret = pcim_enable_device(pdev); + ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &ast_driver); if (ret) return ret; - ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "astdrmfb"); + ret = pcim_enable_device(pdev); if (ret) return ret; - dev = drm_dev_alloc(&driver, &pdev->dev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - dev->pdev = pdev; - pci_set_drvdata(pdev, dev); - - ret = ast_driver_load(dev, ent->driver_data); - if (ret) - goto err_drm_dev_put; + ast = ast_device_create(&ast_driver, pdev, ent->driver_data); + if (IS_ERR(ast)) + return PTR_ERR(ast); + dev = &ast->base; ret = drm_dev_register(dev, ent->driver_data); if (ret) - goto err_ast_driver_unload; + return ret; drm_fbdev_generic_setup(dev, 32); return 0; - -err_ast_driver_unload: - ast_driver_unload(dev); -err_drm_dev_put: - drm_dev_put(dev); - return ret; - } -static void -ast_pci_remove(struct pci_dev *pdev) +static void ast_pci_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); drm_dev_unregister(dev); - ast_driver_unload(dev); - drm_dev_put(dev); + drm_atomic_helper_shutdown(dev); +} + +static void ast_pci_shutdown(struct pci_dev *pdev) +{ + drm_atomic_helper_shutdown(pci_get_drvdata(pdev)); } static int ast_drm_freeze(struct drm_device *dev) @@ -126,7 +141,7 @@ static int ast_drm_freeze(struct drm_device *dev) error = drm_mode_config_helper_suspend(dev); if (error) return error; - pci_save_state(dev->pdev); + pci_save_state(to_pci_dev(dev->dev)); return 0; } @@ -200,46 +215,14 @@ static const struct dev_pm_ops ast_pm_ops = { static struct pci_driver ast_pci_driver = { .name = DRIVER_NAME, - .id_table = pciidlist, + .id_table = ast_pciidlist, .probe = ast_pci_probe, .remove = ast_pci_remove, + .shutdown = ast_pci_shutdown, .driver.pm = &ast_pm_ops, }; -DEFINE_DRM_GEM_FOPS(ast_fops); - -static struct drm_driver driver = { - .driver_features = DRIVER_ATOMIC | - DRIVER_GEM | - DRIVER_MODESET, - - .fops = &ast_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, - - DRM_GEM_VRAM_DRIVER -}; - -static int __init ast_init(void) -{ - if (vgacon_text_force() && ast_modeset == -1) - return -EINVAL; - - if (ast_modeset == 0) - return -EINVAL; - return pci_register_driver(&ast_pci_driver); -} -static void __exit ast_exit(void) -{ - pci_unregister_driver(&ast_pci_driver); -} - -module_init(ast_init); -module_exit(ast_exit); +drm_module_pci_driver_if_modeset(ast_pci_driver, ast_modeset); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/src/ast_drv.h b/src/ast_drv.h index c587ee7..57f2878 100644 --- a/src/ast_drv.h +++ b/src/ast_drv.h @@ -28,10 +28,10 @@ #ifndef __AST_DRV_H__ #define __AST_DRV_H__ -#include -#include #include #include +#include +#include #include #include @@ -40,34 +40,53 @@ #include #include +#include "ast_reg.h" + #define DRIVER_AUTHOR "Dave Airlie" #define DRIVER_NAME "ast" #define DRIVER_DESC "AST" -#define DRIVER_DATE "20240801" +#define DRIVER_DATE "20241212" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 14 -#define DRIVER_PATCHLEVEL 4 +#define DRIVER_MINOR 15 +#define DRIVER_PATCHLEVEL 1 #define PCI_CHIP_AST2000 0x2000 #define PCI_CHIP_AST2100 0x2010 -#define PCI_CHIP_AIP200 0xA200 +#define __AST_CHIP(__gen, __index) ((__gen) << 16 | (__index)) enum ast_chip { - AST2000, - AST2100, - AST1100, - AST2200, - AST2150, - AST2300, - AST2400, - AST2500, - AST2600, - AIP200, + /* 1st gen */ + AST1000 = __AST_CHIP(1, 0), // unused + AST2000 = __AST_CHIP(1, 1), + /* 2nd gen */ + AST1100 = __AST_CHIP(2, 0), + AST2100 = __AST_CHIP(2, 1), + AST2050 = __AST_CHIP(2, 2), // unused + /* 3rd gen */ + AST2200 = __AST_CHIP(3, 0), + AST2150 = __AST_CHIP(3, 1), + /* 4th gen */ + AST2300 = __AST_CHIP(4, 0), + AST1300 = __AST_CHIP(4, 1), + AST1050 = __AST_CHIP(4, 2), // unused + /* 5th gen */ + AST2400 = __AST_CHIP(5, 0), + AST1400 = __AST_CHIP(5, 1), + AST1250 = __AST_CHIP(5, 2), // no VGA + /* 6th gen */ + AST2500 = __AST_CHIP(6, 0), + AST2510 = __AST_CHIP(6, 1), + AST2520 = __AST_CHIP(6, 2), // no VGA + /* 7th gen */ + AST2600 = __AST_CHIP(7, 0), + AST2620 = __AST_CHIP(7, 1), // no VGA }; +#define __AST_CHIP_GEN(__chip) (((unsigned long)(__chip)) >> 16) + enum ast_tx_chip { AST_TX_NONE, AST_TX_SIL164, @@ -84,7 +103,9 @@ enum ast_tx_chip { #define AST_DRAM_4Gx16 7 #define AST_DRAM_8Gx16 8 -#define MAX_COLOR_LUT_ENTRIES 256 +/* + * Hardware cursor + */ #define AST_MAX_HWC_WIDTH 64 #define AST_MAX_HWC_HEIGHT 64 @@ -92,8 +113,6 @@ enum ast_tx_chip { #define AST_HWC_SIZE (AST_MAX_HWC_WIDTH * AST_MAX_HWC_HEIGHT * 2) #define AST_HWC_SIGNATURE_SIZE 32 -#define AST_DEFAULT_HWC_NUM 2 - /* define for signature structure */ #define AST_HWC_SIGNATURE_CHECKSUM 0x00 #define AST_HWC_SIGNATURE_SizeX 0x04 @@ -103,6 +122,22 @@ enum ast_tx_chip { #define AST_HWC_SIGNATURE_HOTSPOTX 0x14 #define AST_HWC_SIGNATURE_HOTSPOTY 0x18 +/* + * Planes + */ + +struct ast_plane { + struct drm_plane base; + + void __iomem *vaddr; + u64 offset; + unsigned long size; +}; + +static inline struct ast_plane *to_ast_plane(struct drm_plane *plane) +{ + return container_of(plane, struct ast_plane, base); +} /* * Connector with i2c channel @@ -130,29 +165,29 @@ to_ast_connector(struct drm_connector *connector) */ struct ast_private { - struct drm_device *dev; + struct drm_device base; - struct mutex ioregs_lock; /* Protects access to I/O registers in ioregs */ void __iomem *regs; void __iomem *ioregs; - void __iomem *reservedbuffer; + void __iomem *dp501_fw_buf; enum ast_chip chip; uint32_t dram_bus_width; uint32_t dram_type; uint32_t mclk; - int fb_mtrr; + struct mutex modeset_lock; /* Protects access to modeset I/O registers in ioregs */ - struct { - struct drm_gem_vram_object *gbo[AST_DEFAULT_HWC_NUM]; - void __iomem *vaddr[AST_DEFAULT_HWC_NUM]; - unsigned int next_index; - } cursor; + void __iomem *vram; + unsigned long vram_base; + unsigned long vram_size; + unsigned long vram_fb_available; + struct ast_plane primary_plane; + struct ast_plane cursor_plane; + struct drm_crtc crtc; struct drm_encoder encoder; - struct drm_plane primary_plane; - struct drm_plane cursor_plane; + struct ast_connector connector; bool RefCLK25MHz; enum { @@ -168,30 +203,30 @@ struct ast_private { static inline struct ast_private *to_ast_private(struct drm_device *dev) { - return dev->dev_private; + return container_of(dev, struct ast_private, base); } -int ast_driver_load(struct drm_device *dev, unsigned long flags); -void ast_driver_unload(struct drm_device *dev); +struct ast_private *ast_device_create(const struct drm_driver *drv, + struct pci_dev *pdev, + unsigned long flags); -#define AST_IO_AR_PORT_WRITE (0x40) -#define AST_IO_MISC_PORT_WRITE (0x42) -#define AST_IO_VGA_ENABLE_PORT (0x43) -#define AST_IO_SEQ_PORT (0x44) -#define AST_IO_DAC_INDEX_READ (0x47) -#define AST_IO_DAC_INDEX_WRITE (0x48) -#define AST_IO_DAC_DATA (0x49) -#define AST_IO_GR_PORT (0x4E) -#define AST_IO_CRTC_PORT (0x54) -#define AST_IO_INPUT_STATUS1_READ (0x5A) -#define AST_IO_MISC_PORT_READ (0x4C) - -#define AST_IO_MM_OFFSET (0x380) - -#define AST_IO_VGAIR1_VREFRESH BIT(3) +static inline unsigned long __ast_gen(struct ast_private *ast) +{ + return __AST_CHIP_GEN(ast->chip); +} +#define AST_GEN(__ast) __ast_gen(__ast) -#define AST_IO_VGACRCB_HWC_ENABLED BIT(1) -#define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ +static inline bool __ast_gen_is_eq(struct ast_private *ast, unsigned long gen) +{ + return __ast_gen(ast) == gen; +} +#define IS_AST_GEN1(__ast) __ast_gen_is_eq(__ast, 1) +#define IS_AST_GEN2(__ast) __ast_gen_is_eq(__ast, 2) +#define IS_AST_GEN3(__ast) __ast_gen_is_eq(__ast, 3) +#define IS_AST_GEN4(__ast) __ast_gen_is_eq(__ast, 4) +#define IS_AST_GEN5(__ast) __ast_gen_is_eq(__ast, 5) +#define IS_AST_GEN6(__ast) __ast_gen_is_eq(__ast, 6) +#define IS_AST_GEN7(__ast) __ast_gen_is_eq(__ast, 7) #define __ast_read(x) \ static inline u##x ast_read##x(struct ast_private *ast, u32 reg) { \ @@ -250,11 +285,9 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, static inline void ast_open_key(struct ast_private *ast) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x80, 0xA8); } -bool ast_wait_dram_init(struct ast_private *ast); - #define AST_VIDMEM_SIZE_8M 0x00800000 #define AST_VIDMEM_SIZE_16M 0x01000000 #define AST_VIDMEM_SIZE_32M 0x02000000 @@ -311,9 +344,6 @@ struct ast_crtc_state { int ast_mode_config_init(struct ast_private *ast); -#define AST_VPLL_REF_CLOCK_25M BIT(2) -#define AST_VPLL_REF_CLOCK_24M 0 - #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) @@ -328,114 +358,9 @@ int ast_mode_config_init(struct ast_private *ast); #define AST_DP501_LINKRATE 0xf014 #define AST_DP501_EDID_DATA 0xf020 -/* - * Display Transmitter Type: - */ -#define TX_TYPE_MASK GENMASK(3, 1) -#define NO_TX (0 << 1) -#define ITE66121_VBIOS_TX (1 << 1) -#define SI164_VBIOS_TX (2 << 1) -#define CH7003_VBIOS_TX (3 << 1) -#define DP501_VBIOS_TX (4 << 1) -#define ANX9807_VBIOS_TX (5 << 1) -#define TX_FW_EMBEDDED_FW_TX (6 << 1) -#define ASTDP_DPMCU_TX (7 << 1) - -#define AST_VRAM_INIT_STATUS_MASK GENMASK(7, 6) -//#define AST_VRAM_INIT_BY_BMC BIT(7) -//#define AST_VRAM_INIT_READY BIT(6) - -/* Define for Soc scratched reg used on ASTDP */ -#define AST_DP_PHY_SLEEP BIT(4) -#define AST_DP_VIDEO_ENABLE BIT(0) - #define AST_DP_POWER_ON true #define AST_DP_POWER_OFF false -/* - * CRD1[b5]: DP MCU FW is executing - * CRDC[b0]: DP link success - * CRDF[b0]: DP HPD - * CRE5[b0]: Host reading EDID process is done - */ -#define ASTDP_MCU_FW_EXECUTING BIT(5) -#define ASTDP_LINK_SUCCESS BIT(0) -#define ASTDP_HPD BIT(0) -#define ASTDP_HOST_EDID_READ_DONE BIT(0) -#define ASTDP_HOST_EDID_READ_DONE_MASK GENMASK(0, 0) - -/* - * CRB8[b1]: Enable VSYNC off - * CRB8[b0]: Enable HSYNC off - */ -#define AST_DPMS_VSYNC_OFF BIT(1) -#define AST_DPMS_HSYNC_OFF BIT(0) - -/* - * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE - * Precondition: A. ~AST_DP_PHY_SLEEP && - * B. DP_HPD && - * C. DP_LINK_SUCCESS - */ -#define ASTDP_MIRROR_VIDEO_ENABLE BIT(4) - -#define ASTDP_EDID_READ_POINTER_MASK GENMASK(7, 0) -#define ASTDP_EDID_VALID_FLAG_MASK GENMASK(0, 0) -#define ASTDP_EDID_READ_DATA_MASK GENMASK(7, 0) - -/* - * ASTDP setmode registers: - * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp) - * CRE1[7:0]: MISC1 (default: 0x00) - * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50) - */ -#define ASTDP_MISC0_24bpp BIT(5) -#define ASTDP_MISC1 0 -#define ASTDP_AND_CLEAR_MASK 0 - -/* - * ASTDP resoultion table: - * EX: ASTDP_A_B_C: - * A: Resolution - * B: Refresh Rate - * C: Misc information, such as CVT, Reduce Blanked - */ -#define ASTDP_640x480_60 0x00 -#define ASTDP_640x480_72 0x01 -#define ASTDP_640x480_75 0x02 -#define ASTDP_640x480_85 0x03 -#define ASTDP_800x600_56 0x04 -#define ASTDP_800x600_60 0x05 -#define ASTDP_800x600_72 0x06 -#define ASTDP_800x600_75 0x07 -#define ASTDP_800x600_85 0x08 -#define ASTDP_1024x768_60 0x09 -#define ASTDP_1024x768_70 0x0A -#define ASTDP_1024x768_75 0x0B -#define ASTDP_1024x768_85 0x0C -#define ASTDP_1280x1024_60 0x0D -#define ASTDP_1280x1024_75 0x0E -#define ASTDP_1280x1024_85 0x0F -#define ASTDP_1600x1200_60 0x10 -#define ASTDP_320x240_60 0x11 -#define ASTDP_400x300_60 0x12 -#define ASTDP_512x384_60 0x13 -#define ASTDP_1920x1200_60 0x14 -#define ASTDP_1920x1080_60 0x15 -#define ASTDP_1280x800_60 0x16 -#define ASTDP_1280x800_60_RB 0x17 -#define ASTDP_1440x900_60 0x18 -#define ASTDP_1440x900_60_RB 0x19 -#define ASTDP_1680x1050_60 0x1A -#define ASTDP_1680x1050_60_RB 0x1B -#define ASTDP_1600x900_60 0x1C -#define ASTDP_1600x900_60_RB 0x1D -#define ASTDP_1366x768_60 0x1E -#define ASTDP_1152x864_75 0x1F -#define ASTDP_1600x900_60_DMT 0x51 -#define ASTDP_1280x720_60 0x52 -#define ASTDP_1280x960_60 0x53 - int ast_mm_init(struct ast_private *ast); /* ast post */ @@ -451,20 +376,15 @@ void ast_set_dp501_video_output(struct drm_device *dev, u8 mode); bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size); bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata); void ast_init_3rdtx(struct drm_device *dev); -void ast_release_firmware(struct drm_device *dev); -/* aspeed DP */ -/* ast_cursor.c */ -int ast_cursor_init(struct ast_private *ast); -int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb); -void ast_cursor_page_flip(struct ast_private *ast); -void ast_cursor_show(struct ast_private *ast, int x, int y, - unsigned int offset_x, unsigned int offset_y); -void ast_cursor_hide(struct ast_private *ast); +/* ast_i2c.c */ +struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); +/* aspeed DP */ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void ast_dp_launch(struct drm_device *dev); void ast_dp_power_on_off(struct drm_device *dev, bool no); void ast_dp_set_on_off(struct drm_device *dev, bool no); void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode); +int ast_vga_read_edid(struct drm_device *dev, u8 *ediddata); #endif diff --git a/src/ast_hdmitx.c b/src/ast_hdmitx.c deleted file mode 100644 index 6a52530..0000000 --- a/src/ast_hdmitx.c +++ /dev/null @@ -1,679 +0,0 @@ - -#include - -#include "ast_drv.h" -#include "ast_hdmitx.h" - -#define I2C_BASE 0x1e780000 - -static void SetI2CReg(struct drm_device *dev, u8 jChannel, u8 DeviceAddr, u8 jIndex, u8 jData ) -{ - struct ast_private *ast = dev->dev_private; - u32 ulData, ulI2CBase, ulI2CAddr; - u8 *ulI2CPortBase; - u8 *pjMMIOBase; - u32 retry; - - { - pjMMIOBase = ast->ioregs; - ulI2CBase = I2C_BASE; - ulI2CPortBase = pjMMIOBase + 0x1a000 + 0x40 * jChannel; - ulI2CAddr = DeviceAddr; - } - - *(u32 *) (pjMMIOBase + 0xF004) = ulI2CBase; - *(u32 *) (pjMMIOBase + 0xF000) = 0x1; - - *(u32 *) (ulI2CPortBase + 0x00) = 0x0; - *(u32 *) (ulI2CPortBase + 0x04) = 0x77743356; - *(u32 *) (ulI2CPortBase + 0x08) = 0x0; - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x00) = 0x1; - *(u32 *) (ulI2CPortBase + 0x0C) = 0xAF; - *(u32 *) (ulI2CPortBase + 0x20) = ulI2CAddr; - *(u32 *) (ulI2CPortBase + 0x14) = 0x03; - retry = 0; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - udelay(10); - if (retry++ > 1000) - goto Exit_SetI2CReg; - } while (!(ulData & 0x01)); - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x20) = (u32) jIndex; - *(u32 *) (ulI2CPortBase + 0x14) = 0x02; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - } while (!(ulData & 0x01)); - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x20) = (u32) jData; - *(u32 *) (ulI2CPortBase + 0x14) = 0x02; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - } while (!(ulData & 0x01)); - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x0C) |= 0x10; - *(u32 *) (ulI2CPortBase + 0x14) = 0x20; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - } while (!(ulData & 0x10)); - *(u32 *) (ulI2CPortBase + 0x0C) &= 0xffffffef; - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - udelay(10); - -Exit_SetI2CReg: - ; -} - -static u8 GetI2CReg(struct drm_device *dev, u8 jChannel, u8 DeviceAddr, u8 jIndex) -{ - struct ast_private *ast = dev->dev_private; - u8 jData; - u32 ulData, ulI2CBase, ulI2CAddr; - u8 *ulI2CPortBase; - u8 *pjMMIOBase; - u32 retry; - - { - pjMMIOBase = ast->ioregs; - ulI2CBase = I2C_BASE; - ulI2CPortBase = pjMMIOBase + 0x1a000 + 0x40 * jChannel; - ulI2CAddr = DeviceAddr; - } - - *(u32 *) (pjMMIOBase + 0xF004) = ulI2CBase; - *(u32 *) (pjMMIOBase + 0xF000) = 0x1; - - *(u32 *) (ulI2CPortBase + 0x00) = 0x0; - *(u32 *) (ulI2CPortBase + 0x04) = 0x77743356; - *(u32 *) (ulI2CPortBase + 0x08) = 0x0; - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x00) = 0x1; - *(u32 *) (ulI2CPortBase + 0x0C) = 0xAF; - *(u32 *) (ulI2CPortBase + 0x20) = ulI2CAddr; - *(u32 *) (ulI2CPortBase + 0x14) = 0x03; - retry = 0; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - udelay(10); - if (retry++ > 1000) - return 0; - } while (!(ulData & 0x01)); - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x20) = (u32) jIndex; - *(u32 *) (ulI2CPortBase + 0x14) = 0x02; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - } while (!(ulData & 0x01)); - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x20) = ulI2CAddr + 1; - *(u32 *) (ulI2CPortBase + 0x14) = 0x1B; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - } while (!(ulData & 0x04)); - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - *(u32 *) (ulI2CPortBase + 0x0C) |= 0x10; - *(u32 *) (ulI2CPortBase + 0x14) = 0x20; - do { - ulData = *(u32 *) (ulI2CPortBase + 0x10); - } while (!(ulData & 0x10)); - *(u32 *) (ulI2CPortBase + 0x0C) &= 0xffffffef; - *(u32 *) (ulI2CPortBase + 0x10) = 0xffffffff; - jData = (u8) ((*(u32 *) (ulI2CPortBase + 0x20) & 0xFF00) >> 8); - - return (jData); -} -static bool I2C_Read_ByteN(struct drm_device *dev, u8 Addr, u8 RegAddr, u8 *pData, int N) -{ - u8 i, *pI2CData, jData; - - pI2CData = pData; - for (i = 0; i < N; i++) - { - jData = GetI2CReg(dev, (u8) HDMI_I2C_CHANNEL, Addr, (RegAddr + i)); - *(u8 *) (pI2CData++) = jData; - } - - return TRUE ; -} - -static bool I2C_Write_ByteN(struct drm_device *dev, u8 Addr,u8 RegAddr,u8 *pData,int N) -{ - u8 i; - - for (i = 0; i < N; i++) - { - SetI2CReg(dev, (u8) HDMI_I2C_CHANNEL, Addr, (RegAddr + i), *(u8 *)(pData + i)); - } - - return TRUE ; -} - -static u8 I2C_Read_Byte(struct drm_device *dev, u8 Addr,u8 RegAddr) -{ - u8 data ; - - I2C_Read_ByteN(dev, Addr,RegAddr,&data, 1) ; - - return data ; -} - -static bool I2C_Write_Byte(struct drm_device *dev, u8 Addr,u8 RegAddr,u8 Data) -{ - return I2C_Write_ByteN(dev, Addr,RegAddr,&Data, 1) ; -} - -static u8 HDMITX_ReadI2C_Byte(struct drm_device *dev, u8 RegAddr) -{ - return I2C_Read_Byte(dev, HDMI_TX_I2C_SLAVE_ADDR,RegAddr) ; -} - -static bool HDMITX_WriteI2C_Byte(struct drm_device *dev, u8 RegAddr,u8 Data) -{ - return I2C_Write_Byte(dev, HDMI_TX_I2C_SLAVE_ADDR,RegAddr,Data) ; -} - -static bool HDMITX_ReadI2C_ByteN(struct drm_device *dev, u8 RegAddr,u8 *pData,int N) -{ - return I2C_Read_ByteN(dev, HDMI_TX_I2C_SLAVE_ADDR,RegAddr,pData,N) ; -} - -static bool HDMITX_SetI2C_Byte(struct drm_device *dev, u8 Reg,u8 Mask,u8 Value) -{ - u8 Temp; - if( Mask != 0xFF ) - { - Temp=HDMITX_ReadI2C_Byte(dev, Reg); - Temp&=(~Mask); - Temp|=Value&Mask; - } - else - { - Temp=Value; - } - return HDMITX_WriteI2C_Byte(dev, Reg,Temp); -} - -static void hdmitx_LoadRegSetting(struct drm_device *dev, RegSetEntry table[]) -{ - u32 i ; - - for( i = 0 ; ; i++ ) - { - if( table[i].offset == 0 && table[i].invAndMask == 0 && table[i].OrMask == 0 ) - { - return ; - } - else if( table[i].invAndMask == 0 && table[i].OrMask == 0 ) - { - udelay(table[i].offset); - } - else if( table[i].invAndMask == 0xFF ) - { - HDMITX_WriteI2C_Byte(dev, table[i].offset,table[i].OrMask); - } - else - { - HDMITX_SetI2C_Byte(dev, table[i].offset,table[i].invAndMask,table[i].OrMask); - } - } -} - -/* - * Export Procedures - */ -bool ast_hdmi_check(struct drm_device *dev) -{ - // Check ite 66121 chip - u16 VendorID, DeviceID; - u8 pData[4]; - - Switch_HDMITX_Bank(dev, 0) ; - HDMITX_ReadI2C_ByteN(dev, 0x00, pData, 4); - VendorID = *(u16 *)(pData) & 0xFFFF; - DeviceID = *(u16 *)(pData + 2) & 0x0FFF; - if ((VendorID != 0x4954) || ((DeviceID != 0x0612) && (DeviceID != 0x0622))) - { - return FALSE; - } - - return (TRUE); - -} - -#ifndef INV_INPUT_PCLK -#define PCLKINV 0 -#else -#define PCLKINV B_TX_VDO_LATCH_EDGE -#endif - -#ifndef INV_INPUT_ACLK - #define InvAudCLK 0 -#else - #define InvAudCLK B_TX_AUDFMT_FALL_EDGE_SAMPLE_WS -#endif - -#define INIT_CLK_HIGH -/* #define INIT_CLK_LOW */ - -RegSetEntry HDMITX_Init_Table[] = { - - {0x0F, 0x40, 0x00}, - - {0x62, 0x08, 0x00}, - {0x64, 0x04, 0x00}, - {0x01,0x00,0x00},/*idle(100)*/ - - {0x04, 0x20, 0x20}, - {0x04, 0x1D, 0x1D}, - {0x01,0x00,0x00},/*idle(100)*/ - {0x0F, 0x01, 0x00}, /* bank 0 */ - #ifdef INIT_CLK_LOW - {0x62, 0x90, 0x10}, - {0x64, 0x89, 0x09}, - {0x68, 0x10, 0x10}, - #endif - - {0xD1, 0x0E, 0x0C}, - {0x65, 0x03, 0x00}, - #ifdef NON_SEQUENTIAL_YCBCR422 /* for ITE HDMIRX */ - {0x71, 0xFC, 0x1C}, - #else - {0x71, 0xFC, 0x18}, - #endif - - {0x8D, 0xFF, CEC_I2C_SLAVE_ADDR}, - {0x0F, 0x08, 0x08}, - - {0xF8,0xFF,0xC3}, - {0xF8,0xFF,0xA5}, - {0x20, 0x80, 0x80}, - {0x37, 0x01, 0x00}, - {0x20, 0x80, 0x00}, - {0xF8,0xFF,0xFF}, - - {0x59, 0xD8, 0x40|PCLKINV}, - {0xE1, 0x20, InvAudCLK}, - {0x05, 0xC0, 0x40}, - {REG_TX_INT_MASK1, 0xFF, (u8)(~(B_TX_RXSEN_MASK|B_TX_HPD_MASK))}, - {REG_TX_INT_MASK2, 0xFF, (u8)(~(B_TX_KSVLISTCHK_MASK|B_TX_AUTH_DONE_MASK|B_TX_AUTH_FAIL_MASK))}, - {REG_TX_INT_MASK3, 0xFF, (u8)(~(B_TX_VIDSTABLE_MASK))}, - {0x0C, 0xFF, 0xFF}, - {0x0D, 0xFF, 0xFF}, - {0x0E, 0x03, 0x03}, - - {0x0C, 0xFF, 0x00}, - {0x0D, 0xFF, 0x00}, - {0x0E, 0x02, 0x00}, - {0x09, 0x03, 0x00}, /* Enable HPD and RxSen Interrupt */ - {0,0,0} -}; - -RegSetEntry HDMITX_DefaultVideo_Table[] = { - - /* ////////////////////////////////////////////////// - // Config default output format. - /////////////////////////////////////////////////// */ - {0x72, 0xff, 0x00}, - {0x70, 0xff, 0x00}, -#ifndef DEFAULT_INPUT_YCBCR -/* GenCSC\RGB2YUV_ITU709_16_235.c */ - {0x72, 0xFF, 0x02}, - {0x73, 0xFF, 0x00}, - {0x74, 0xFF, 0x80}, - {0x75, 0xFF, 0x00}, - {0x76, 0xFF, 0xB8}, - {0x77, 0xFF, 0x05}, - {0x78, 0xFF, 0xB4}, - {0x79, 0xFF, 0x01}, - {0x7A, 0xFF, 0x93}, - {0x7B, 0xFF, 0x00}, - {0x7C, 0xFF, 0x49}, - {0x7D, 0xFF, 0x3C}, - {0x7E, 0xFF, 0x18}, - {0x7F, 0xFF, 0x04}, - {0x80, 0xFF, 0x9F}, - {0x81, 0xFF, 0x3F}, - {0x82, 0xFF, 0xD9}, - {0x83, 0xFF, 0x3C}, - {0x84, 0xFF, 0x10}, - {0x85, 0xFF, 0x3F}, - {0x86, 0xFF, 0x18}, - {0x87, 0xFF, 0x04}, -#else -/* GenCSC\YUV2RGB_ITU709_16_235.c */ - {0x0F, 0x01, 0x00}, - {0x72, 0xFF, 0x03}, - {0x73, 0xFF, 0x00}, - {0x74, 0xFF, 0x80}, - {0x75, 0xFF, 0x00}, - {0x76, 0xFF, 0x00}, - {0x77, 0xFF, 0x08}, - {0x78, 0xFF, 0x53}, - {0x79, 0xFF, 0x3C}, - {0x7A, 0xFF, 0x89}, - {0x7B, 0xFF, 0x3E}, - {0x7C, 0xFF, 0x00}, - {0x7D, 0xFF, 0x08}, - {0x7E, 0xFF, 0x51}, - {0x7F, 0xFF, 0x0C}, - {0x80, 0xFF, 0x00}, - {0x81, 0xFF, 0x00}, - {0x82, 0xFF, 0x00}, - {0x83, 0xFF, 0x08}, - {0x84, 0xFF, 0x00}, - {0x85, 0xFF, 0x00}, - {0x86, 0xFF, 0x87}, - {0x87, 0xFF, 0x0E}, -#endif - - {0x04, 0x08, 0x00}, - {0,0,0} -}; - -RegSetEntry HDMITX_SetHDMI_Table[] = { - - /* ////////////////////////////////////////////////// - // Config default HDMI Mode - /////////////////////////////////////////////////// */ - {0xC0, 0x01, 0x01}, - {0xC1, 0x03, 0x03}, - {0xC6, 0x03, 0x03}, - {0,0,0} -}; - -RegSetEntry HDMITX_SetDVI_Table[] = { - - /* ////////////////////////////////////////////////// - // Config default HDMI Mode - /////////////////////////////////////////////////// */ - {0x0F, 0x01, 0x01}, - {0x58, 0xFF, 0x00}, - {0x0F, 0x01, 0x00}, - {0xC0, 0x01, 0x00}, - {0xC1, 0x03, 0x02}, - {0xC6, 0x03, 0x00}, - {0,0,0} -}; - -RegSetEntry HDMITX_DefaultAVIInfo_Table[] = { - - /* ////////////////////////////////////////////////// - // Config default avi infoframe - /////////////////////////////////////////////////// */ - {0x0F, 0x01, 0x01}, - {0x58, 0xFF, 0x10}, - {0x59, 0xFF, 0x08}, - {0x5A, 0xFF, 0x00}, - {0x5B, 0xFF, 0x00}, - {0x5C, 0xFF, 0x00}, - {0x5D, 0xFF, 0x57}, - {0x5E, 0xFF, 0x00}, - {0x5F, 0xFF, 0x00}, - {0x60, 0xFF, 0x00}, - {0x61, 0xFF, 0x00}, - {0x62, 0xFF, 0x00}, - {0x63, 0xFF, 0x00}, - {0x64, 0xFF, 0x00}, - {0x65, 0xFF, 0x00}, - {0x0F, 0x01, 0x00}, - {0xCD, 0x03, 0x03}, - {0,0,0} -}; -RegSetEntry HDMITX_DeaultAudioInfo_Table[] = { - - /* /////////////////////////////////////////////////// - // Config default audio infoframe - /////////////////////////////////////////////////// */ - {0x0F, 0x01, 0x01}, - {0x68, 0xFF, 0x00}, - {0x69, 0xFF, 0x00}, - {0x6A, 0xFF, 0x00}, - {0x6B, 0xFF, 0x00}, - {0x6C, 0xFF, 0x00}, - {0x6D, 0xFF, 0x71}, - {0x0F, 0x01, 0x00}, - {0xCE, 0x03, 0x03}, - - {0,0,0} -}; - -RegSetEntry HDMITX_Aud_CHStatus_LPCM_20bit_48Khz[] = -{ - {0x0F, 0x01, 0x01}, - {0x33, 0xFF, 0x00}, - {0x34, 0xFF, 0x18}, - {0x35, 0xFF, 0x00}, - {0x91, 0xFF, 0x00}, - {0x92, 0xFF, 0x00}, - {0x93, 0xFF, 0x01}, - {0x94, 0xFF, 0x00}, - {0x98, 0xFF, 0x02}, - {0x99, 0xFF, 0xDA}, - {0x0F, 0x01, 0x00}, - {0,0,0}/*end of table*/ -} ; - -RegSetEntry HDMITX_AUD_SPDIF_2ch_24bit[] = -{ - {0x0F, 0x11, 0x00}, - {0x04, 0x14, 0x04}, - {0xE0, 0xFF, 0xD1}, - {0xE1, 0xFF, 0x01}, - {0xE2, 0xFF, 0xE4}, - {0xE3, 0xFF, 0x10}, - {0xE4, 0xFF, 0x00}, - {0xE5, 0xFF, 0x00}, - {0x04, 0x14, 0x00}, - {0,0,0}/*end of table*/ -} ; - -RegSetEntry HDMITX_AUD_I2S_2ch_24bit[] = -{ - {0x0F, 0x11, 0x00}, - {0x04, 0x14, 0x04}, - {0xE0, 0xFF, 0xC1}, - {0xE1, 0xFF, 0x01}, - {0xE2, 0xFF, 0xE4}, - {0xE3, 0xFF, 0x00}, - {0xE4, 0xFF, 0x00}, - {0xE5, 0xFF, 0x00}, - {0x04, 0x14, 0x00}, - {0,0,0}/*end of table*/ -} ; - -RegSetEntry HDMITX_DefaultAudio_Table[] = { - - /* ////////////////////////////////////////////////// - // Config default audio output format. - /////////////////////////////////////////////////// */ - {0x0F, 0x21, 0x00}, - {0x04, 0x14, 0x04}, - {0xE0, 0xFF, 0xC1}, - {0xE1, 0xFF, 0x01}, - {0xE2, 0xFF, 0xE4}, - {0xE3, 0xFF, 0x00}, - {0xE4, 0xFF, 0x00}, - {0xE5, 0xFF, 0x00}, - {0x0F, 0x01, 0x01}, - {0x33, 0xFF, 0x00}, - {0x34, 0xFF, 0x18}, - {0x35, 0xFF, 0x00}, - {0x91, 0xFF, 0x00}, - {0x92, 0xFF, 0x00}, - {0x93, 0xFF, 0x01}, - {0x94, 0xFF, 0x00}, - {0x98, 0xFF, 0x02}, - {0x99, 0xFF, 0xDB}, - {0x0F, 0x01, 0x00}, - {0x04, 0x14, 0x00}, - - {0x00, 0x00, 0x00} /* End of Table. */ -} ; - -RegSetEntry HDMITX_PwrDown_Table[] = { - /* Enable GRCLK */ - {0x0F, 0x40, 0x00}, - /* PLL Reset */ - {0x61, 0x10, 0x10}, /* DRV_RST */ - {0x62, 0x08, 0x00}, /* XP_RESETB */ - {0x64, 0x04, 0x00}, /* IP_RESETB */ - {0x01, 0x00, 0x00}, /* idle(100); */ - - /* PLL PwrDn */ - {0x61, 0x20, 0x20}, /* PwrDn DRV */ - {0x62, 0x44, 0x44}, /* PwrDn XPLL */ - {0x64, 0x40, 0x40}, /* PwrDn IPLL */ - - /* HDMITX PwrDn */ - {0x05, 0x01, 0x01}, /* PwrDn PCLK */ - {0x0F, 0x78, 0x78}, /* PwrDn GRCLK */ - {0x00, 0x00, 0x00} /* End of Table. */ -}; - -RegSetEntry HDMITX_PwrOn_Table[] = { - {0x0F, 0x78, 0x38}, /* PwrOn GRCLK */ - {0x05, 0x01, 0x00}, /* PwrOn PCLK */ - - /* PLL PwrOn */ - {0x61, 0x20, 0x00}, /* PwrOn DRV */ - {0x62, 0x44, 0x00}, /* PwrOn XPLL */ - {0x64, 0x40, 0x00}, /* PwrOn IPLL */ - - /* PLL Reset OFF */ - {0x61, 0x10, 0x00}, /* DRV_RST */ - {0x62, 0x08, 0x08}, /* XP_RESETB */ - {0x64, 0x04, 0x04}, /* IP_RESETB */ - {0x0F, 0x78, 0x08}, /* PwrOn IACLK */ - {0x00, 0x00, 0x00} /* End of Table. */ -}; - -void ast_hdmi_init(struct drm_device *dev) -{ - - hdmitx_LoadRegSetting(dev, HDMITX_Init_Table); - hdmitx_LoadRegSetting(dev, HDMITX_DefaultVideo_Table); - hdmitx_LoadRegSetting(dev, HDMITX_SetDVI_Table); //set to DVI mode - //hdmitx_LoadRegSetting(dev, HDMITX_SetHDMI_Table); - //hdmitx_LoadRegSetting(dev, HDMITX_DefaultAVIInfo_Table); - //hdmitx_LoadRegSetting(dev, HDMITX_DeaultAudioInfo_Table); - //hdmitx_LoadRegSetting(dev, HDMITX_Aud_CHStatus_LPCM_20bit_48Khz); - //hdmitx_LoadRegSetting(dev, HDMITX_AUD_SPDIF_2ch_24bit); - -} -RegSetEntry HDMITX_DisableVideoOutput_Table[] = { - {0x0F, 0x01, 0x00}, - {REG_TX_SW_RST, 0x00, B_HDMITX_VID_RST}, - {REG_TX_AFE_DRV_CTRL, 0xFF, (B_TX_AFE_DRV_RST + B_TX_AFE_DRV_PWD)}, - {0x62, 0x90, 0x00}, - {0x64, 0x89, 0x00}, - {0x00, 0x00, 0x00} -}; - -void ast_hdmi_disable(struct drm_device *dev) -{ - hdmitx_LoadRegSetting(dev, HDMITX_DisableVideoOutput_Table); -} /* DisableHDMITX */ - -RegSetEntry ClearDDCFIFO_HDMITX_Table[] = { - {0x0F, 0x01, 0x00}, /*switch bank 0 */ - {REG_TX_DDC_MASTER_CTRL, 0xff, (B_TX_MASTERDDC+B_TX_MASTERHOST)}, /*hdmitx_ClearDDCFIFO */ - {REG_TX_DDC_CMD, 0xff, CMD_FIFO_CLR}, - {0x01, 0x00, 0x00}, /*delay*/ - {0x00, 0x00, 0x00} -}; - -RegSetEntry ReadEDID_HDMITX_Table[] = { - {0x0F, 0x01, 0x00}, /*switch bank 0*/ - {REG_TX_DDC_MASTER_CTRL, 0xff, (B_TX_MASTERDDC+B_TX_MASTERHOST)}, /*hdmitx_ClearDDCFIFO*/ - {REG_TX_DDC_HEADER, 0xff, 0xa0}, - {REG_TX_DDC_REQCOUNT, 0xff, 0x20}, /*max. fifo: 0x20*/ - {REG_TX_DDC_EDIDSEG, 0xff, 0x00}, - {REG_TX_DDC_CMD, 0xff, CMD_EDID_READ}, - {0x00, 0x00, 0x00} -}; - -bool ast_hdmi_read_edid(struct drm_device *dev, u8 *pEDIDData) -{ - u8 i, j; - u8 *pEDIDPtr = pEDIDData; - u8 volatile jReg; - bool Status = FALSE; - - { - for (i=0; i<4; i++) - { - hdmitx_LoadRegSetting(dev, ClearDDCFIFO_HDMITX_Table); - do { - jReg = HDMITX_ReadI2C_Byte(dev, REG_TX_DDC_STATUS); - if (jReg & B_TX_DDC_ERROR) /*error*/ - return FALSE; - } while (!(jReg & B_TX_DDC_DONE)); - - HDMITX_WriteI2C_Byte(dev, REG_TX_DDC_REQOFF, i*0x20); - hdmitx_LoadRegSetting(dev, ReadEDID_HDMITX_Table); - do { - jReg = HDMITX_ReadI2C_Byte(dev, REG_TX_DDC_STATUS); - if (jReg & B_TX_DDC_ERROR) /*error*/ - return FALSE; - } while (!(jReg & B_TX_DDC_DONE)); - - for (j=0; jRGB)*/ - {0x0F, 0x10, 0x10}, - {REG_TX_CSC_CTRL, (M_TX_CSC_SEL+B_TX_DNFREE_GO+B_TX_EN_DITHER+B_TX_EN_UDFILTER), B_HDMITX_CSC_BYPASS}, - /*set dvi mode*/ - {REG_TX_HDMI_MODE, 0xff, B_TX_DVI_MODE}, - /*hdmitx_SetupAFE*/ - {REG_TX_AFE_DRV_CTRL, 0xff, B_TX_AFE_DRV_RST}, - /*{0x62, 0x90, 0x80},*/ /*PCLK_HIGH */ - /*{0x64, 0x89, 0x80},*/ - /*{0x68, 0x10, 0x80},*/ - {0x62, 0x90, 0x10}, /*PCLK_LOW*/ - {0x64, 0x89, 0x09}, - {0x68, 0x10, 0x10}, - {REG_TX_SW_RST, (B_TX_REF_RST_HDMITX+B_HDMITX_VID_RST), 0x00}, - {REG_TX_AFE_DRV_CTRL, 0xff, 0x00}, - {0x01, 0x00, 0x00}, /* delay1 */ - {REG_TX_SW_RST, 0xff, (B_HDMITX_AUD_RST+B_TX_AREF_RST+B_TX_HDCP_RST_HDMITX)}, - {0x0F, 0x01, 0x00}, /* switch bank 0 */ - {REG_TX_AFE_DRV_CTRL, 0xff, 0x00}, /*hdmitx_FireAFE*/ - {REG_TX_AVI_INFOFRM_CTRL, 0xff, 0x00}, /*hdmitx_DISABLE_AVI_INFOFRM_PKT*/ - {REG_TX_3D_INFO_CTRL, 0xff, 0x00}, /*hdmitx_DISABLE_VSDB_PKT*/ - {REG_TX_GCP, B_TX_SETAVMUTE, 0x00}, /*setHDMITX_AVMute*/ - {REG_TX_PKT_GENERAL_CTRL, 0xff, (B_TX_ENABLE_PKT+B_TX_REPEAT_PKT)}, - {0x00, 0x00, 0x00} -}; - -void ast_hdmi_set_output(struct drm_device *dev) -{ - /*ITE66121_SetOutput*/ - hdmitx_LoadRegSetting(dev, HDMITX_SetOutput_Table); -} diff --git a/src/ast_hdmitx.h b/src/ast_hdmitx.h deleted file mode 100644 index dc31f81..0000000 --- a/src/ast_hdmitx.h +++ /dev/null @@ -1,710 +0,0 @@ -/* #define EXTERN_HDCPROM */ -/* /////////////////////////////////////// - // DDC Address - /////////////////////////////////////// */ -#define DDC_HDCP_ADDRESS 0x74 -#define DDC_EDID_ADDRESS 0xA0 -#define DDC_FIFO_MAXREQ 0x20 - -/* I2C address */ - -#define _80MHz 80000000 -#define HDMI_I2C_CHANNEL 1 -#define HDMI_TX_I2C_SLAVE_ADDR 0x98 -#define CEC_I2C_SLAVE_ADDR 0x9C -/* ///////////////////////////////////////////////////////////////////// - // Register offset - ////////////////////////////////////////////////////////////////////// */ - -#define REG_TX_VENDOR_ID0 0x00 -#define REG_TX_VENDOR_ID1 0x01 -#define REG_TX_DEVICE_ID0 0x02 -#define REG_TX_DEVICE_ID1 0x03 - - #define O_TX_DEVID 0 - #define M_TX_DEVID 0xF - #define O_TX_REVID 4 - #define M_TX_REVID 0xF - -#define REG_TX_SW_RST 0x04 - #define B_TX_ENTEST (1<<7) - #define B_TX_REF_RST_HDMITX (1<<5) - #define B_TX_AREF_RST (1<<4) - #define B_HDMITX_VID_RST (1<<3) - #define B_HDMITX_AUD_RST (1<<2) - #define B_TX_HDMI_RST (1<<1) - #define B_TX_HDCP_RST_HDMITX (1<<0) - -#define REG_TX_INT_CTRL 0x05 - #define B_TX_INTPOL_ACTL 0 - #define B_TX_INTPOL_ACTH (1<<7) - #define B_TX_INT_PUSHPULL 0 - #define B_TX_INT_OPENDRAIN (1<<6) - -#define REG_TX_INT_STAT1 0x06 - #define B_TX_INT_AUD_OVERFLOW (1<<7) - #define B_TX_INT_ROMACQ_NOACK (1<<6) - #define B_TX_INT_RDDC_NOACK (1<<5) - #define B_TX_INT_DDCFIFO_ERR (1<<4) - #define B_TX_INT_ROMACQ_BUS_HANG (1<<3) - #define B_TX_INT_DDC_BUS_HANG (1<<2) - #define B_TX_INT_RX_SENSE (1<<1) - #define B_TX_INT_HPD_PLUG (1<<0) - -#define REG_TX_INT_STAT2 0x07 - #define B_TX_INT_HDCP_SYNC_DET_FAIL (1<<7) - #define B_TX_INT_VID_UNSTABLE (1<<6) - #define B_TX_INT_PKTACP (1<<5) - #define B_TX_INT_PKTNULL (1<<4) - #define B_TX_INT_PKTGENERAL (1<<3) - #define B_TX_INT_KSVLIST_CHK (1<<2) - #define B_TX_INT_AUTH_DONE (1<<1) - #define B_TX_INT_AUTH_FAIL (1<<0) - -#define REG_TX_INT_STAT3 0x08 - #define B_TX_INT_AUD_CTS (1<<6) - #define B_TX_INT_VSYNC (1<<5) - #define B_TX_INT_VIDSTABLE (1<<4) - #define B_TX_INT_PKTMPG (1<<3) - #define B_TX_INT_PKTSPD (1<<2) - #define B_TX_INT_PKTAUD (1<<1) - #define B_TX_INT_PKTAVI (1<<0) - -#define REG_TX_INT_MASK1 0x09 - #define B_TX_AUDIO_OVFLW_MASK (1<<7) - #define B_TX_DDC_NOACK_MASK (1<<5) - #define B_TX_DDC_FIFO_ERR_MASK (1<<4) - #define B_TX_DDC_BUS_HANG_MASK (1<<2) - #define B_TX_RXSEN_MASK (1<<1) - #define B_TX_HPD_MASK (1<<0) - -#define REG_TX_INT_MASK2 0x0A - #define B_TX_PKT_AVI_MASK (1<<7) - #define B_TX_PKT_VID_UNSTABLE_MASK (1<<6) - #define B_TX_PKT_ACP_MASK (1<<5) - #define B_TX_PKT_NULL_MASK (1<<4) - #define B_TX_PKT_GEN_MASK (1<<3) - #define B_TX_KSVLISTCHK_MASK (1<<2) - #define B_TX_AUTH_DONE_MASK (1<<1) - #define B_TX_AUTH_FAIL_MASK (1<<0) - -#define REG_TX_INT_MASK3 0x0B - #define B_TX_HDCP_SYNC_DET_FAIL_MASK (1<<6) - #define B_TX_AUDCTS_MASK (1<<5) - #define B_TX_VSYNC_MASK (1<<4) - #define B_TX_VIDSTABLE_MASK (1<<3) - #define B_TX_PKT_MPG_MASK (1<<2) - #define B_TX_PKT_SPD_MASK (1<<1) - #define B_TX_PKT_AUD_MASK (1<<0) - -#define REG_TX_INT_CLR0 0x0C - #define B_TX_CLR_PKTACP (1<<7) - #define B_TX_CLR_PKTNULL (1<<6) - #define B_TX_CLR_PKTGENERAL (1<<5) - #define B_TX_CLR_KSVLISTCHK (1<<4) - #define B_TX_CLR_AUTH_DONE (1<<3) - #define B_TX_CLR_AUTH_FAIL (1<<2) - #define B_TX_CLR_RXSENSE (1<<1) - #define B_TX_CLR_HPD (1<<0) - -#define REG_TX_INT_CLR1 0x0D - #define B_TX_CLR_VSYNC (1<<7) - #define B_TX_CLR_VIDSTABLE (1<<6) - #define B_TX_CLR_PKTMPG (1<<5) - #define B_TX_CLR_PKTSPD (1<<4) - #define B_TX_CLR_PKTAUD (1<<3) - #define B_TX_CLR_PKTAVI (1<<2) - #define B_TX_CLR_HDCP_SYNC_DET_FAIL (1<<1) - #define B_TX_CLR_VID_UNSTABLE (1<<0) - -#define REG_TX_SYS_STATUS 0x0E - /* readonly */ - #define B_TX_INT_ACTIVE (1<<7) - #define B_TX_HPDETECT (1<<6) - #define B_TX_RXSENDETECT (1<<5) - #define B_TXVIDSTABLE (1<<4) - /* read/write */ - #define O_TX_CTSINTSTEP 2 - #define M_TX_CTSINTSTEP (3<<2) - #define B_TX_CLR_AUD_CTS (1<<1) - #define B_TX_INTACTDONE (1<<0) - -#define REG_TX_BANK_CTRL 0x0F - #define B_TX_BANK0 0 - #define B_TX_BANK1 1 - -/* DDC */ - -#define REG_TX_DDC_MASTER_CTRL 0x10 - #define B_TX_MASTERROM (1<<1) - #define B_TX_MASTERDDC (0<<1) - #define B_TX_MASTERHOST (1<<0) - #define B_TX_MASTERHDCP (0<<0) - -#define REG_TX_DDC_HEADER 0x11 -#define REG_TX_DDC_REQOFF 0x12 -#define REG_TX_DDC_REQCOUNT 0x13 -#define REG_TX_DDC_EDIDSEG 0x14 -#define REG_TX_DDC_CMD 0x15 - #define CMD_DDC_SEQ_BURSTREAD 0 - #define CMD_LINK_CHKREAD 2 - #define CMD_EDID_READ 3 - #define CMD_FIFO_CLR 9 - #define CMD_GEN_SCLCLK 0xA - #define CMD_DDC_ABORT 0xF - -#define REG_TX_DDC_STATUS 0x16 - #define B_TX_DDC_DONE (1<<7) - #define B_TX_DDC_ACT (1<<6) - #define B_TX_DDC_NOACK (1<<5) - #define B_TX_DDC_WAITBUS (1<<4) - #define B_TX_DDC_ARBILOSE (1<<3) - #define B_TX_DDC_ERROR (B_TX_DDC_NOACK|B_TX_DDC_WAITBUS|B_TX_DDC_ARBILOSE) - #define B_TX_DDC_FIFOFULL (1<<2) - #define B_TX_DDC_FIFOEMPTY (1<<1) - -#define REG_TX_DDC_READFIFO 0x17 -#define REG_TX_ROM_STARTADDR 0x18 -#define REG_TX_HDCP_HEADER 0x19 -#define REG_TX_ROM_HEADER 0x1A -#define REG_TX_BUSHOLD_T 0x1B -#define REG_TX_ROM_STAT 0x1C - #define B_TX_ROM_DONE (1<<7) - #define B_TX_ROM_ACTIVE (1<<6) - #define B_TX_ROM_NOACK (1<<5) - #define B_TX_ROM_WAITBUS (1<<4) - #define B_TX_ROM_ARBILOSE (1<<3) - #define B_TX_ROM_BUSHANG (1<<2) - -/* HDCP */ -#define REG_TX_AN_GENERATE 0x1F - #define B_TX_START_CIPHER_GEN 1 - #define B_TX_STOP_CIPHER_GEN 0 - -#define REG_TX_CLK_CTRL0 0x58 - #define O_TX_OSCLK_SEL 5 - #define M_TX_OSCLK_SEL 3 - #define B_TX_AUTO_OVER_SAMPLING_CLOCK (1<<4) - #define O_TX_EXT_MCLK_SEL 2 - #define M_TX_EXT_MCLK_SEL (3< +#include + +#include "ast_drv.h" + +static void ast_i2c_setsda(void *i2c_priv, int data) +{ + struct ast_i2c_chan *i2c = i2c_priv; + struct ast_private *ast = to_ast_private(i2c->dev); + int i; + u8 ujcrb7, jtemp; + + for (i = 0; i < 0x10000; i++) { + ujcrb7 = ((data & 0x01) ? 0 : 1) << 2; + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0xf1, ujcrb7); + jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x04); + if (ujcrb7 == jtemp) + break; + } +} + +static void ast_i2c_setscl(void *i2c_priv, int clock) +{ + struct ast_i2c_chan *i2c = i2c_priv; + struct ast_private *ast = to_ast_private(i2c->dev); + int i; + u8 ujcrb7, jtemp; + + for (i = 0; i < 0x10000; i++) { + ujcrb7 = ((clock & 0x01) ? 0 : 1); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0xf4, ujcrb7); + jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x01); + if (ujcrb7 == jtemp) + break; + } +} + +static int ast_i2c_getsda(void *i2c_priv) +{ + struct ast_i2c_chan *i2c = i2c_priv; + struct ast_private *ast = to_ast_private(i2c->dev); + uint32_t val, val2, count, pass; + + count = 0; + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x20) >> 5) & 0x01; + do { + val2 = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x20) >> 5) & 0x01; + if (val == val2) { + pass++; + } else { + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x20) >> 5) & 0x01; + } + } while ((pass < 5) && (count++ < 0x10000)); + + return val & 1 ? 1 : 0; +} + +static int ast_i2c_getscl(void *i2c_priv) +{ + struct ast_i2c_chan *i2c = i2c_priv; + struct ast_private *ast = to_ast_private(i2c->dev); + uint32_t val, val2, count, pass; + + count = 0; + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x10) >> 4) & 0x01; + do { + val2 = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x10) >> 4) & 0x01; + if (val == val2) { + pass++; + } else { + pass = 0; + val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x10) >> 4) & 0x01; + } + } while ((pass < 5) && (count++ < 0x10000)); + + return val & 1 ? 1 : 0; +} + +static void ast_i2c_release(struct drm_device *dev, void *res) +{ + struct ast_i2c_chan *i2c = res; + + i2c_del_adapter(&i2c->adapter); +} + +struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) +{ + struct ast_i2c_chan *i2c; + int ret; + + i2c = drmm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return ERR_PTR(-ENOMEM); + + i2c->adapter.owner = THIS_MODULE; + i2c->adapter.dev.parent = dev->dev; + i2c->dev = dev; + i2c_set_adapdata(&i2c->adapter, i2c); + snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), + "AST i2c bit bus"); + i2c->adapter.algo_data = &i2c->bit; + + i2c->bit.udelay = 20; + i2c->bit.timeout = 2; + i2c->bit.data = i2c; + i2c->bit.setsda = ast_i2c_setsda; + i2c->bit.setscl = ast_i2c_setscl; + i2c->bit.getsda = ast_i2c_getsda; + i2c->bit.getscl = ast_i2c_getscl; + ret = i2c_bit_add_bus(&i2c->adapter); + if (ret) { + drm_err(dev, "Failed to register bit i2c\n"); + return ERR_PTR(ret); + } + + ret = drmm_add_action_or_reset(dev, ast_i2c_release, i2c); + if (ret) + return ERR_PTR(ret); + + return i2c; +} diff --git a/src/ast_main.c b/src/ast_main.c index 2810cee..394ffd8 100644 --- a/src/ast_main.c +++ b/src/ast_main.c @@ -27,11 +27,11 @@ */ #include -#include #include +#include #include -#include +#include #include "ast_drv.h" @@ -67,8 +67,9 @@ u8 ast_get_index_reg_mask(struct ast_private *ast, static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) { - struct device_node *np = dev->pdev->dev.of_node; + struct device_node *np = dev->dev->of_node; struct ast_private *ast = to_ast_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); u32 data, jregd0, jregd1; /* Defaults */ @@ -85,7 +86,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) } /* Not all families have a P2A bridge */ - if (dev->pdev->device != PCI_CHIP_AST2000) + if (pdev->device != PCI_CHIP_AST2000) return; /* @@ -93,23 +94,17 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) * is disabled. We force using P2A if VGA only mode bit * is set D[7] */ - jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); - jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); + jregd0 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); + jregd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff); if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { - /* Patch AST2500 */ - if (((dev->pdev->revision & 0xF0) == 0x40) && ((jregd0 & 0xC0) == 0)) + /* Patch GEN6 */ + if (((pdev->revision & 0xF0) == 0x40) + && ((jregd0 & AST_VRAM_INIT_STATUS_MASK) == 0)) ast_patch_ahb_2500(ast); /* Double check it's actually working */ - if ((dev->pdev->revision & 0xF0) >= 0x30) - data = ast_read32(ast, 0xf004); - else /* AST2300 and before */ - { - ast_write32(ast, 0xf004, 0x1e6e0000); - ast_write32(ast, 0xf000, 0x1); - data = ast_read32(ast, 0x1207c); - } - if ((data != 0xFFFFFFFF) && (data != 0x00)) { // for AST2600, data == 0x00 + data = ast_read32(ast, 0xf004); + if ((data != 0xFFFFFFFF) && (data != 0x00)) { /* P2A works, grab silicon revision */ ast->config_mode = ast_use_p2a; @@ -130,6 +125,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) static int ast_detect_chip(struct drm_device *dev, bool *need_post) { struct ast_private *ast = to_ast_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); u32 jreg, scu_rev; /* @@ -154,65 +150,73 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ast_detect_config_mode(dev, &scu_rev); /* Identify chipset */ - if (dev->pdev->device == PCI_CHIP_AIP200) { - ast->chip = AIP200; - drm_info(dev, "AIP 200 detected\n"); - } else { - if (dev->pdev->revision >= 0x50) { - ast->chip = AST2600; - drm_info(dev, "AST 2600 detected\n"); - } else if (dev->pdev->revision >= 0x40) { + if (pdev->revision >= 0x50) { + ast->chip = AST2600; + drm_info(dev, "AST 2600 detected\n"); + } else if (pdev->revision >= 0x40) { + switch (scu_rev & 0x300) { + case 0x0100: + ast->chip = AST2510; + drm_info(dev, "AST 2510 detected\n"); + break; + default: ast->chip = AST2500; drm_info(dev, "AST 2500 detected\n"); - } else if (dev->pdev->revision >= 0x30) { + } + } else if (pdev->revision >= 0x30) { + switch (scu_rev & 0x300) { + case 0x0100: + ast->chip = AST1400; + drm_info(dev, "AST 1400 detected\n"); + break; + default: ast->chip = AST2400; drm_info(dev, "AST 2400 detected\n"); - } else if (dev->pdev->revision >= 0x20) { + } + } else if (pdev->revision >= 0x20) { + switch (scu_rev & 0x300) { + case 0x0000: + ast->chip = AST1300; + drm_info(dev, "AST 1300 detected\n"); + break; + default: ast->chip = AST2300; drm_info(dev, "AST 2300 detected\n"); - } else if (dev->pdev->revision >= 0x10) { - switch (scu_rev & 0x0300) { - case 0x0200: - ast->chip = AST1100; - drm_info(dev, "AST 1100 detected\n"); - break; - case 0x0100: - ast->chip = AST2200; - drm_info(dev, "AST 2200 detected\n"); - break; - case 0x0000: - ast->chip = AST2150; - drm_info(dev, "AST 2150 detected\n"); - break; - default: - ast->chip = AST2100; - drm_info(dev, "AST 2100 detected\n"); - break; - } - } else { - ast->chip = AST2000; - drm_info(dev, "AST 2000 detected\n"); } - } - - /* If P2A disable, check the DRAM initiated by BMC */ - if (ast->config_mode != ast_use_p2a){ - if(ast_wait_dram_init(ast) == false){ - drm_err(dev, "DRAM did not be initiated\n"); - return -1; + } else if (pdev->revision >= 0x10) { + switch (scu_rev & 0x0300) { + case 0x0200: + ast->chip = AST1100; + drm_info(dev, "AST 1100 detected\n"); + break; + case 0x0100: + ast->chip = AST2200; + drm_info(dev, "AST 2200 detected\n"); + break; + case 0x0000: + ast->chip = AST2150; + drm_info(dev, "AST 2150 detected\n"); + break; + default: + ast->chip = AST2100; + drm_info(dev, "AST 2100 detected\n"); + break; } + } else { + ast->chip = AST2000; + drm_info(dev, "AST 2000 detected\n"); } /* Check 25MHz Ref CLK */ ast->RefCLK25MHz = false; - if (ast->chip == AST2400 || ast->chip == AST2500 || ast->chip == AST2600) { + if (IS_AST_GEN5(ast) || IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) { if (ast->config_mode == ast_use_p2a) { jreg = ast_read32(ast, 0x12070); if (jreg & 0x00800000) ast->RefCLK25MHz = true; } else { - jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); - if (jreg & 0x04) + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); + if (jreg & AST_VPLL_REF_CLOCK_25M) ast->RefCLK25MHz = true; } } @@ -229,31 +233,28 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) * SIL164 when there is none. */ if (!*need_post) { - jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff); + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); if (jreg & 0x80) ast->tx_chip_type = AST_TX_SIL164; } - if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) { + if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { /* - * On AST2300 and 2400, look the configuration set by the SoC in + * On AST GEN4+, look 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_CRTC_PORT, 0xd1, 0xff); + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff); switch (jreg) { - case 0x02: - ast->tx_chip_type = AST_TX_ITE66121; - break; case 0x04: ast->tx_chip_type = AST_TX_SIL164; break; case 0x08: - ast->dp501_fw_addr = kzalloc(32 * 1024, GFP_KERNEL); + 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) == false) { - kfree(ast->dp501_fw_addr); + drmm_kfree(dev, ast->dp501_fw_addr); ast->dp501_fw_addr = NULL; } } @@ -261,11 +262,11 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) case 0x0c: ast->tx_chip_type = AST_TX_DP501; } - } else if (ast->chip == AST2600) { - if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK) == + } 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_type = AST_TX_ASTDP; - ast_dp_launch(dev); + ast_dp_launch(&ast->base); } } @@ -288,7 +289,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) static int ast_get_dram_info(struct drm_device *dev) { - struct device_node *np = dev->pdev->dev.of_node; + struct device_node *np = dev->dev->of_node; struct ast_private *ast = to_ast_private(dev); u32 mcr_cfg, mcr_scu_mpll, mcr_scu_strap; u32 denum, num, div, ref_pll, dsel; @@ -297,7 +298,7 @@ static int ast_get_dram_info(struct drm_device *dev) case ast_use_dt: /* * If some properties are missing, use reasonable - * defaults for AST2400 + * defaults for GEN5 */ if (of_property_read_u32(np, "aspeed,mcr-configuration", &mcr_cfg)) @@ -320,7 +321,7 @@ static int ast_get_dram_info(struct drm_device *dev) default: ast->dram_bus_width = 16; ast->dram_type = AST_DRAM_1Gx16; - if (ast->chip == AST2500 || ast->chip == AST2600) + if (IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) ast->mclk = 800; else ast->mclk = 396; @@ -332,7 +333,7 @@ static int ast_get_dram_info(struct drm_device *dev) else ast->dram_bus_width = 32; - if (ast->chip == AST2500) { + if (IS_AST_GEN6(ast)) { switch (mcr_cfg & 0x03) { case 0: ast->dram_type = AST_DRAM_1Gx16; @@ -348,7 +349,7 @@ static int ast_get_dram_info(struct drm_device *dev) ast->dram_type = AST_DRAM_8Gx16; break; } - } else if (ast->chip == AST2300 || ast->chip == AST2400) { + } else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) { switch (mcr_cfg & 0x03) { case 0: ast->dram_type = AST_DRAM_512Mx16; @@ -406,117 +407,87 @@ static int ast_get_dram_info(struct drm_device *dev) return 0; } -int ast_driver_load(struct drm_device *dev, unsigned long flags) +/* + * Run this function as part of the HW device cleanup; not + * when the DRM device gets released. + */ +static void ast_device_release(void *data) { + struct ast_private *ast = data; + + /* enable standard VGA decode */ + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x04); +} + +struct ast_private *ast_device_create(const struct drm_driver *drv, + struct pci_dev *pdev, + unsigned long flags) +{ + struct drm_device *dev; struct ast_private *ast; bool need_post; int ret = 0; - ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL); - if (!ast) - return -ENOMEM; - - dev->dev_private = ast; - ast->dev = dev; + ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_private, base); + if (IS_ERR(ast)) + return ast; + dev = &ast->base; - mutex_init(&ast->ioregs_lock); + pci_set_drvdata(pdev, dev); - ast->regs = pci_iomap(dev->pdev, 1, 0); - if (!ast->regs) { - ret = -EIO; - goto out_free; - } + ast->regs = pcim_iomap(pdev, 1, 0); + if (!ast->regs) + return ERR_PTR(-EIO); /* * After AST2500, MMIO is enabled by default, and it should be adopted * to be compatible with ARM. */ - if (dev->pdev->revision >= 0x40) { + if (pdev->revision >= 0x40) { ast->ioregs = ast->regs + AST_IO_MM_OFFSET; - } else if (!(pci_resource_flags(dev->pdev, 2) & IORESOURCE_IO)) { + } else if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) { drm_info(dev, "platform has no IO space, trying MMIO\n"); ast->ioregs = ast->regs + AST_IO_MM_OFFSET; } /* "map" IO regs if the above hasn't done so already */ if (!ast->ioregs) { - ast->ioregs = pcim_iomap(dev->pdev, 2, 0); - if (!ast->ioregs) { - ret = -EIO; - goto out_free; - } + ast->ioregs = pcim_iomap(pdev, 2, 0); + if (!ast->ioregs) + return ERR_PTR(-EIO); } - ret = ast_detect_chip(dev, &need_post); - if (ret) - goto out_free; - - if (need_post) - ast_post_gpu(dev); + ast_detect_chip(dev, &need_post); ret = ast_get_dram_info(dev); if (ret) - goto out_free; + 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); + ast->mclk, ast->dram_type, ast->dram_bus_width); - ret = ast_mm_init(ast); + if (need_post) + ast_post_gpu(dev); + ret = ast_mm_init(ast); if (ret) - goto out_free; + return ERR_PTR(ret); /* map reserved buffer */ - ast->reservedbuffer = NULL; - if (dev->vram_mm->vram_size < pci_resource_len(dev->pdev, 0)) { - ast->reservedbuffer = ioremap(pci_resource_start(ast->dev->pdev, 0) + (unsigned long)dev->vram_mm->vram_size, - pci_resource_len(dev->pdev, 0) - dev->vram_mm->vram_size); - if (!ast->reservedbuffer) { - drm_warn(dev, "failed to map reserved buffer! \n"); - } + ast->dp501_fw_buf = NULL; + if (ast->vram_size < pci_resource_len(pdev, 0)) { + ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0); + if (!ast->dp501_fw_buf) + drm_info(dev, "failed to map reserved buffer!\n"); } ret = ast_mode_config_init(ast); if (ret) - goto out_free; - - return 0; -out_free: - kfree(ast); - dev->dev_private = NULL; - return ret; -} + return ERR_PTR(ret); -void ast_driver_unload(struct drm_device *dev) -{ - struct ast_private *ast = to_ast_private(dev); - - /* enable standard VGA decode */ - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); - - ast_release_firmware(dev); - kfree(ast->dp501_fw_addr); - mutex_destroy(&ast->ioregs_lock); - - kfree(ast); -} - -bool ast_wait_dram_init(struct ast_private *ast) -{ - u32 WaitCount = 15000; - u8 bDRAMInitial = 0; - bool bStatus = true; - - do{ - bDRAMInitial = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD0, 0x40); - msleep(1); - WaitCount--; - - if(WaitCount == 0){ - bStatus = false; - break; - } - } while(!bDRAMInitial); + ret = devm_add_action_or_reset(dev->dev, ast_device_release, ast); + if (ret) + return ERR_PTR(ret); - return bStatus; + return ast; } - diff --git a/src/ast_mm.c b/src/ast_mm.c index 7fbe353..260b1e7 100644 --- a/src/ast_mm.c +++ b/src/ast_mm.c @@ -28,7 +28,6 @@ #include -#include #include #include @@ -40,7 +39,7 @@ static u32 ast_get_vram_size(struct ast_private *ast) u32 vram_size; vram_size = AST_VIDMEM_DEFAULT_SIZE; - jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff); + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xaa, 0xff); switch (jreg & 3) { case 0: vram_size = AST_VIDMEM_SIZE_8M; @@ -56,7 +55,7 @@ static u32 ast_get_vram_size(struct ast_private *ast) break; } - jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xff); + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0x99, 0xff); switch (jreg & 0x03) { case 1: vram_size -= 0x100000; @@ -72,35 +71,30 @@ static u32 ast_get_vram_size(struct ast_private *ast) return vram_size; } -static void ast_mm_release(struct drm_device *dev, void *ptr) -{ - struct ast_private *ast = to_ast_private(dev); - - arch_phys_wc_del(ast->fb_mtrr); - arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), - pci_resource_len(dev->pdev, 0)); -} - int ast_mm_init(struct ast_private *ast) { + struct drm_device *dev = &ast->base; + struct pci_dev *pdev = to_pci_dev(dev->dev); + resource_size_t base, size; u32 vram_size; - int ret; - struct drm_device *dev = ast->dev; + + base = pci_resource_start(pdev, 0); + size = pci_resource_len(pdev, 0); + + /* Don't fail on errors, but performance might be reduced. */ + devm_arch_io_reserve_memtype_wc(dev->dev, base, size); + devm_arch_phys_wc_add(dev->dev, base, size); vram_size = ast_get_vram_size(ast); drm_info(dev, "Available graphics memory: %d KB\n", vram_size / 1024); - ret = drmm_vram_helper_init(dev, pci_resource_start(dev->pdev, 0), - vram_size); - if (ret) { - drm_err(dev, "Error initializing VRAM MM; %d\n", ret); - return ret; - } + ast->vram = devm_ioremap_wc(dev->dev, base, vram_size); + if (!ast->vram) + return -ENOMEM; - arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0), - pci_resource_len(dev->pdev, 0)); - ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0), - pci_resource_len(dev->pdev, 0)); + ast->vram_base = base; + ast->vram_size = vram_size; + ast->vram_fb_available = vram_size; - return drmm_add_action_or_reset(dev, ast_mm_release, NULL); + return 0; } diff --git a/src/ast_mode.c b/src/ast_mode.c index a3adce2..c7ac478 100644 --- a/src/ast_mode.c +++ b/src/ast_mode.c @@ -35,32 +35,34 @@ #include #include #include +#include +#include +#include #include +#include #include -#include -#include +#include +#include #include #include #include "ast_drv.h" #include "ast_tables.h" -#include "ast_hdmitx.h" -static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); -static void ast_i2c_destroy(struct ast_i2c_chan *i2c); +#define AST_LUT_SIZE 256 static inline void ast_load_palette_index(struct ast_private *ast, u8 index, u8 red, u8 green, u8 blue) { - ast_io_write8(ast, AST_IO_DAC_INDEX_WRITE, index); - ast_io_read8(ast, AST_IO_SEQ_PORT); - ast_io_write8(ast, AST_IO_DAC_DATA, red); - ast_io_read8(ast, AST_IO_SEQ_PORT); - ast_io_write8(ast, AST_IO_DAC_DATA, green); - ast_io_read8(ast, AST_IO_SEQ_PORT); - ast_io_write8(ast, AST_IO_DAC_DATA, blue); - ast_io_read8(ast, AST_IO_SEQ_PORT); + ast_io_write8(ast, AST_IO_VGADWR, index); + ast_io_read8(ast, AST_IO_VGASRI); + ast_io_write8(ast, AST_IO_VGAPDR, red); + ast_io_read8(ast, AST_IO_VGASRI); + ast_io_write8(ast, AST_IO_VGAPDR, green); + ast_io_read8(ast, AST_IO_VGASRI); + ast_io_write8(ast, AST_IO_VGAPDR, blue); + ast_io_read8(ast, AST_IO_VGASRI); } static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc) @@ -75,7 +77,7 @@ static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc) g = r + crtc->gamma_size; b = g + crtc->gamma_size; - for (i = 0; i < MAX_COLOR_LUT_ENTRIES; i++) + for (i = 0; i < AST_LUT_SIZE; i++) ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8); } @@ -229,13 +231,13 @@ static void ast_set_vbios_color_reg(struct ast_private *ast, return; } - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0x0f) << 4)); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x8c, (u8)((color_index & 0x0f) << 4)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0x00); if (vbios_mode->enh_table->flags & NewModeInfo) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, format->cpp[0] * 8); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0xa8); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x92, format->cpp[0] * 8); } } @@ -248,23 +250,23 @@ static void ast_set_vbios_mode_reg(struct ast_private *ast, refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; mode_id = vbios_mode->enh_table->mode_id; - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x8d, refresh_rate_index & 0xff); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x8e, mode_id & 0xff); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0x00); if (vbios_mode->enh_table->flags & NewModeInfo) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0xa8); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x93, adjusted_mode->clock / 1000); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x94, adjusted_mode->crtc_hdisplay); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x95, adjusted_mode->crtc_hdisplay >> 8); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x96, adjusted_mode->crtc_vdisplay); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x97, adjusted_mode->crtc_vdisplay >> 8); } if (vbios_mode->enh_table->flags & HalfDCLK) - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xff, 0x08); + ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xff, 0x08); else - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xf7, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xf7, 0x00); } static void ast_set_std_reg(struct ast_private *ast, @@ -278,41 +280,41 @@ static void ast_set_std_reg(struct ast_private *ast, stdtable = vbios_mode->std_table; jreg = stdtable->misc; - ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); + ast_io_write8(ast, AST_IO_VGAMR_W, jreg); /* Set SEQ; except Screen Disable field */ - ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03); - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, stdtable->seq[0]); + ast_set_index_reg(ast, AST_IO_VGASRI, 0x00, 0x03); + ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0x20, stdtable->seq[0]); for (i = 1; i < 4; i++) { jreg = stdtable->seq[i]; - ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1) , jreg); + ast_set_index_reg(ast, AST_IO_VGASRI, (i + 1), jreg); } /* Set CRTC; except base address and offset */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x7f, 0x00); for (i = 0; i < 12; i++) - ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); + ast_set_index_reg(ast, AST_IO_VGACRI, i, stdtable->crtc[i]); for (i = 14; i < 19; i++) - ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); + ast_set_index_reg(ast, AST_IO_VGACRI, i, stdtable->crtc[i]); for (i = 20; i < 25; i++) - ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); + ast_set_index_reg(ast, AST_IO_VGACRI, i, stdtable->crtc[i]); /* set AR */ - jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); + jreg = ast_io_read8(ast, AST_IO_VGAIR1_R); for (i = 0; i < 20; i++) { jreg = stdtable->ar[i]; - ast_io_write8(ast, AST_IO_AR_PORT_WRITE, (u8)i); - ast_io_write8(ast, AST_IO_AR_PORT_WRITE, jreg); + ast_io_write8(ast, AST_IO_VGAARI_W, (u8)i); + ast_io_write8(ast, AST_IO_VGAARI_W, jreg); } - ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14); - ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00); + ast_io_write8(ast, AST_IO_VGAARI_W, 0x14); + ast_io_write8(ast, AST_IO_VGAARI_W, 0x00); - jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); - ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20); + jreg = ast_io_read8(ast, AST_IO_VGAIR1_R); + ast_io_write8(ast, AST_IO_VGAARI_W, 0x20); /* Set GR */ for (i = 0; i < 9; i++) - ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); + ast_set_index_reg(ast, AST_IO_VGAGRI, i, stdtable->gr[i]); } static void ast_set_crtc_reg(struct ast_private *ast, @@ -322,52 +324,52 @@ static void ast_set_crtc_reg(struct ast_private *ast, u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0; u16 temp, precache = 0; - if ((ast->chip == AST2500 || ast->chip == AST2600) && + if ((IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) && (vbios_mode->enh_table->flags & AST2500PreCatchCRT)) precache = 40; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x7f, 0x00); temp = (mode->crtc_htotal >> 3) - 5; if (temp & 0x100) jregAC |= 0x01; /* HT D[8] */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x00, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x00, 0x00, temp); temp = (mode->crtc_hdisplay >> 3) - 1; if (temp & 0x100) jregAC |= 0x04; /* HDE D[8] */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x01, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x01, 0x00, temp); temp = (mode->crtc_hblank_start >> 3) - 1; if (temp & 0x100) jregAC |= 0x10; /* HBS D[8] */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x02, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x02, 0x00, temp); temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f; if (temp & 0x20) jreg05 |= 0x80; /* HBE D[5] */ if (temp & 0x40) jregAD |= 0x01; /* HBE D[5] */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f)); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x03, 0xE0, (temp & 0x1f)); temp = ((mode->crtc_hsync_start-precache) >> 3) - 1; if (temp & 0x100) jregAC |= 0x40; /* HRS D[5] */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x04, 0x00, temp); temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f; if (temp & 0x20) jregAD |= 0x04; /* HRE D[5] */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05)); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05)); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xAC, 0x00, jregAC); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xAD, 0x00, jregAD); //HSync Time non octave pixels (1920x1080@60Hz HSync 44 pixels); VGACRFC[1]=1 for 1080p only. - if ((ast->chip == AST2600) && (mode->crtc_vdisplay == 1080)) - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x02); + if (IS_AST_GEN7(ast) && (mode->crtc_vdisplay == 1080)) + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xFC, 0xFD, 0x02); else - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xFC, 0xFD, 0x00); /* vert timings */ temp = (mode->crtc_vtotal) - 2; @@ -377,7 +379,7 @@ static void ast_set_crtc_reg(struct ast_private *ast, jreg07 |= 0x20; if (temp & 0x400) jregAE |= 0x01; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x06, 0x00, temp); temp = (mode->crtc_vsync_start) - 1; if (temp & 0x100) @@ -386,14 +388,14 @@ static void ast_set_crtc_reg(struct ast_private *ast, jreg07 |= 0x80; if (temp & 0x400) jregAE |= 0x08; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x10, 0x00, temp); temp = (mode->crtc_vsync_end - 1) & 0x3f; if (temp & 0x10) jregAE |= 0x20; if (temp & 0x20) jregAE |= 0x40; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x70, temp & 0xf); temp = mode->crtc_vdisplay - 1; if (temp & 0x100) @@ -402,7 +404,7 @@ static void ast_set_crtc_reg(struct ast_private *ast, jreg07 |= 0x40; if (temp & 0x400) jregAE |= 0x02; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x12, 0x00, temp); temp = mode->crtc_vblank_start - 1; if (temp & 0x100) @@ -411,23 +413,23 @@ static void ast_set_crtc_reg(struct ast_private *ast, jreg09 |= 0x20; if (temp & 0x400) jregAE |= 0x04; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x15, 0x00, temp); temp = mode->crtc_vblank_end - 1; if (temp & 0x100) jregAE |= 0x10; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x16, 0x00, temp); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80)); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x07, 0x00, jreg07); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x09, 0xdf, jreg09); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xAE, 0x00, (jregAE | 0x80)); if (precache) - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0x3f, 0x80); else - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0x3f, 0x00); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x7f, 0x80); } static void ast_set_offset_reg(struct ast_private *ast, @@ -436,8 +438,8 @@ static void ast_set_offset_reg(struct ast_private *ast, u16 offset; offset = fb->pitches[0] >> 3; - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x13, (offset & 0xff)); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xb0, (offset >> 8) & 0x3f); } static void ast_set_dclk_reg(struct ast_private *ast, @@ -446,7 +448,7 @@ static void ast_set_dclk_reg(struct ast_private *ast, { const struct ast_vbios_dclk_info *clk_info; - if (ast->chip == AST2500 || ast->chip == AST2600) { + if (IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) { if (ast->RefCLK25MHz) clk_info = &dclk_table_ast2500_25MHz[vbios_mode->enh_table->dclk_index]; else @@ -458,9 +460,9 @@ static void ast_set_dclk_reg(struct ast_private *ast, clk_info = &dclk_table[vbios_mode->enh_table->dclk_index]; } - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f, + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xc0, 0x00, clk_info->param1); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xc1, 0x00, clk_info->param2); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xbb, 0x0f, (clk_info->param3 & 0xc0) | ((clk_info->param3 & 0x3) << 4)); } @@ -489,30 +491,26 @@ static void ast_set_color_reg(struct ast_private *ast, break; } - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa0, 0x8f, jregA0); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xf0, jregA3); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa8, 0xfd, jregA8); } static void ast_set_crtthd_reg(struct ast_private *ast) { /* Set Threshold */ - if (ast->chip == AST2600) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0xe0); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0xa0); - } else if (ast->chip == AST2300 || ast->chip == AST2400 || - ast->chip == AST2500) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60); - } else if (ast->chip == AST2100 || - ast->chip == AST1100 || - ast->chip == AST2200 || - ast->chip == AST2150) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f); + if (IS_AST_GEN7(ast)) { + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0xe0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0xa0); + } else if (IS_AST_GEN6(ast) || IS_AST_GEN5(ast) || IS_AST_GEN4(ast)) { + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0x78); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0x60); + } else if (IS_AST_GEN3(ast) || IS_AST_GEN2(ast)) { + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0x3f); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0x2f); } else { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0x2f); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0x1f); } } @@ -522,24 +520,24 @@ static void ast_set_sync_reg(struct ast_private *ast, { u8 jreg; - jreg = ast_io_read8(ast, AST_IO_MISC_PORT_READ); + jreg = ast_io_read8(ast, AST_IO_VGAMR_R); jreg &= ~0xC0; if (vbios_mode->enh_table->flags & NVSync) jreg |= 0x80; if (vbios_mode->enh_table->flags & NHSync) jreg |= 0x40; - ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); + ast_io_write8(ast, AST_IO_VGAMR_W, jreg); } static void ast_set_start_address_crt1(struct ast_private *ast, - unsigned offset) + unsigned int offset) { u32 addr; addr = offset >> 2; - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff)); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x0d, (u8)(addr & 0xff)); + ast_set_index_reg(ast, AST_IO_VGACRI, 0x0c, (u8)((addr >> 8) & 0xff)); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xaf, (u8)((addr >> 16) & 0xff)); } @@ -549,10 +547,33 @@ static void ast_wait_for_vretrace(struct ast_private *ast) u8 vgair1; do { - vgair1 = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); + vgair1 = ast_io_read8(ast, AST_IO_VGAIR1_R); } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout)); } +/* + * Planes + */ + +static int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane, + void __iomem *vaddr, u64 offset, unsigned long size, + uint32_t possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, unsigned int format_count, + const uint64_t *format_modifiers, + enum drm_plane_type type) +{ + struct drm_plane *plane = &ast_plane->base; + + ast_plane->vaddr = vaddr; + ast_plane->offset = offset; + ast_plane->size = size; + + return drm_universal_plane_init(dev, plane, possible_crtcs, funcs, + formats, format_count, format_modifiers, + type, NULL); +} + /* * Primary plane */ @@ -564,83 +585,102 @@ static const uint32_t ast_primary_plane_formats[] = { }; static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_atomic_state *state) { - struct drm_crtc_state *crtc_state; - struct ast_crtc_state *ast_crtc_state; + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc_state *new_crtc_state; + struct ast_crtc_state *new_ast_crtc_state; int ret; - if (!state->crtc) + if (!new_plane_state->crtc) return 0; - crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); - ret = drm_atomic_helper_check_plane_state(state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); if (ret) return ret; - if (!state->visible) + if (!new_plane_state->visible) return 0; - ast_crtc_state = to_ast_crtc_state(crtc_state); + new_ast_crtc_state = to_ast_crtc_state(new_crtc_state); - ast_crtc_state->format = state->fb->format; + new_ast_crtc_state->format = new_plane_state->fb->format; return 0; } -static void -ast_primary_plane_helper_atomic_update(struct drm_plane *plane, - struct drm_plane_state *old_plane_state) +static void ast_handle_damage(struct ast_plane *ast_plane, struct iosys_map *src, + struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + struct iosys_map dst = IOSYS_MAP_INIT_VADDR(ast_plane->vaddr); + + iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip)); + drm_fb_memcpy(&dst, fb->pitches, src, fb, clip); +} + +static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *state) { struct drm_device *dev = plane->dev; struct ast_private *ast = to_ast_private(dev); - struct drm_plane_state *plane_state = plane->state; + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_framebuffer *fb = plane_state->fb; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); struct drm_framebuffer *old_fb = old_plane_state->fb; - struct drm_gem_vram_object *gbo; - s64 gpu_addr; + struct ast_plane *ast_plane = to_ast_plane(plane); + struct drm_rect damage; + struct drm_atomic_helper_damage_iter iter; if (!old_fb || (fb->format != old_fb->format)) { struct drm_crtc *crtc = plane_state->crtc; - struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc->state); + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; ast_set_color_reg(ast, fb->format); ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info); } - gbo = drm_gem_vram_of_gem(fb->obj[0]); - gpu_addr = drm_gem_vram_offset(gbo); - if (drm_WARN_ON_ONCE(dev, gpu_addr < 0)) - return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */ + drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); + drm_atomic_for_each_plane_damage(&iter, &damage) { + ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage); + } ast_set_offset_reg(ast, fb); - ast_set_start_address_crt1(ast, (u32)gpu_addr); - - /* Perform flash screen when VGASR01 sceenn enable*/ - ast_wait_for_vretrace(ast); - - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); } -static void -ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) +static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane, + struct drm_atomic_state *state) { struct ast_private *ast = to_ast_private(plane->dev); + struct ast_plane *ast_plane = to_ast_plane(plane); + + /* + * Some BMCs stop scanning out the video signal after the driver + * reprogrammed the scanout address. This stalls display + * output for several seconds and makes the display unusable. + * Therefore only reprogram the address after enabling the plane. + */ + ast_set_start_address_crt1(ast, (u32)ast_plane->offset); +} - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20); +static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *state) +{ } static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { - .prepare_fb = drm_gem_vram_plane_helper_prepare_fb, - .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb, + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, .atomic_check = ast_primary_plane_helper_atomic_check, .atomic_update = ast_primary_plane_helper_atomic_update, + .atomic_enable = ast_primary_plane_helper_atomic_enable, .atomic_disable = ast_primary_plane_helper_atomic_disable, }; @@ -648,101 +688,242 @@ static const struct drm_plane_funcs ast_primary_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, .destroy = drm_plane_cleanup, - .reset = drm_atomic_helper_plane_reset, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + DRM_GEM_SHADOW_PLANE_FUNCS, }; +static int ast_primary_plane_init(struct ast_private *ast) +{ + struct drm_device *dev = &ast->base; + struct ast_plane *ast_primary_plane = &ast->primary_plane; + struct drm_plane *primary_plane = &ast_primary_plane->base; + void __iomem *vaddr = ast->vram; + u64 offset = 0; /* with shmem, the primary plane is always at offset 0 */ + unsigned long cursor_size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); + unsigned long size = ast->vram_fb_available - cursor_size; + int ret; + + ret = ast_plane_init(dev, ast_primary_plane, vaddr, offset, size, + 0x01, &ast_primary_plane_funcs, + ast_primary_plane_formats, ARRAY_SIZE(ast_primary_plane_formats), + NULL, DRM_PLANE_TYPE_PRIMARY); + if (ret) { + drm_err(dev, "ast_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + return 0; +} + /* * Cursor plane */ -static const uint32_t ast_cursor_plane_formats[] = { - DRM_FORMAT_ARGB8888, -}; +static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height) +{ + union { + u32 ul; + u8 b[4]; + } srcdata32[2], data32; + union { + u16 us; + u8 b[2]; + } data16; + u32 csum = 0; + s32 alpha_dst_delta, last_alpha_dst_delta; + u8 __iomem *dstxor; + const u8 *srcxor; + int i, j; + u32 per_pixel_copy, two_pixel_copy; + + alpha_dst_delta = AST_MAX_HWC_WIDTH << 1; + last_alpha_dst_delta = alpha_dst_delta - (width << 1); + + srcxor = src; + dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; + per_pixel_copy = width & 1; + two_pixel_copy = width >> 1; + + for (j = 0; j < height; j++) { + for (i = 0; i < two_pixel_copy; i++) { + srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; + srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; + data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); + data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); + data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); + data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); + + writel(data32.ul, dstxor); + csum += data32.ul; + + dstxor += 4; + srcxor += 8; + + } + + for (i = 0; i < per_pixel_copy; i++) { + srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; + data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); + data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); + writew(data16.us, dstxor); + csum += (u32)data16.us; -static int -ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane, - struct drm_plane_state *new_state) + dstxor += 2; + srcxor += 4; + } + dstxor += last_alpha_dst_delta; + } + + /* write checksum + signature */ + dst += AST_HWC_SIZE; + writel(csum, dst); + writel(width, dst + AST_HWC_SIGNATURE_SizeX); + writel(height, dst + AST_HWC_SIGNATURE_SizeY); + writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); + writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); +} + +static void ast_set_cursor_base(struct ast_private *ast, u64 address) { - struct drm_framebuffer *fb = new_state->fb; - struct drm_crtc *crtc = new_state->crtc; - struct ast_private *ast; - int ret; + u8 addr0 = (address >> 3) & 0xff; + u8 addr1 = (address >> 11) & 0xff; + u8 addr2 = (address >> 19) & 0xff; - if (!crtc || !fb) - return 0; + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc8, addr0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc9, addr1); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xca, addr2); +} + +static void ast_set_cursor_location(struct ast_private *ast, u16 x, u16 y, + u8 x_offset, u8 y_offset) +{ + u8 x0 = (x & 0x00ff); + u8 x1 = (x & 0x0f00) >> 8; + u8 y0 = (y & 0x00ff); + u8 y1 = (y & 0x0700) >> 8; + + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc2, x_offset); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc3, y_offset); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc4, x0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc5, x1); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc6, y0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc7, y1); +} - ast = to_ast_private(plane->dev); +static void ast_set_cursor_enabled(struct ast_private *ast, bool enabled) +{ + static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP | + AST_IO_VGACRCB_HWC_ENABLED); - ret = ast_cursor_blit(ast, fb); - if (ret) - return ret; + u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP; - return 0; + if (enabled) + vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED; + + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xcb, mask, vgacrcb); } +static const uint32_t ast_cursor_plane_formats[] = { + DRM_FORMAT_ARGB8888, +}; + static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_atomic_state *state) { - struct drm_framebuffer *fb = state->fb; - struct drm_crtc_state *crtc_state; + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_framebuffer *new_fb = new_plane_state->fb; + struct drm_crtc_state *new_crtc_state; int ret; - if (!state->crtc) + if (!new_plane_state->crtc) return 0; - crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); - ret = drm_atomic_helper_check_plane_state(state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); - if (ret) + if (ret || !new_plane_state->visible) return ret; - if (!state->visible) - return 0; - - if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT) + if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT) return -EINVAL; return 0; } -static void -ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, - struct drm_plane_state *old_state) +static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *state) { - struct drm_plane_state *state = plane->state; - struct drm_framebuffer *fb = state->fb; - struct ast_private *ast = plane->dev->dev_private; + struct ast_plane *ast_plane = to_ast_plane(plane); + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + struct drm_framebuffer *fb = plane_state->fb; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); + struct ast_private *ast = to_ast_private(plane->dev); + struct iosys_map src_map = shadow_plane_state->data[0]; + struct drm_rect damage; + const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */ + u64 dst_off = ast_plane->offset; + u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */ + u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */ unsigned int offset_x, offset_y; + u16 x, y; + u8 x_offset, y_offset; + + /* + * Do data transfer to hardware buffer and point the scanout + * engine to the offset. + */ + + if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) { + ast_update_cursor_image(dst, src, fb->width, fb->height); + ast_set_cursor_base(ast, dst_off); + } + + /* + * Update location in HWC signature and registers. + */ + + writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X); + writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y); offset_x = AST_MAX_HWC_WIDTH - fb->width; - offset_y = AST_MAX_HWC_WIDTH - fb->height; + offset_y = AST_MAX_HWC_HEIGHT - fb->height; - if (state->fb != old_state->fb) { - /* A new cursor image was installed. */ - ast_cursor_page_flip(ast); + if (plane_state->crtc_x < 0) { + x_offset = (-plane_state->crtc_x) + offset_x; + x = 0; + } else { + x_offset = offset_x; + x = plane_state->crtc_x; + } + if (plane_state->crtc_y < 0) { + y_offset = (-plane_state->crtc_y) + offset_y; + y = 0; + } else { + y_offset = offset_y; + y = plane_state->crtc_y; } - ast_cursor_show(ast, state->crtc_x, state->crtc_y, - offset_x, offset_y); + ast_set_cursor_location(ast, x, y, x_offset, y_offset); + + /* Dummy write to enable HWC and make the HW pick-up the changes. */ + ast_set_cursor_enabled(ast, true); } -static void -ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) +static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *state) { struct ast_private *ast = to_ast_private(plane->dev); - ast_cursor_hide(ast); + ast_set_cursor_enabled(ast, false); } static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = { - .prepare_fb = ast_cursor_plane_helper_prepare_fb, - .cleanup_fb = NULL, /* not required for cursor plane */ + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, .atomic_check = ast_cursor_plane_helper_atomic_check, .atomic_update = ast_cursor_plane_helper_atomic_update, .atomic_disable = ast_cursor_plane_helper_atomic_disable, @@ -752,11 +933,48 @@ static const struct drm_plane_funcs ast_cursor_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, .destroy = drm_plane_cleanup, - .reset = drm_atomic_helper_plane_reset, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + DRM_GEM_SHADOW_PLANE_FUNCS, }; +static int ast_cursor_plane_init(struct ast_private *ast) +{ + struct drm_device *dev = &ast->base; + struct ast_plane *ast_cursor_plane = &ast->cursor_plane; + struct drm_plane *cursor_plane = &ast_cursor_plane->base; + size_t size; + void __iomem *vaddr; + u64 offset; + int ret; + + /* + * Allocate backing storage for cursors. The BOs are permanently + * pinned to the top end of the VRAM. + */ + + size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); + + if (ast->vram_fb_available < size) + return -ENOMEM; + + vaddr = ast->vram + ast->vram_fb_available - size; + offset = ast->vram_fb_available - size; + + ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size, + 0x01, &ast_cursor_plane_funcs, + ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats), + NULL, DRM_PLANE_TYPE_CURSOR); + if (ret) { + drm_err(dev, "ast_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(cursor_plane); + + ast->vram_fb_available -= size; + + return 0; +} + /* * CRTC */ @@ -774,8 +992,8 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) */ switch (mode) { case DRM_MODE_DPMS_ON: - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, 0); + ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0x00); if (ast->tx_chip_type == AST_TX_DP501) ast_set_dp501_video_output(crtc->dev, 1); @@ -809,30 +1027,99 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF); } - ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0x20); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch); + ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0x20); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, ch); + break; + } +} + +static enum drm_mode_status +ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) +{ + struct ast_private *ast = to_ast_private(crtc->dev); + int flags = MODE_NOMODE; + + switch (mode->hdisplay) { + case 640: + if (mode->vdisplay == 480) + flags = MODE_OK; + break; + case 800: + if (mode->vdisplay == 600) + flags = MODE_OK; + break; + case 1024: + if (mode->vdisplay == 768) + flags = MODE_OK; + break; + case 1152: + if (mode->vdisplay == 864) + flags = MODE_OK; + break; + case 1280: + if (mode->vdisplay == 1024) + flags = MODE_OK; + else if (mode->vdisplay == 800) + flags = MODE_OK; + else if (mode->vdisplay == 720 || mode->vdisplay == 960) + flags = MODE_OK; + break; + case 1360: + if (mode->vdisplay == 768) + flags = MODE_OK; + break; + case 1440: + if (mode->vdisplay == 900) + flags = MODE_OK; + break; + case 1600: + if (mode->vdisplay == 1200) + flags = MODE_OK; + else if (mode->vdisplay == 900) + flags = MODE_OK; + break; + case 1680: + if (mode->vdisplay == 1050) + flags = MODE_OK; + break; + case 1920: + if ((ast->chip == AST2100) || // GEN2, but not AST1100 (?) + (ast->chip == AST2200) || // GEN3, but not AST2150 (?) + IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || + IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) { + if (mode->vdisplay == 1080) + flags = MODE_OK; + else if (mode->vdisplay == 1200) + flags = MODE_OK; + } break; + default: + return flags; } + + return flags; } static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, - struct drm_crtc_state *state) + struct drm_atomic_state *state) { + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + struct drm_device *dev = crtc->dev; struct ast_crtc_state *ast_state; const struct drm_format_info *format; bool succ; - if (!state->enable) + if (!crtc_state->enable) return 0; /* no mode checks if CRTC is being disabled */ - ast_state = to_ast_crtc_state(state); + ast_state = to_ast_crtc_state(crtc_state); format = ast_state->format; - if (!format) - return 0; + if (drm_WARN_ON_ONCE(dev, !format)) + return -EINVAL; /* BUG: We didn't set format in primary check(). */ - succ = ast_get_vbios_mode_info(format, &state->mode, - &state->adjusted_mode, + succ = ast_get_vbios_mode_info(format, &crtc_state->mode, + &crtc_state->adjusted_mode, &ast_state->vbios_mode_info); if (!succ) return -EINVAL; @@ -840,19 +1127,16 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, return 0; } -static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) -{ - struct ast_private *ast = to_ast_private(crtc->dev); - - ast_open_key(ast); -} - -static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) +static void +ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *state) { + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, + crtc); + struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, + crtc); struct ast_private *ast = to_ast_private(crtc->dev); - struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc->state); + struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state); /* @@ -863,39 +1147,36 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, ast_crtc_load_lut(ast, crtc); } -static void -ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) +static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) { struct drm_device *dev = crtc->dev; struct ast_private *ast = to_ast_private(dev); - struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc->state); + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; - struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; - ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06); ast_set_std_reg(ast, adjusted_mode, vbios_mode_info); + ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info); ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info); ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info); ast_set_crtthd_reg(ast); ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info); //Set Aspeed Display-Port - if (ast->tx_chip_type == AST_TX_ASTDP){ + if (ast->tx_chip_type == AST_TX_ASTDP) ast_dp_set_mode(crtc, vbios_mode_info); - }else if (ast->tx_chip_type == AST_TX_ITE66121){ - ast_hdmi_set_output(dev); - } ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON); } -static void -ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) +static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *state) { + struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); struct drm_device *dev = crtc->dev; struct ast_private *ast = to_ast_private(dev); @@ -921,8 +1202,8 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { + .mode_valid = ast_crtc_helper_mode_valid, .atomic_check = ast_crtc_helper_atomic_check, - .atomic_begin = ast_crtc_helper_atomic_begin, .atomic_flush = ast_crtc_helper_atomic_flush, .atomic_enable = ast_crtc_helper_atomic_enable, .atomic_disable = ast_crtc_helper_atomic_disable, @@ -939,12 +1220,6 @@ static void ast_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, &ast_state->base); } -static void ast_crtc_destroy(struct drm_crtc *crtc) -{ - drm_crtc_cleanup(crtc); - kfree(crtc); -} - static struct drm_crtc_state * ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { @@ -979,8 +1254,7 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc, static const struct drm_crtc_funcs ast_crtc_funcs = { .reset = ast_crtc_reset, - .gamma_set = drm_atomic_helper_legacy_gamma_set, - .destroy = ast_crtc_destroy, + .destroy = drm_crtc_cleanup, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, .atomic_duplicate_state = ast_crtc_atomic_duplicate_state, @@ -990,28 +1264,21 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_private *ast = to_ast_private(dev); - struct drm_crtc *crtc; + struct drm_crtc *crtc = &ast->crtc; int ret; - crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); - if (!crtc) - return -ENOMEM; - - ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane, - &ast->cursor_plane, &ast_crtc_funcs, + ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base, + &ast->cursor_plane.base, &ast_crtc_funcs, NULL); if (ret) - goto err_kfree; + return ret; + + drm_mode_crtc_set_gamma_size(crtc, AST_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, AST_LUT_SIZE); - drm_crtc_enable_color_mgmt(crtc, 0, false, MAX_COLOR_LUT_ENTRIES); - drm_mode_crtc_set_gamma_size(crtc, MAX_COLOR_LUT_ENTRIES); drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs); return 0; - -err_kfree: - kfree(crtc); - return ret; } /* @@ -1037,10 +1304,33 @@ static int ast_encoder_init(struct drm_device *dev) * Connector */ +/* This helper function which reports connector_status. + * If we want VGA on/off with KVM, status depends on scratch reg D0[1]. + * Otherwise, status is always connected. + * + */ +static int aspeed_detect(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, bool force) +{ + struct ast_private *ast = to_ast_private(connector->dev); + int status = connector_status_disconnected; + + if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD4, BIT(0))) + return connector_status_connected; + + if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD4, BIT(1))) + status = connector_status_connected; + + drm_dbg_kms(&ast->base, "[CONNECTOR:%d:%s] force=%d status=%d\n", + connector->base.id, connector->name, force, status); + return status; +} + static int ast_get_modes(struct drm_connector *connector) { struct ast_connector *ast_connector = to_ast_connector(connector); struct ast_private *ast = to_ast_private(connector->dev); + struct pci_dev *pdev = to_pci_dev(ast->base.dev); struct edid *edid; int ret; int flags = -1; @@ -1055,12 +1345,10 @@ static int ast_get_modes(struct drm_connector *connector) flags = -1; kfree(edid); } - } else if (ast->tx_chip_type == AST_TX_ITE66121) { - ast_hdmi_read_edid(connector->dev, (u8 *)edid); } else if (ast->tx_chip_type == AST_TX_ASTDP) { - mutex_lock(&ast->ioregs_lock); + mutex_lock(&ast->modeset_lock); flags = ast_astdp_read_edid(connector->dev, (u8 *)edid); - mutex_unlock(&ast->ioregs_lock); + mutex_unlock(&ast->modeset_lock); if (flags < 0) { drm_info(connector->dev, "No DP EDID\n"); kfree(edid); @@ -1068,9 +1356,25 @@ static int ast_get_modes(struct drm_connector *connector) } if (flags < 0) { - mutex_lock(&ast->ioregs_lock); - edid = drm_get_edid(connector, &ast_connector->i2c->adapter); - mutex_unlock(&ast->ioregs_lock); + if (pdev->revision == 0x70 && + ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD4, BIT(2))) { + edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (!edid) + return -ENOMEM; + + mutex_lock(&ast->modeset_lock); + flags = ast_vga_read_edid(connector->dev, (u8 *)edid); + mutex_unlock(&ast->modeset_lock); + + if (flags < 0) { + drm_info(connector->dev, "No VGA EDID\n"); + kfree(edid); + } + } else { + mutex_lock(&ast->modeset_lock); + edid = drm_get_edid(connector, &ast_connector->i2c->adapter); + mutex_unlock(&ast->modeset_lock); + } } if (edid) { drm_connector_update_edid_property(&ast_connector->base, edid); @@ -1082,104 +1386,26 @@ static int ast_get_modes(struct drm_connector *connector) return 0; } -static enum drm_mode_status ast_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct ast_private *ast = to_ast_private(connector->dev); - int flags = MODE_NOMODE; - - switch (mode->hdisplay) { - case 640: - if (mode->vdisplay == 480) - flags = MODE_OK; - break; - case 800: - if (mode->vdisplay == 600) - flags = MODE_OK; - break; - case 1024: - if (mode->vdisplay == 768) - flags = MODE_OK; - break; - case 1152: - if (mode->vdisplay == 864) - flags = MODE_OK; - break; - case 1280: - if (mode->vdisplay == 1024) - flags = MODE_OK; - else if (mode->vdisplay == 800) - flags = MODE_OK; - else if (mode->vdisplay == 720 || mode->vdisplay == 960) - flags = MODE_OK; - break; - case 1360: - if (mode->vdisplay == 768) - flags = MODE_OK; - break; - case 1440: - if (mode->vdisplay == 900) - flags = MODE_OK; - break; - case 1600: - if (mode->vdisplay == 1200) - flags = MODE_OK; - else if (mode->vdisplay == 900) - flags = MODE_OK; - break; - case 1680: - if (mode->vdisplay == 1050) - flags = MODE_OK; - break; - case 1920: - if (ast->chip == AST2100 || ast->chip == AST2200 || - ast->chip == AST2300 || ast->chip == AST2400 || - ast->chip == AST2500 || ast->chip == AST2600) { - if (mode->vdisplay == 1080) - flags = MODE_OK; - else if (mode->vdisplay == 1200) - flags = MODE_OK; - } - break; - default: - return flags; - } - - return flags; -} - -static void ast_connector_destroy(struct drm_connector *connector) -{ - struct ast_connector *ast_connector = to_ast_connector(connector); - ast_i2c_destroy(ast_connector->i2c); - drm_connector_cleanup(connector); - kfree(connector); -} - static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { + .detect_ctx = aspeed_detect, .get_modes = ast_get_modes, - .mode_valid = ast_mode_valid, }; static const struct drm_connector_funcs ast_connector_funcs = { .reset = drm_atomic_helper_connector_reset, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = ast_connector_destroy, + .destroy = drm_connector_cleanup, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; static int ast_connector_init(struct drm_device *dev) { - struct ast_connector *ast_connector; - struct drm_connector *connector; - struct drm_encoder *encoder; - - ast_connector = kzalloc(sizeof(struct ast_connector), GFP_KERNEL); - if (!ast_connector) - return -ENOMEM; + struct ast_private *ast = to_ast_private(dev); + struct ast_connector *ast_connector = &ast->connector; + struct drm_connector *connector = &ast_connector->base; + struct drm_encoder *encoder = &ast->encoder; - connector = &ast_connector->base; ast_connector->i2c = ast_i2c_create(dev); if (!ast_connector->i2c) drm_err(dev, "failed to add ddc bus for connector\n"); @@ -1194,9 +1420,8 @@ static int ast_connector_init(struct drm_device *dev) connector->interlace_allowed = 0; connector->doublescan_allowed = 0; - connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head); drm_connector_attach_encoder(connector, encoder); return 0; @@ -1209,29 +1434,46 @@ static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *s { struct ast_private *ast = to_ast_private(state->dev); - mutex_lock(&ast->ioregs_lock); + mutex_lock(&ast->modeset_lock); drm_atomic_helper_commit_tail_rpm(state); - mutex_unlock(&ast->ioregs_lock); + mutex_unlock(&ast->modeset_lock); } -static const struct drm_mode_config_helper_funcs -ast_mode_config_helper_funcs = { +static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = { .atomic_commit_tail = ast_mode_config_helper_atomic_commit_tail, }; +static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev, + const struct drm_display_mode *mode) +{ + static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */ + struct ast_private *ast = to_ast_private(dev); + unsigned long fbsize, fbpages, max_fbpages; + + max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT; + + fbsize = mode->hdisplay * mode->vdisplay * max_bpp; + fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE); + + if (fbpages > max_fbpages) + return MODE_MEM; + + return MODE_OK; +} + static const struct drm_mode_config_funcs ast_mode_config_funcs = { - .fb_create = drm_gem_fb_create, - .mode_valid = drm_vram_helper_mode_valid, + .fb_create = drm_gem_fb_create_with_dirty, + .mode_valid = ast_mode_config_mode_valid, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, }; int ast_mode_config_init(struct ast_private *ast) { - struct drm_device *dev = ast->dev; + struct drm_device *dev = &ast->base; int ret; - ret = ast_cursor_init(ast); + ret = drmm_mutex_init(dev, &ast->modeset_lock); if (ret) return ret; @@ -1245,8 +1487,12 @@ int ast_mode_config_init(struct ast_private *ast) dev->mode_config.preferred_depth = 24; dev->mode_config.prefer_shadow = 1; - if (ast->chip == AST2100 || ast->chip == AST2200 || ast->chip == AST2300 || ast->chip == AST2400 - || ast->chip == AST2500 || ast->chip == AST2600) { + if (ast->chip == AST2100 || // GEN2, but not AST1100 (?) + ast->chip == AST2200 || // GEN3, but not AST2150 (?) + IS_AST_GEN7(ast) || + IS_AST_GEN6(ast) || + IS_AST_GEN5(ast) || + IS_AST_GEN4(ast)) { dev->mode_config.max_width = 1920; dev->mode_config.max_height = 2048; } else { @@ -1256,30 +1502,13 @@ int ast_mode_config_init(struct ast_private *ast) dev->mode_config.helper_private = &ast_mode_config_helper_funcs; - memset(&ast->primary_plane, 0, sizeof(ast->primary_plane)); - ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01, - &ast_primary_plane_funcs, - ast_primary_plane_formats, - ARRAY_SIZE(ast_primary_plane_formats), - NULL, DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) { - drm_err(dev, "ast: drm_universal_plane_init() failed: %d\n", ret); + ret = ast_primary_plane_init(ast); + if (ret) return ret; - } - drm_plane_helper_add(&ast->primary_plane, - &ast_primary_plane_helper_funcs); - - ret = drm_universal_plane_init(dev, &ast->cursor_plane, 0x01, - &ast_cursor_plane_funcs, - ast_cursor_plane_formats, - ARRAY_SIZE(ast_cursor_plane_formats), - NULL, DRM_PLANE_TYPE_CURSOR, NULL); - if (ret) { - drm_err(dev, "drm_universal_plane_failed(): %d\n", ret); + + ret = ast_cursor_plane_init(ast); + if (ret) return ret; - } - drm_plane_helper_add(&ast->cursor_plane, - &ast_cursor_plane_helper_funcs); ast_crtc_init(dev); ast_encoder_init(dev); @@ -1287,126 +1516,10 @@ int ast_mode_config_init(struct ast_private *ast) drm_mode_config_reset(dev); - return 0; -} - -static int get_clock(void *i2c_priv) -{ - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = to_ast_private(i2c->dev); - uint32_t val, val2, count, pass; - - count = 0; - pass = 0; - val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; - do { - val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; - if (val == val2) { - pass++; - } else { - pass = 0; - val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; - } - } while ((pass < 5) && (count++ < 0x10000)); - - return val & 1 ? 1 : 0; -} - -static int get_data(void *i2c_priv) -{ - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = to_ast_private(i2c->dev); - uint32_t val, val2, count, pass; - - count = 0; - pass = 0; - val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; - do { - val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; - if (val == val2) { - pass++; - } else { - pass = 0; - val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; - } - } while ((pass < 5) && (count++ < 0x10000)); - - return val & 1 ? 1 : 0; -} - -static void set_clock(void *i2c_priv, int clock) -{ - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = to_ast_private(i2c->dev); - int i; - u8 ujcrb7, jtemp; - - for (i = 0; i < 0x10000; i++) { - ujcrb7 = ((clock & 0x01) ? 0 : 1); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7); - jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01); - if (ujcrb7 == jtemp) - break; - } -} - -static void set_data(void *i2c_priv, int data) -{ - struct ast_i2c_chan *i2c = i2c_priv; - struct ast_private *ast = to_ast_private(i2c->dev); - int i; - u8 ujcrb7, jtemp; - - for (i = 0; i < 0x10000; i++) { - ujcrb7 = ((data & 0x01) ? 0 : 1) << 2; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7); - jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04); - if (ujcrb7 == jtemp) - break; - } -} - -static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev) -{ - struct ast_i2c_chan *i2c; - int ret; - - i2c = kzalloc(sizeof(struct ast_i2c_chan), GFP_KERNEL); - if (!i2c) - return NULL; - - i2c->adapter.owner = THIS_MODULE; - i2c->adapter.class = I2C_CLASS_DDC; - i2c->adapter.dev.parent = &dev->pdev->dev; - i2c->dev = dev; - i2c_set_adapdata(&i2c->adapter, i2c); - snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), - "AST i2c bit bus"); - i2c->adapter.algo_data = &i2c->bit; - - i2c->bit.udelay = 20; - i2c->bit.timeout = 2; - i2c->bit.data = i2c; - i2c->bit.setsda = set_data; - i2c->bit.setscl = set_clock; - i2c->bit.getsda = get_data; - i2c->bit.getscl = get_clock; - ret = i2c_bit_add_bus(&i2c->adapter); - if (ret) { - drm_err(dev, "Failed to register bit i2c\n"); - goto out_free; - } + // enable poll if we want VGA on/off with KVM. + if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD4, BIT(0))) + drm_kms_helper_poll_init(dev); - return i2c; -out_free: - kfree(i2c); - return NULL; + return 0; } -static void ast_i2c_destroy(struct ast_i2c_chan *i2c) -{ - if (!i2c) - return; - i2c_del_adapter(&i2c->adapter); - kfree(i2c); -} diff --git a/src/ast_post.c b/src/ast_post.c index bd45e51..f9e9f7c 100644 --- a/src/ast_post.c +++ b/src/ast_post.c @@ -37,23 +37,23 @@ void ast_enable_vga(struct drm_device *dev) struct ast_private *ast = to_ast_private(dev); u8 ch; - ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01); - ch = ast_io_read8(ast, AST_IO_MISC_PORT_READ); - ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, ch | 0x01); + ast_io_write8(ast, AST_IO_VGAER, AST_IO_VGAER_VGA_ENABLE); + ch = ast_io_read8(ast, AST_IO_VGAMR_R); + ast_io_write8(ast, AST_IO_VGAMR_W, ch | AST_IO_VGAMR_IOSEL); } void ast_disable_vga(struct drm_device *dev) { struct ast_private *ast = to_ast_private(dev); - ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x0); + ast_io_write8(ast, AST_IO_VGAER, 0x0); } void ast_enable_mmio(struct drm_device *dev) { struct ast_private *ast = to_ast_private(dev); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06); } @@ -62,9 +62,9 @@ bool ast_is_vga_enabled(struct drm_device *dev) struct ast_private *ast = to_ast_private(dev); u8 ch; - ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT); + ch = ast_io_read8(ast, AST_IO_VGAER); - return !!(ch & 0x01); + return ch & AST_IO_VGAER_VGA_ENABLE; } static const u8 extreginfo[] = { 0x7f, 0x06, 0x1c, 0xff }; @@ -79,34 +79,34 @@ ast_set_def_ext_reg(struct drm_device *dev) /* reset scratch */ for (i = 0x81; i <= 0x9f; i++) - ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00); + ast_set_index_reg(ast, AST_IO_VGACRI, i, 0x00); - if (ast->chip == AST2300 || ast->chip == AST2400 || - ast->chip == AST2500 || ast->chip == AST2600) { + if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast) || + IS_AST_GEN7(ast)) { ext_reg_info = extreginfo_ast2300; } else ext_reg_info = extreginfo; index = 0xa0; while (*ext_reg_info != 0xff) { - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, index, 0x00, *ext_reg_info); index++; ext_reg_info++; } /* disable standard IO/MEM decode if secondary */ - /* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */ + /* ast_set_index_reg-mask(ast, AST_IO_VGACRI, 0xa1, 0xff, 0x3); */ /* Set Ext. Default */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x8c, 0x00, 0x01); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x00, 0x00); /* Enable RAMDAC for A1 */ reg = 0x04; - if (ast->chip == AST2300 || ast->chip == AST2400 || - ast->chip == AST2500 || ast->chip == AST2600) + if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast) || + IS_AST_GEN7(ast)) reg |= 0x20; - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg); + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xff, reg); } void ast_post_gpu(struct drm_device *dev) @@ -117,19 +117,19 @@ void ast_post_gpu(struct drm_device *dev) ast_open_key(ast); ast_enable_mmio(dev); ast_set_def_ext_reg(dev); - ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x0b); - ast_set_index_reg(ast, AST_IO_GR_PORT, 6, 0x05); + ast_io_write8(ast, AST_IO_VGAMR_W, 0x0b); + ast_set_index_reg(ast, AST_IO_VGAGRI, 6, 0x05); - if (ast->chip == AST2600) { + if (IS_AST_GEN7(ast)) { if (ast->tx_chip_type == AST_TX_ASTDP) ast_dp_launch(dev); } else if (ast->config_mode == ast_use_p2a) { - if (ast->chip == AST2500) + if (IS_AST_GEN6(ast)) ast_post_chip_2500(dev); ast_init_3rdtx(dev); } else { if (ast->tx_chip_type != AST_TX_NONE) - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */ + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); /* Enable DVO */ } } diff --git a/src/ast_reg.h b/src/ast_reg.h new file mode 100644 index 0000000..40fcff7 --- /dev/null +++ b/src/ast_reg.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __AST_REG_H__ +#define __AST_REG_H__ + +#include + +/* + * Modesetting + */ + +#define AST_IO_MM_OFFSET (0x380) +#define AST_IO_MM_LENGTH (128) + +#define AST_IO_VGAARI_W (0x40) + +#define AST_IO_VGAMR_W (0x42) +#define AST_IO_VGAMR_R (0x4c) +#define AST_IO_VGAMR_IOSEL BIT(0) + +#define AST_IO_VGAER (0x43) +#define AST_IO_VGAER_VGA_ENABLE BIT(0) + +#define AST_IO_VGASRI (0x44) +#define AST_IO_VGADRR (0x47) +#define AST_IO_VGADWR (0x48) +#define AST_IO_VGAPDR (0x49) +#define AST_IO_VGAGRI (0x4E) + +#define AST_IO_VGACRI (0x54) +#define AST_IO_VGACR80_PASSWORD (0xa8) +#define AST_IO_VGACRA1_VGAIO_DISABLED BIT(1) +#define AST_IO_VGACRA1_MMIO_ENABLED BIT(2) +#define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ +#define AST_IO_VGACRCB_HWC_ENABLED BIT(1) + +#define AST_IO_VGAIR1_R (0x5A) +#define AST_IO_VGAIR1_VREFRESH BIT(3) + +/* + * Display Transmitter Type + */ + +#define TX_TYPE_MASK GENMASK(3, 1) +#define NO_TX (0 << 1) +#define ITE66121_VBIOS_TX (1 << 1) +#define SI164_VBIOS_TX (2 << 1) +#define CH7003_VBIOS_TX (3 << 1) +#define DP501_VBIOS_TX (4 << 1) +#define ANX9807_VBIOS_TX (5 << 1) +#define TX_FW_EMBEDDED_FW_TX (6 << 1) +#define ASTDP_DPMCU_TX (7 << 1) + +#define AST_VRAM_INIT_STATUS_MASK GENMASK(7, 6) +//#define AST_VRAM_INIT_BY_BMC BIT(7) +//#define AST_VRAM_INIT_READY BIT(6) + +/* + * AST DisplayPort + */ + +/* Define for Soc scratched reg used on ASTDP */ +#define AST_DP_PHY_SLEEP BIT(4) +#define AST_DP_VIDEO_ENABLE BIT(0) + +/* + * CRD0[b2]: V-PLL reference clock(0b:24MHz, 1b:25MHz) + * CRD1[b5]: DP MCU FW is executing + * CRDC[b0]: DP link success + * CRDF[b0]: DP HPD + * CRE5[b0]: Host reading EDID process is done + */ +#define AST_VPLL_REF_CLOCK_25M BIT(2) +#define ASTDP_MCU_FW_EXECUTING BIT(5) +#define ASTDP_LINK_SUCCESS BIT(0) +#define ASTDP_HPD BIT(0) +#define ASTDP_HOST_EDID_READ_DONE BIT(0) +#define ASTDP_HOST_EDID_READ_DONE_MASK GENMASK(0, 0) + +/* + * CRB8[b1]: Enable VSYNC off + * CRB8[b0]: Enable HSYNC off + */ +#define AST_DPMS_VSYNC_OFF BIT(1) +#define AST_DPMS_HSYNC_OFF BIT(0) + +/* + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE + * Precondition: A. ~AST_DP_PHY_SLEEP && + * B. DP_HPD && + * C. DP_LINK_SUCCESS + */ +#define ASTDP_MIRROR_VIDEO_ENABLE BIT(4) + +#define ASTDP_EDID_READ_POINTER_MASK GENMASK(7, 0) +#define ASTDP_EDID_VALID_FLAG_MASK GENMASK(0, 0) +#define ASTDP_EDID_READ_DATA_MASK GENMASK(7, 0) + +/* + * ASTDP setmode registers: + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp) + * CRE1[7:0]: MISC1 (default: 0x00) + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x53) + */ +#define ASTDP_MISC0_24bpp BIT(5) +#define ASTDP_MISC1 0 +#define ASTDP_AND_CLEAR_MASK 0x00 + +/* + * ASTDP resoultion table used in CRE2: + * EX: ASTDP_A_B_C: + * A: Resolution + * B: Refresh Rate + * C: Misc information, such as CVT, Reduce Blanked + */ +#define ASTDP_640x480_60 0x00 +#define ASTDP_640x480_72 0x01 +#define ASTDP_640x480_75 0x02 +#define ASTDP_640x480_85 0x03 +#define ASTDP_800x600_56 0x04 +#define ASTDP_800x600_60 0x05 +#define ASTDP_800x600_72 0x06 +#define ASTDP_800x600_75 0x07 +#define ASTDP_800x600_85 0x08 +#define ASTDP_1024x768_60 0x09 +#define ASTDP_1024x768_70 0x0A +#define ASTDP_1024x768_75 0x0B +#define ASTDP_1024x768_85 0x0C +#define ASTDP_1280x1024_60 0x0D +#define ASTDP_1280x1024_75 0x0E +#define ASTDP_1280x1024_85 0x0F +#define ASTDP_1600x1200_60 0x10 +#define ASTDP_320x240_60 0x11 +#define ASTDP_400x300_60 0x12 +#define ASTDP_512x384_60 0x13 +#define ASTDP_1920x1200_60 0x14 +#define ASTDP_1920x1080_60 0x15 +#define ASTDP_1280x800_60 0x16 +#define ASTDP_1280x800_60_RB 0x17 +#define ASTDP_1440x900_60 0x18 +#define ASTDP_1440x900_60_RB 0x19 +#define ASTDP_1680x1050_60 0x1A +#define ASTDP_1680x1050_60_RB 0x1B +#define ASTDP_1600x900_60 0x1C +#define ASTDP_1600x900_60_RB 0x1D +#define ASTDP_1366x768_60 0x1E +#define ASTDP_1152x864_75 0x1F +#define ASTDP_1600x900_60_DMT 0x51 +#define ASTDP_1280x720_60 0x52 +#define ASTDP_1280x960_60 0x53 + +#endif diff --git a/src/ast_tables.h b/src/ast_tables.h index c40a56b..8d55fc8 100644 --- a/src/ast_tables.h +++ b/src/ast_tables.h @@ -315,9 +315,9 @@ static const struct ast_vbios_enhtable res_1024x768[] = { }; static const struct ast_vbios_enhtable res_1280x960[] = { - {1800, 1280, 12, 14, 1000, 960, 1, 3, VCLK108, /* 60Hz */ + {1800, 1280, 96, 112, 1000, 960, 1, 3, VCLK108, /* 60Hz */ (SyncPP | Charx8Dot), 60, 1, 0x3E }, - {1800, 1280, 12, 14, 1000, 960, 1, 3, VCLK108, /* end */ + {1800, 1280, 96, 112, 1000, 960, 1, 3, VCLK108, /* end */ (SyncPP | Charx8Dot), 0xFF, 1, 0x3E }, }; -- Gitee