diff options
Diffstat (limited to 'drivers/gpu/drm/ast')
| -rw-r--r-- | drivers/gpu/drm/ast/ast_dp.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_dp501.c | 43 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_drv.h | 100 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_main.c | 298 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_mm.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 122 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_post.c | 74 | 
7 files changed, 396 insertions, 254 deletions
| diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 6dc1a09504e1..fdd9a493aa9c 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -7,6 +7,17 @@  #include <drm/drm_print.h>  #include "ast_drv.h" +bool ast_astdp_is_connected(struct ast_device *ast) +{ +	if (!ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)) +		return false; +	if (!ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) +		return false; +	if (!ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)) +		return false; +	return true; +} +  int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)  {  	struct ast_device *ast = to_ast_device(dev); diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 1bc35a992369..f10d53b0c94f 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -272,11 +272,9 @@ static bool ast_launch_m68k(struct drm_device *dev)  	return true;  } -bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) +bool ast_dp501_is_connected(struct ast_device *ast)  { -	struct ast_device *ast = to_ast_device(dev); -	u32 i, boot_address, offset, data; -	u32 *pEDIDidx; +	u32 boot_address, offset, data;  	if (ast->config_mode == ast_use_p2a) {  		boot_address = get_fw_base(ast); @@ -292,14 +290,6 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)  		data = ast_mindwm(ast, boot_address + offset);  		if (!(data & AST_DP501_PNP_CONNECTED))  			return false; - -		/* Read EDID */ -		offset = AST_DP501_EDID_DATA; -		for (i = 0; i < 128; i += 4) { -			data = ast_mindwm(ast, boot_address + offset + i); -			pEDIDidx = (u32 *)(ediddata + i); -			*pEDIDidx = data; -		}  	} else {  		if (!ast->dp501_fw_buf)  			return false; @@ -319,10 +309,33 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)  		data = readl(ast->dp501_fw_buf + offset);  		if (!(data & AST_DP501_PNP_CONNECTED))  			return false; +	} +	return true; +} + +bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) +{ +	struct ast_device *ast = to_ast_device(dev); +	u32 i, boot_address, offset, data; +	u32 *pEDIDidx; + +	if (!ast_dp501_is_connected(ast)) +		return false; + +	if (ast->config_mode == ast_use_p2a) { +		boot_address = get_fw_base(ast);  		/* Read EDID */  		offset = AST_DP501_EDID_DATA;  		for (i = 0; i < 128; i += 4) { +			data = ast_mindwm(ast, boot_address + offset + i); +			pEDIDidx = (u32 *)(ediddata + i); +			*pEDIDidx = data; +		} +	} else { +		/* Read EDID */ +		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; @@ -350,7 +363,7 @@ static bool ast_init_dvo(struct drm_device *dev)  		data |= 0x00000500;  		ast_write32(ast, 0x12008, data); -		if (ast->chip == AST2300) { +		if (IS_AST_GEN4(ast)) {  			data = ast_read32(ast, 0x12084);  			/* multi-pins for DVO single-edge */  			data |= 0xfffe0000; @@ -366,7 +379,7 @@ static bool ast_init_dvo(struct drm_device *dev)  			data &= 0xffffffcf;  			data |= 0x00000020;  			ast_write32(ast, 0x12090, data); -		} else { /* AST2400 */ +		} else { /* AST GEN5+ */  			data = ast_read32(ast, 0x12088);  			/* multi-pins for DVO single-edge */  			data |= 0x30000000; @@ -437,7 +450,7 @@ void ast_init_3rdtx(struct drm_device *dev)  	struct ast_device *ast = to_ast_device(dev);  	u8 jreg; -	if (ast->chip == AST2300 || ast->chip == AST2400) { +	if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) {  		jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);  		switch (jreg & 0x0e) {  		case 0x04: diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 5498a6676f2e..848a9f1403e8 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -52,19 +52,38 @@  #define PCI_CHIP_AST2000 0x2000  #define PCI_CHIP_AST2100 0x2010 +#define __AST_CHIP(__gen, __index)	((__gen) << 16 | (__index))  enum ast_chip { -	AST2000, -	AST2100, -	AST1100, -	AST2200, -	AST2150, -	AST2300, -	AST2400, -	AST2500, -	AST2600, +	/* 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), // unused +	/* 6th gen */ +	AST2500 = __AST_CHIP(6, 0), +	AST2510 = __AST_CHIP(6, 1), +	AST2520 = __AST_CHIP(6, 2), // unused +	/* 7th gen */ +	AST2600 = __AST_CHIP(7, 0), +	AST2620 = __AST_CHIP(7, 1), // unused  }; +#define __AST_CHIP_GEN(__chip)	(((unsigned long)(__chip)) >> 16) +  enum ast_tx_chip {  	AST_TX_NONE,  	AST_TX_SIL164, @@ -166,7 +185,6 @@ struct ast_device {  	void __iomem *dp501_fw_buf;  	enum ast_chip chip; -	bool vga2_clone;  	uint32_t dram_bus_width;  	uint32_t dram_type;  	uint32_t mclk; @@ -196,6 +214,10 @@ struct ast_device {  			struct drm_encoder encoder;  			struct drm_connector connector;  		} astdp; +		struct { +			struct drm_encoder encoder; +			struct drm_connector connector; +		} bmc;  	} output;  	bool support_wide_screen; @@ -219,6 +241,24 @@ struct ast_device *ast_device_create(const struct drm_driver *drv,  				     struct pci_dev *pdev,  				     unsigned long flags); +static inline unsigned long __ast_gen(struct ast_device *ast) +{ +	return __AST_CHIP_GEN(ast->chip); +} +#define AST_GEN(__ast)	__ast_gen(__ast) + +static inline bool __ast_gen_is_eq(struct ast_device *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_IO_AR_PORT_WRITE		(0x40)  #define AST_IO_MISC_PORT_WRITE		(0x42)  #define AST_IO_VGA_ENABLE_PORT		(0x43) @@ -258,26 +298,35 @@ static inline void ast_io_write8(struct ast_device *ast, u32 reg, u8 val)  	iowrite8(val, ast->ioregs + reg);  } -static inline void ast_set_index_reg(struct ast_device *ast, -				     uint32_t base, uint8_t index, -				     uint8_t val) +static inline u8 ast_get_index_reg(struct ast_device *ast, u32 base, u8 index)  {  	ast_io_write8(ast, base, index);  	++base; -	ast_io_write8(ast, base, val); +	return ast_io_read8(ast, base);  } -void ast_set_index_reg_mask(struct ast_device *ast, -			    uint32_t base, uint8_t index, -			    uint8_t mask, uint8_t val); -uint8_t ast_get_index_reg(struct ast_device *ast, -			  uint32_t base, uint8_t index); -uint8_t ast_get_index_reg_mask(struct ast_device *ast, -			       uint32_t base, uint8_t index, uint8_t mask); +static inline u8 ast_get_index_reg_mask(struct ast_device *ast, u32 base, u8 index, +					u8 preserve_mask) +{ +	u8 val = ast_get_index_reg(ast, base, index); + +	return val & preserve_mask; +} + +static inline void ast_set_index_reg(struct ast_device *ast, u32 base, u8 index, u8 val) +{ +	ast_io_write8(ast, base, index); +	++base; +	ast_io_write8(ast, base, val); +} -static inline void ast_open_key(struct ast_device *ast) +static inline void ast_set_index_reg_mask(struct ast_device *ast, u32 base, u8 index, +					  u8 preserve_mask, u8 val)  { -	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8); +	u8 tmp = ast_get_index_reg_mask(ast, base, index, preserve_mask); + +	tmp |= val; +	ast_set_index_reg(ast, base, index, tmp);  }  #define AST_VIDMEM_SIZE_8M    0x00800000 @@ -458,9 +507,6 @@ int ast_mode_config_init(struct ast_device *ast);  int ast_mm_init(struct ast_device *ast);  /* ast post */ -void ast_enable_vga(struct drm_device *dev); -void ast_enable_mmio(struct drm_device *dev); -bool ast_is_vga_enabled(struct drm_device *dev);  void ast_post_gpu(struct drm_device *dev);  u32 ast_mindwm(struct ast_device *ast, u32 r);  void ast_moutdwm(struct ast_device *ast, u32 r, u32 v); @@ -468,6 +514,7 @@ void ast_patch_ahb_2500(struct ast_device *ast);  /* ast dp501 */  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_is_connected(struct ast_device *ast);  bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);  u8 ast_get_dp501_max_clk(struct drm_device *dev);  void ast_init_3rdtx(struct drm_device *dev); @@ -476,6 +523,7 @@ void ast_init_3rdtx(struct drm_device *dev);  struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);  /* aspeed DP */ +bool ast_astdp_is_connected(struct ast_device *ast);  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); diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 1f35438f614a..dae365ed3969 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -35,131 +35,153 @@  #include "ast_drv.h" -void ast_set_index_reg_mask(struct ast_device *ast, -			    uint32_t base, uint8_t index, -			    uint8_t mask, uint8_t val) +static bool ast_is_vga_enabled(struct drm_device *dev)  { -	u8 tmp; -	ast_io_write8(ast, base, index); -	tmp = (ast_io_read8(ast, base + 1) & mask) | val; -	ast_set_index_reg(ast, base, index, tmp); +	struct ast_device *ast = to_ast_device(dev); +	u8 ch; + +	ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT); + +	return !!(ch & 0x01);  } -uint8_t ast_get_index_reg(struct ast_device *ast, -			  uint32_t base, uint8_t index) +static void ast_enable_vga(struct drm_device *dev)  { -	uint8_t ret; -	ast_io_write8(ast, base, index); -	ret = ast_io_read8(ast, base + 1); -	return ret; +	struct ast_device *ast = to_ast_device(dev); + +	ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01); +	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01);  } -uint8_t ast_get_index_reg_mask(struct ast_device *ast, -			       uint32_t base, uint8_t index, uint8_t mask) +/* + * Run this function as part of the HW device cleanup; not + * when the DRM device gets released. + */ +static void ast_enable_mmio_release(void *data)  { -	uint8_t ret; -	ast_io_write8(ast, base, index); -	ret = ast_io_read8(ast, base + 1) & mask; -	return ret; +	struct ast_device *ast = data; + +	/* enable standard VGA decode */ +	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);  } -static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) +static int ast_enable_mmio(struct ast_device *ast)  { -	struct device_node *np = dev->dev->of_node; -	struct ast_device *ast = to_ast_device(dev); +	struct drm_device *dev = &ast->base; + +	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); + +	return devm_add_action_or_reset(dev->dev, ast_enable_mmio_release, ast); +} + +static void ast_open_key(struct ast_device *ast) +{ +	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8); +} + +static int ast_device_config_init(struct ast_device *ast) +{ +	struct drm_device *dev = &ast->base;  	struct pci_dev *pdev = to_pci_dev(dev->dev); -	uint32_t data, jregd0, jregd1; +	struct device_node *np = dev->dev->of_node; +	uint32_t scu_rev = 0xffffffff; +	u32 data; +	u8 jregd0, jregd1; + +	/* +	 * Find configuration mode and read SCU revision +	 */ -	/* Defaults */  	ast->config_mode = ast_use_defaults; -	*scu_rev = 0xffffffff;  	/* Check if we have device-tree properties */ -	if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", -					scu_rev)) { +	if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", &data)) {  		/* We do, disable P2A access */  		ast->config_mode = ast_use_dt; -		drm_info(dev, "Using device-tree for configuration\n"); -		return; -	} +		scu_rev = data; +	} else if (pdev->device == PCI_CHIP_AST2000) { // Not all families have a P2A bridge +		/* +		 * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge +		 * 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); +		if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { + +			/* +			 * We have a P2A bridge and it is enabled. +			 */ + +			/* Patch AST2500/AST2510 */ +			if ((pdev->revision & 0xf0) == 0x40) { +				if (!(jregd0 & AST_VRAM_INIT_STATUS_MASK)) +					ast_patch_ahb_2500(ast); +			} -	/* Not all families have a P2A bridge */ -	if (pdev->device != PCI_CHIP_AST2000) -		return; +			/* Double check that it's actually working */ +			data = ast_read32(ast, 0xf004); +			if ((data != 0xffffffff) && (data != 0x00)) { +				ast->config_mode = ast_use_p2a; -	/* -	 * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge -	 * 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); -	if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { -		/* Patch AST2500 */ -		if (((pdev->revision & 0xF0) == 0x40) -			&& ((jregd0 & AST_VRAM_INIT_STATUS_MASK) == 0)) -			ast_patch_ahb_2500(ast); - -		/* Double check it's actually working */ -		data = ast_read32(ast, 0xf004); -		if ((data != 0xFFFFFFFF) && (data != 0x00)) { -			/* P2A works, grab silicon revision */ -			ast->config_mode = ast_use_p2a; - -			drm_info(dev, "Using P2A bridge for configuration\n"); - -			/* Read SCU7c (silicon revision register) */ -			ast_write32(ast, 0xf004, 0x1e6e0000); -			ast_write32(ast, 0xf000, 0x1); -			*scu_rev = ast_read32(ast, 0x1207c); -			return; +				/* Read SCU7c (silicon revision register) */ +				ast_write32(ast, 0xf004, 0x1e6e0000); +				ast_write32(ast, 0xf000, 0x1); +				scu_rev = ast_read32(ast, 0x1207c); +			}  		}  	} -	/* We have a P2A bridge but it's disabled */ -	drm_info(dev, "P2A bridge disabled, using default configuration\n"); -} - -static int ast_detect_chip(struct drm_device *dev, bool *need_post) -{ -	struct ast_device *ast = to_ast_device(dev); -	struct pci_dev *pdev = to_pci_dev(dev->dev); -	uint32_t jreg, scu_rev; +	switch (ast->config_mode) { +	case ast_use_defaults: +		drm_info(dev, "Using default configuration\n"); +		break; +	case ast_use_dt: +		drm_info(dev, "Using device-tree for configuration\n"); +		break; +	case ast_use_p2a: +		drm_info(dev, "Using P2A bridge for configuration\n"); +		break; +	}  	/* -	 * If VGA isn't enabled, we need to enable now or subsequent -	 * access to the scratch registers will fail. We also inform -	 * our caller that it needs to POST the chip -	 * (Assumption: VGA not enabled -> need to POST) +	 * Identify chipset  	 */ -	if (!ast_is_vga_enabled(dev)) { -		ast_enable_vga(dev); -		drm_info(dev, "VGA not enabled on entry, requesting chip POST\n"); -		*need_post = true; -	} else -		*need_post = false; - - -	/* Enable extended register access */ -	ast_open_key(ast); -	ast_enable_mmio(dev); -	/* Find out whether P2A works or whether to use device-tree */ -	ast_detect_config_mode(dev, &scu_rev); - -	/* Identify chipset */  	if (pdev->revision >= 0x50) {  		ast->chip = AST2600;  		drm_info(dev, "AST 2600 detected\n");  	} else if (pdev->revision >= 0x40) { -		ast->chip = AST2500; -		drm_info(dev, "AST 2500 detected\n"); +		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 (pdev->revision >= 0x30) { -		ast->chip = AST2400; -		drm_info(dev, "AST 2400 detected\n"); +		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 (pdev->revision >= 0x20) { -		ast->chip = AST2300; -		drm_info(dev, "AST 2300 detected\n"); +		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"); +			break; +		}  	} else if (pdev->revision >= 0x10) {  		switch (scu_rev & 0x0300) {  		case 0x0200: @@ -179,15 +201,21 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)  			drm_info(dev, "AST 2100 detected\n");  			break;  		} -		ast->vga2_clone = false;  	} else {  		ast->chip = AST2000;  		drm_info(dev, "AST 2000 detected\n");  	} +	return 0; +} + +static void ast_detect_widescreen(struct ast_device *ast) +{ +	u8 jreg; +  	/* Check if we support wide screen */ -	switch (ast->chip) { -	case AST2000: +	switch (AST_GEN(ast)) { +	case 1:  		ast->support_wide_screen = false;  		break;  	default: @@ -198,20 +226,23 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)  			ast->support_wide_screen = true;  		else {  			ast->support_wide_screen = false; -			if (ast->chip == AST2300 && -			    (scu_rev & 0x300) == 0x0) /* ast1300 */ +			if (ast->chip == AST1300)  				ast->support_wide_screen = true; -			if (ast->chip == AST2400 && -			    (scu_rev & 0x300) == 0x100) /* ast1400 */ +			if (ast->chip == AST1400)  				ast->support_wide_screen = true; -			if (ast->chip == AST2500 && -			    scu_rev == 0x100)           /* ast2510 */ +			if (ast->chip == AST2510)  				ast->support_wide_screen = true; -			if (ast->chip == AST2600)		/* ast2600 */ +			if (IS_AST_GEN7(ast))  				ast->support_wide_screen = true;  		}  		break;  	} +} + +static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) +{ +	struct drm_device *dev = &ast->base; +	u8 jreg;  	/* Check 3rd Tx option (digital output afaik) */  	ast->tx_chip_types |= AST_TX_NONE_BIT; @@ -224,15 +255,15 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)  	 * is at power-on reset, otherwise we'll incorrectly "detect" a  	 * SIL164 when there is none.  	 */ -	if (!*need_post) { +	if (!need_post) {  		jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff);  		if (jreg & 0x80)  			ast->tx_chip_types = AST_TX_SIL164_BIT;  	} -	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)  		 */ @@ -254,7 +285,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)  		case 0x0c:  			ast->tx_chip_types = AST_TX_DP501_BIT;  		} -	} else if (ast->chip == AST2600) { +	} else if (IS_AST_GEN7(ast)) {  		if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK) ==  		    ASTDP_DPMCU_TX) {  			ast->tx_chip_types = AST_TX_ASTDP_BIT; @@ -271,8 +302,6 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)  		drm_info(dev, "Using DP501 DisplayPort transmitter\n");  	if (ast->tx_chip_types & AST_TX_ASTDP_BIT)  		drm_info(dev, "Using ASPEED DisplayPort transmitter\n"); - -	return 0;  }  static int ast_get_dram_info(struct drm_device *dev) @@ -286,7 +315,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)) @@ -309,7 +338,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) +		if (IS_AST_GEN6(ast))  			ast->mclk = 800;  		else  			ast->mclk = 396; @@ -321,7 +350,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; @@ -337,7 +366,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; @@ -395,25 +424,13 @@ static int ast_get_dram_info(struct drm_device *dev)  	return 0;  } -/* - * 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_device *ast = data; - -	/* enable standard VGA decode */ -	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); -} -  struct ast_device *ast_device_create(const struct drm_driver *drv,  				     struct pci_dev *pdev,  				     unsigned long flags)  {  	struct drm_device *dev;  	struct ast_device *ast; -	bool need_post; +	bool need_post = false;  	int ret = 0;  	ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base); @@ -449,7 +466,30 @@ struct ast_device *ast_device_create(const struct drm_driver *drv,  			return ERR_PTR(-EIO);  	} -	ast_detect_chip(dev, &need_post); +	if (!ast_is_vga_enabled(dev)) { +		drm_info(dev, "VGA not enabled on entry, requesting chip POST\n"); +		need_post = true; +	} + +	/* +	 * If VGA isn't enabled, we need to enable now or subsequent +	 * access to the scratch registers will fail. +	 */ +	if (need_post) +		ast_enable_vga(dev); + +	/* Enable extended register access */ +	ast_open_key(ast); +	ret = ast_enable_mmio(ast); +	if (ret) +		return ERR_PTR(ret); + +	ret = ast_device_config_init(ast); +	if (ret) +		return ERR_PTR(ret); + +	ast_detect_widescreen(ast); +	ast_detect_tx_chip(ast, need_post);  	ret = ast_get_dram_info(dev);  	if (ret) @@ -477,9 +517,5 @@ struct ast_device *ast_device_create(const struct drm_driver *drv,  	if (ret)  		return ERR_PTR(ret); -	ret = devm_add_action_or_reset(dev->dev, ast_device_release, ast); -	if (ret) -		return ERR_PTR(ret); -  	return ast;  } diff --git a/drivers/gpu/drm/ast/ast_mm.c b/drivers/gpu/drm/ast/ast_mm.c index e16af60deef9..bc174bd933b9 100644 --- a/drivers/gpu/drm/ast/ast_mm.c +++ b/drivers/gpu/drm/ast/ast_mm.c @@ -38,8 +38,6 @@ static u32 ast_get_vram_size(struct ast_device *ast)  	u8 jreg;  	u32 vram_size; -	ast_open_key(ast); -  	vram_size = AST_VIDMEM_DEFAULT_SIZE;  	jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff);  	switch (jreg & 3) { diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b3c670af6ef2..32f04ec6c386 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -342,7 +342,7 @@ static void ast_set_crtc_reg(struct ast_device *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; @@ -384,7 +384,7 @@ static void ast_set_crtc_reg(struct ast_device *ast,  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD);  	// Workaround for HSync Time non octave pixels (1920x1080@60Hz HSync 44 pixels); -	if ((ast->chip == AST2600) && (mode->crtc_vdisplay == 1080)) +	if (IS_AST_GEN7(ast) && (mode->crtc_vdisplay == 1080))  		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x02);  	else  		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x00); @@ -466,7 +466,7 @@ static void ast_set_dclk_reg(struct ast_device *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))  		clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];  	else  		clk_info = &dclk_table[vbios_mode->enh_table->dclk_index]; @@ -510,17 +510,13 @@ static void ast_set_color_reg(struct ast_device *ast,  static void ast_set_crtthd_reg(struct ast_device *ast)  {  	/* Set Threshold */ -	if (ast->chip == AST2600) { +	if (IS_AST_GEN7(ast)) {  		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) { +	} else if (IS_AST_GEN6(ast) || IS_AST_GEN5(ast) || IS_AST_GEN4(ast)) {  		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) { +	} else if (IS_AST_GEN3(ast) || IS_AST_GEN2(ast)) {  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f);  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f);  	} else { @@ -1082,9 +1078,10 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode  		if ((mode->hdisplay == 1152) && (mode->vdisplay == 864))  			return MODE_OK; -		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_GEN4(ast) || IS_AST_GEN5(ast) || +		    IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) {  			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))  				return MODE_OK; @@ -1585,8 +1582,20 @@ err_drm_connector_update_edid_property:  	return 0;  } +static int ast_dp501_connector_helper_detect_ctx(struct drm_connector *connector, +						 struct drm_modeset_acquire_ctx *ctx, +						 bool force) +{ +	struct ast_device *ast = to_ast_device(connector->dev); + +	if (ast_dp501_is_connected(ast)) +		return connector_status_connected; +	return connector_status_disconnected; +} +  static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {  	.get_modes = ast_dp501_connector_helper_get_modes, +	.detect_ctx = ast_dp501_connector_helper_detect_ctx,  };  static const struct drm_connector_funcs ast_dp501_connector_funcs = { @@ -1611,7 +1620,7 @@ static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector  	connector->interlace_allowed = 0;  	connector->doublescan_allowed = 0; -	connector->polled = DRM_CONNECTOR_POLL_CONNECT; +	connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;  	return 0;  } @@ -1683,8 +1692,20 @@ err_drm_connector_update_edid_property:  	return 0;  } +static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector, +						 struct drm_modeset_acquire_ctx *ctx, +						 bool force) +{ +	struct ast_device *ast = to_ast_device(connector->dev); + +	if (ast_astdp_is_connected(ast)) +		return connector_status_connected; +	return connector_status_disconnected; +} +  static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {  	.get_modes = ast_astdp_connector_helper_get_modes, +	.detect_ctx = ast_astdp_connector_helper_detect_ctx,  };  static const struct drm_connector_funcs ast_astdp_connector_funcs = { @@ -1709,7 +1730,7 @@ static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector  	connector->interlace_allowed = 0;  	connector->doublescan_allowed = 0; -	connector->polled = DRM_CONNECTOR_POLL_CONNECT; +	connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;  	return 0;  } @@ -1739,6 +1760,60 @@ static int ast_astdp_output_init(struct ast_device *ast)  }  /* + * BMC virtual Connector + */ + +static const struct drm_encoder_funcs ast_bmc_encoder_funcs = { +	.destroy = drm_encoder_cleanup, +}; + +static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector) +{ +	return drm_add_modes_noedid(connector, 4096, 4096); +} + +static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = { +	.get_modes = ast_bmc_connector_helper_get_modes, +}; + +static const struct drm_connector_funcs ast_bmc_connector_funcs = { +	.reset = drm_atomic_helper_connector_reset, +	.fill_modes = drm_helper_probe_single_connector_modes, +	.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_bmc_output_init(struct ast_device *ast) +{ +	struct drm_device *dev = &ast->base; +	struct drm_crtc *crtc = &ast->crtc; +	struct drm_encoder *encoder = &ast->output.bmc.encoder; +	struct drm_connector *connector = &ast->output.bmc.connector; +	int ret; + +	ret = drm_encoder_init(dev, encoder, +			       &ast_bmc_encoder_funcs, +			       DRM_MODE_ENCODER_VIRTUAL, "ast_bmc"); +	if (ret) +		return ret; +	encoder->possible_crtcs = drm_crtc_mask(crtc); + +	ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs, +				 DRM_MODE_CONNECTOR_VIRTUAL); +	if (ret) +		return ret; + +	drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs); + +	ret = drm_connector_attach_encoder(connector, encoder); +	if (ret) +		return ret; + +	return 0; +} + +/*   * Mode config   */ @@ -1800,12 +1875,12 @@ int ast_mode_config_init(struct ast_device *ast)  	dev->mode_config.min_height = 0;  	dev->mode_config.preferred_depth = 24; -	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 { @@ -1845,8 +1920,13 @@ int ast_mode_config_init(struct ast_device *ast)  		if (ret)  			return ret;  	} +	ret = ast_bmc_output_init(ast); +	if (ret) +		return ret;  	drm_mode_config_reset(dev); +	drm_kms_helper_poll_init(dev); +  	return 0;  } diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index a005aec18a02..13e15173f2c5 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -37,41 +37,13 @@  static void ast_post_chip_2300(struct drm_device *dev);  static void ast_post_chip_2500(struct drm_device *dev); -void ast_enable_vga(struct drm_device *dev) -{ -	struct ast_device *ast = to_ast_device(dev); - -	ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01); -	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01); -} - -void ast_enable_mmio(struct drm_device *dev) -{ -	struct ast_device *ast = to_ast_device(dev); - -	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); -} - - -bool ast_is_vga_enabled(struct drm_device *dev) -{ -	struct ast_device *ast = to_ast_device(dev); -	u8 ch; - -	ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT); - -	return !!(ch & 0x01); -} -  static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff }; -static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff };  static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff };  static void  ast_set_def_ext_reg(struct drm_device *dev)  {  	struct ast_device *ast = to_ast_device(dev); -	struct pci_dev *pdev = to_pci_dev(dev->dev);  	u8 i, index, reg;  	const u8 *ext_reg_info; @@ -79,13 +51,9 @@ ast_set_def_ext_reg(struct drm_device *dev)  	for (i = 0x81; i <= 0x9f; i++)  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00); -	if (ast->chip == AST2300 || ast->chip == AST2400 || -	    ast->chip == AST2500) { -		if (pdev->revision >= 0x20) -			ext_reg_info = extreginfo_ast2300; -		else -			ext_reg_info = extreginfo_ast2300a0; -	} else +	if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) +		ext_reg_info = extreginfo_ast2300; +	else  		ext_reg_info = extreginfo;  	index = 0xa0; @@ -104,8 +72,7 @@ ast_set_def_ext_reg(struct drm_device *dev)  	/* Enable RAMDAC for A1 */  	reg = 0x04; -	if (ast->chip == AST2300 || ast->chip == AST2400 || -	    ast->chip == AST2500) +	if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast))  		reg |= 0x20;  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);  } @@ -281,7 +248,7 @@ static void ast_init_dram_reg(struct drm_device *dev)  	j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);  	if ((j & 0x80) == 0) { /* VGA only */ -		if (ast->chip == AST2000) { +		if (IS_AST_GEN1(ast)) {  			dram_reg_info = ast2000_dram_table_data;  			ast_write32(ast, 0xf004, 0x1e6e0000);  			ast_write32(ast, 0xf000, 0x1); @@ -290,8 +257,8 @@ static void ast_init_dram_reg(struct drm_device *dev)  			do {  				;  			} while (ast_read32(ast, 0x10100) != 0xa8); -		} else {/* AST2100/1100 */ -			if (ast->chip == AST2100 || ast->chip == 2200) +		} else { /* GEN2/GEN3 */ +			if (ast->chip == AST2100 || ast->chip == AST2200)  				dram_reg_info = ast2100_dram_table_data;  			else  				dram_reg_info = ast1100_dram_table_data; @@ -313,7 +280,7 @@ static void ast_init_dram_reg(struct drm_device *dev)  			if (dram_reg_info->index == 0xff00) {/* delay fn */  				for (i = 0; i < 15; i++)  					udelay(dram_reg_info->data); -			} else if (dram_reg_info->index == 0x4 && ast->chip != AST2000) { +			} else if (dram_reg_info->index == 0x4 && !IS_AST_GEN1(ast)) {  				data = dram_reg_info->data;  				if (ast->dram_type == AST_DRAM_1Gx16)  					data = 0x00000d89; @@ -339,15 +306,13 @@ static void ast_init_dram_reg(struct drm_device *dev)  				cbrdlli_ast2150(ast, 32); /* 32 bits */  		} -		switch (ast->chip) { -		case AST2000: +		switch (AST_GEN(ast)) { +		case 1:  			temp = ast_read32(ast, 0x10140);  			ast_write32(ast, 0x10140, temp | 0x40);  			break; -		case AST1100: -		case AST2100: -		case AST2200: -		case AST2150: +		case 2: +		case 3:  			temp = ast_read32(ast, 0x1200c);  			ast_write32(ast, 0x1200c, temp & 0xfffffffd);  			temp = ast_read32(ast, 0x12040); @@ -367,25 +332,16 @@ static void ast_init_dram_reg(struct drm_device *dev)  void ast_post_gpu(struct drm_device *dev)  {  	struct ast_device *ast = to_ast_device(dev); -	struct pci_dev *pdev = to_pci_dev(dev->dev); -	u32 reg; - -	pci_read_config_dword(pdev, 0x04, ®); -	reg |= 0x3; -	pci_write_config_dword(pdev, 0x04, reg); -	ast_enable_vga(dev); -	ast_open_key(ast); -	ast_enable_mmio(dev);  	ast_set_def_ext_reg(dev); -	if (ast->chip == AST2600) { +	if (IS_AST_GEN7(ast)) {  		if (ast->tx_chip_types & AST_TX_ASTDP_BIT)  			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); -		else if (ast->chip == AST2300 || ast->chip == AST2400) +		else if (IS_AST_GEN5(ast) || IS_AST_GEN4(ast))  			ast_post_chip_2300(dev);  		else  			ast_init_dram_reg(dev); | 
