brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · d836f2a Raw
309 lines · c
1/*2 * Copyright 2012 Red Hat Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the6 * "Software"), to deal in the Software without restriction, including7 * without limitation the rights to use, copy, modify, merge, publish,8 * distribute, sub license, and/or sell copies of the Software, and to9 * permit persons to whom the Software is furnished to do so, subject to10 * the following conditions:11 *12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE18 * USE OR OTHER DEALINGS IN THE SOFTWARE.19 *20 * The above copyright notice and this permission notice (including the21 * next paragraph) shall be included in all copies or substantial portions22 * of the Software.23 *24 */25/*26 * Authors: Dave Airlie <airlied@redhat.com>27 */28 29#include <linux/of.h>30#include <linux/pci.h>31 32#include <drm/drm_atomic_helper.h>33#include <drm/drm_drv.h>34#include <drm/drm_gem.h>35#include <drm/drm_managed.h>36 37#include "ast_drv.h"38 39static void ast_detect_widescreen(struct ast_device *ast)40{41	u8 jreg;42 43	/* Check if we support wide screen */44	switch (AST_GEN(ast)) {45	case 1:46		ast->support_wide_screen = false;47		break;48	default:49		jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);50		if (!(jreg & 0x80))51			ast->support_wide_screen = true;52		else if (jreg & 0x01)53			ast->support_wide_screen = true;54		else {55			ast->support_wide_screen = false;56			if (ast->chip == AST1300)57				ast->support_wide_screen = true;58			if (ast->chip == AST1400)59				ast->support_wide_screen = true;60			if (ast->chip == AST2510)61				ast->support_wide_screen = true;62			if (IS_AST_GEN7(ast))63				ast->support_wide_screen = true;64		}65		break;66	}67}68 69static void ast_detect_tx_chip(struct ast_device *ast, bool need_post)70{71	struct drm_device *dev = &ast->base;72	u8 jreg;73 74	/* Check 3rd Tx option (digital output afaik) */75	ast->tx_chip_types |= AST_TX_NONE_BIT;76 77	/*78	 * VGACRA3 Enhanced Color Mode Register, check if DVO is already79	 * enabled, in that case, assume we have a SIL164 TMDS transmitter80	 *81	 * Don't make that assumption if we the chip wasn't enabled and82	 * is at power-on reset, otherwise we'll incorrectly "detect" a83	 * SIL164 when there is none.84	 */85	if (!need_post) {86		jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff);87		if (jreg & 0x80)88			ast->tx_chip_types = AST_TX_SIL164_BIT;89	}90 91	if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) {92		/*93		 * On AST GEN4+, look the configuration set by the SoC in94		 * the SOC scratch register #1 bits 11:8 (interestingly marked95		 * as "reserved" in the spec)96		 */97		jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff);98		switch (jreg) {99		case 0x04:100			ast->tx_chip_types = AST_TX_SIL164_BIT;101			break;102		case 0x08:103			ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL);104			if (ast->dp501_fw_addr) {105				/* backup firmware */106				if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) {107					drmm_kfree(dev, ast->dp501_fw_addr);108					ast->dp501_fw_addr = NULL;109				}110			}111			fallthrough;112		case 0x0c:113			ast->tx_chip_types = AST_TX_DP501_BIT;114		}115	} else if (IS_AST_GEN7(ast)) {116		if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, TX_TYPE_MASK) ==117		    ASTDP_DPMCU_TX) {118			int ret = ast_dp_launch(ast);119 120			if (!ret)121				ast->tx_chip_types = AST_TX_ASTDP_BIT;122		}123	}124 125	/* Print stuff for diagnostic purposes */126	if (ast->tx_chip_types & AST_TX_NONE_BIT)127		drm_info(dev, "Using analog VGA\n");128	if (ast->tx_chip_types & AST_TX_SIL164_BIT)129		drm_info(dev, "Using Sil164 TMDS transmitter\n");130	if (ast->tx_chip_types & AST_TX_DP501_BIT)131		drm_info(dev, "Using DP501 DisplayPort transmitter\n");132	if (ast->tx_chip_types & AST_TX_ASTDP_BIT)133		drm_info(dev, "Using ASPEED DisplayPort transmitter\n");134}135 136static int ast_get_dram_info(struct drm_device *dev)137{138	struct device_node *np = dev->dev->of_node;139	struct ast_device *ast = to_ast_device(dev);140	uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;141	uint32_t denum, num, div, ref_pll, dsel;142 143	switch (ast->config_mode) {144	case ast_use_dt:145		/*146		 * If some properties are missing, use reasonable147		 * defaults for GEN5148		 */149		if (of_property_read_u32(np, "aspeed,mcr-configuration",150					 &mcr_cfg))151			mcr_cfg = 0x00000577;152		if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",153					 &mcr_scu_mpll))154			mcr_scu_mpll = 0x000050C0;155		if (of_property_read_u32(np, "aspeed,mcr-scu-strap",156					 &mcr_scu_strap))157			mcr_scu_strap = 0;158		break;159	case ast_use_p2a:160		ast_write32(ast, 0xf004, 0x1e6e0000);161		ast_write32(ast, 0xf000, 0x1);162		mcr_cfg = ast_read32(ast, 0x10004);163		mcr_scu_mpll = ast_read32(ast, 0x10120);164		mcr_scu_strap = ast_read32(ast, 0x10170);165		break;166	case ast_use_defaults:167	default:168		ast->dram_bus_width = 16;169		ast->dram_type = AST_DRAM_1Gx16;170		if (IS_AST_GEN6(ast))171			ast->mclk = 800;172		else173			ast->mclk = 396;174		return 0;175	}176 177	if (mcr_cfg & 0x40)178		ast->dram_bus_width = 16;179	else180		ast->dram_bus_width = 32;181 182	if (IS_AST_GEN6(ast)) {183		switch (mcr_cfg & 0x03) {184		case 0:185			ast->dram_type = AST_DRAM_1Gx16;186			break;187		default:188		case 1:189			ast->dram_type = AST_DRAM_2Gx16;190			break;191		case 2:192			ast->dram_type = AST_DRAM_4Gx16;193			break;194		case 3:195			ast->dram_type = AST_DRAM_8Gx16;196			break;197		}198	} else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) {199		switch (mcr_cfg & 0x03) {200		case 0:201			ast->dram_type = AST_DRAM_512Mx16;202			break;203		default:204		case 1:205			ast->dram_type = AST_DRAM_1Gx16;206			break;207		case 2:208			ast->dram_type = AST_DRAM_2Gx16;209			break;210		case 3:211			ast->dram_type = AST_DRAM_4Gx16;212			break;213		}214	} else {215		switch (mcr_cfg & 0x0c) {216		case 0:217		case 4:218			ast->dram_type = AST_DRAM_512Mx16;219			break;220		case 8:221			if (mcr_cfg & 0x40)222				ast->dram_type = AST_DRAM_1Gx16;223			else224				ast->dram_type = AST_DRAM_512Mx32;225			break;226		case 0xc:227			ast->dram_type = AST_DRAM_1Gx32;228			break;229		}230	}231 232	if (mcr_scu_strap & 0x2000)233		ref_pll = 14318;234	else235		ref_pll = 12000;236 237	denum = mcr_scu_mpll & 0x1f;238	num = (mcr_scu_mpll & 0x3fe0) >> 5;239	dsel = (mcr_scu_mpll & 0xc000) >> 14;240	switch (dsel) {241	case 3:242		div = 0x4;243		break;244	case 2:245	case 1:246		div = 0x2;247		break;248	default:249		div = 0x1;250		break;251	}252	ast->mclk = ref_pll * (num + 2) / ((denum + 2) * (div * 1000));253	return 0;254}255 256struct drm_device *ast_device_create(struct pci_dev *pdev,257				     const struct drm_driver *drv,258				     enum ast_chip chip,259				     enum ast_config_mode config_mode,260				     void __iomem *regs,261				     void __iomem *ioregs,262				     bool need_post)263{264	struct drm_device *dev;265	struct ast_device *ast;266	int ret;267 268	ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);269	if (IS_ERR(ast))270		return ERR_CAST(ast);271	dev = &ast->base;272 273	ast->chip = chip;274	ast->config_mode = config_mode;275	ast->regs = regs;276	ast->ioregs = ioregs;277 278	ast_detect_widescreen(ast);279	ast_detect_tx_chip(ast, need_post);280 281	ret = ast_get_dram_info(dev);282	if (ret)283		return ERR_PTR(ret);284 285	drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n",286		 ast->mclk, ast->dram_type, ast->dram_bus_width);287 288	if (need_post)289		ast_post_gpu(dev);290 291	ret = ast_mm_init(ast);292	if (ret)293		return ERR_PTR(ret);294 295	/* map reserved buffer */296	ast->dp501_fw_buf = NULL;297	if (ast->vram_size < pci_resource_len(pdev, 0)) {298		ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0);299		if (!ast->dp501_fw_buf)300			drm_info(dev, "failed to map reserved buffer!\n");301	}302 303	ret = ast_mode_config_init(ast);304	if (ret)305		return ERR_PTR(ret);306 307	return dev;308}309