diff options
Diffstat (limited to 'drivers/gpu/drm/ast/ast_main.c')
| -rw-r--r-- | drivers/gpu/drm/ast/ast_main.c | 152 | 
1 files changed, 85 insertions, 67 deletions
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 7f6152d374c..a2cc6be9798 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -66,12 +66,16 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast,  static int ast_detect_chip(struct drm_device *dev)  {  	struct ast_private *ast = dev->dev_private; +	uint32_t data, jreg;  	if (dev->pdev->device == PCI_CHIP_AST1180) {  		ast->chip = AST1100;  		DRM_INFO("AST 1180 detected\n");  	} else { -		if (dev->pdev->revision >= 0x20) { +		if (dev->pdev->revision >= 0x30) { +			ast->chip = AST2400; +			DRM_INFO("AST 2400 detected\n"); +		} else if (dev->pdev->revision >= 0x20) {  			ast->chip = AST2300;  			DRM_INFO("AST 2300 detected\n");  		} else if (dev->pdev->revision >= 0x10) { @@ -104,6 +108,59 @@ static int ast_detect_chip(struct drm_device *dev)  			DRM_INFO("AST 2000 detected\n");  		}  	} + +	switch (ast->chip) { +	case AST1180: +		ast->support_wide_screen = true; +		break; +	case AST2000: +		ast->support_wide_screen = false; +		break; +	default: +		jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); +		if (!(jreg & 0x80)) +			ast->support_wide_screen = true; +		else if (jreg & 0x01) +			ast->support_wide_screen = true; +		else { +			ast->support_wide_screen = false; +			ast_write32(ast, 0xf004, 0x1e6e0000); +			ast_write32(ast, 0xf000, 0x1); +			data = ast_read32(ast, 0x1207c); +			data &= 0x300; +			if (ast->chip == AST2300 && data == 0x0) /* ast1300 */ +				ast->support_wide_screen = true; +			if (ast->chip == AST2400 && data == 0x100) /* ast1400 */ +				ast->support_wide_screen = true; +		} +		break; +	} + +	ast->tx_chip_type = AST_TX_NONE; +	jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff); +	if (jreg & 0x80) +		ast->tx_chip_type = AST_TX_SIL164; +	if ((ast->chip == AST2300) || (ast->chip == AST2400)) { +		jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); +		switch (jreg) { +		case 0x04: +			ast->tx_chip_type = AST_TX_SIL164; +			break; +		case 0x08: +			ast->dp501_fw_addr = kzalloc(32*1024, GFP_KERNEL); +			if (ast->dp501_fw_addr) { +				/* backup firmware */ +				if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) { +					kfree(ast->dp501_fw_addr); +					ast->dp501_fw_addr = NULL; +				} +			} +			/* fallthrough */ +		case 0x0c: +			ast->tx_chip_type = AST_TX_DP501; +		} +	} +  	return 0;  } @@ -129,7 +186,7 @@ static int ast_get_dram_info(struct drm_device *dev)  	else  		ast->dram_bus_width = 32; -	if (ast->chip == AST2300) { +	if (ast->chip == AST2300 || ast->chip == AST2400) {  		switch (data & 0x03) {  		case 0:  			ast->dram_type = AST_DRAM_512Mx16; @@ -189,53 +246,6 @@ static int ast_get_dram_info(struct drm_device *dev)  	return 0;  } -uint32_t ast_get_max_dclk(struct drm_device *dev, int bpp) -{ -	struct ast_private *ast = dev->dev_private; -	uint32_t dclk, jreg; -	uint32_t dram_bus_width, mclk, dram_bandwidth, actual_dram_bandwidth, dram_efficency = 500; - -	dram_bus_width = ast->dram_bus_width; -	mclk = ast->mclk; - -	if (ast->chip == AST2100 || -	    ast->chip == AST1100 || -	    ast->chip == AST2200 || -	    ast->chip == AST2150 || -	    ast->dram_bus_width == 16) -		dram_efficency = 600; -	else if (ast->chip == AST2300) -		dram_efficency = 400; - -	dram_bandwidth = mclk * dram_bus_width * 2 / 8; -	actual_dram_bandwidth = dram_bandwidth * dram_efficency / 1000; - -	if (ast->chip == AST1180) -		dclk = actual_dram_bandwidth / ((bpp + 1) / 8); -	else { -		jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); -		if ((jreg & 0x08) && (ast->chip == AST2000)) -			dclk = actual_dram_bandwidth / ((bpp + 1 + 16) / 8); -		else if ((jreg & 0x08) && (bpp == 8)) -			dclk = actual_dram_bandwidth / ((bpp + 1 + 24) / 8); -		else -			dclk = actual_dram_bandwidth / ((bpp + 1) / 8); -	} - -	if (ast->chip == AST2100 || -	    ast->chip == AST2200 || -	    ast->chip == AST2300 || -	    ast->chip == AST1180) { -		if (dclk > 200) -			dclk = 200; -	} else { -		if (dclk > 165) -			dclk = 165; -	} - -	return dclk; -} -  static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)  {  	struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb); @@ -304,17 +314,32 @@ static u32 ast_get_vram_info(struct drm_device *dev)  {  	struct ast_private *ast = dev->dev_private;  	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) { -	case 0: return AST_VIDMEM_SIZE_8M; -	case 1: return AST_VIDMEM_SIZE_16M; -	case 2: return AST_VIDMEM_SIZE_32M; -	case 3: return AST_VIDMEM_SIZE_64M; +	case 0: vram_size = AST_VIDMEM_SIZE_8M; break; +	case 1: vram_size = AST_VIDMEM_SIZE_16M; break; +	case 2: vram_size = AST_VIDMEM_SIZE_32M; break; +	case 3: vram_size = AST_VIDMEM_SIZE_64M; break; +	} + +	jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xff); +	switch (jreg & 0x03) { +	case 1: +		vram_size -= 0x100000; +		break; +	case 2: +		vram_size -= 0x200000; +		break; +	case 3: +		vram_size -= 0x400000; +		break;  	} -	return AST_VIDMEM_DEFAULT_SIZE; + +	return vram_size;  }  int ast_driver_load(struct drm_device *dev, unsigned long flags) @@ -363,6 +388,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)  	if (ast->chip == AST2100 ||  	    ast->chip == AST2200 ||  	    ast->chip == AST2300 || +	    ast->chip == AST2400 ||  	    ast->chip == AST1180) {  		dev->mode_config.max_width = 1920;  		dev->mode_config.max_height = 2048; @@ -390,6 +416,7 @@ int ast_driver_unload(struct drm_device *dev)  {  	struct ast_private *ast = dev->dev_private; +	kfree(ast->dp501_fw_addr);  	ast_mode_fini(dev);  	ast_fbdev_fini(dev);  	drm_mode_config_cleanup(dev); @@ -449,13 +476,7 @@ int ast_dumb_create(struct drm_file *file,  	return 0;  } -int ast_gem_init_object(struct drm_gem_object *obj) -{ -	BUG(); -	return 0; -} - -void ast_bo_unref(struct ast_bo **bo) +static void ast_bo_unref(struct ast_bo **bo)  {  	struct ttm_buffer_object *tbo; @@ -464,16 +485,13 @@ void ast_bo_unref(struct ast_bo **bo)  	tbo = &((*bo)->bo);  	ttm_bo_unref(&tbo); -	if (tbo == NULL) -		*bo = NULL; - +	*bo = NULL;  } +  void ast_gem_free_object(struct drm_gem_object *obj)  {  	struct ast_bo *ast_bo = gem_to_ast_bo(obj); -	if (!ast_bo) -		return;  	ast_bo_unref(&ast_bo);  }  | 
