diff options
Diffstat (limited to 'drivers/gpu/drm/ast/ast_mode.c')
| -rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 130 | 
1 files changed, 103 insertions, 27 deletions
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 7fc9f7272b5..114aee941d4 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -81,7 +81,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo  	u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;  	u32 hborder, vborder; -	switch (crtc->fb->bits_per_pixel) { +	switch (crtc->primary->fb->bits_per_pixel) {  	case 8:  		vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];  		color_index = VGAModeIndex - 1; @@ -115,11 +115,17 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo  		else  			vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];  		break; +	case 1360: +		vbios_mode->enh_table = &res_1360x768[refresh_rate_index]; +		break;  	case 1440:  		vbios_mode->enh_table = &res_1440x900[refresh_rate_index];  		break;  	case 1600: -		vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; +		if (crtc->mode.crtc_vdisplay == 900) +			vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; +		else +			vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];  		break;  	case 1680:  		vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; @@ -175,14 +181,17 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo  		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_CRTC_PORT, 0x91, 0xa8); -		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel); -		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, 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, crtc->primary->fb->bits_per_pixel); +			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_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); +			ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); +		}  	}  	return true; @@ -340,7 +349,7 @@ static void ast_set_offset_reg(struct drm_crtc *crtc)  	u16 offset; -	offset = crtc->fb->pitches[0] >> 3; +	offset = crtc->primary->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);  } @@ -365,7 +374,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode  	struct ast_private *ast = crtc->dev->dev_private;  	u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; -	switch (crtc->fb->bits_per_pixel) { +	switch (crtc->primary->fb->bits_per_pixel) {  	case 8:  		jregA0 = 0x70;  		jregA3 = 0x01; @@ -389,7 +398,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);  	/* Set Threshold */ -	if (ast->chip == AST2300) { +	if (ast->chip == AST2300 || ast->chip == AST2400) {  		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 || @@ -404,7 +413,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode  	}  } -void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode, +static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,  		      struct ast_vbios_mode_info *vbios_mode)  {  	struct ast_private *ast = dev->dev_private; @@ -415,10 +424,10 @@ void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,  	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);  } -bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, +static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,  		     struct ast_vbios_mode_info *vbios_mode)  { -	switch (crtc->fb->bits_per_pixel) { +	switch (crtc->primary->fb->bits_per_pixel) {  	case 8:  		break;  	default: @@ -427,7 +436,7 @@ bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,  	return true;  } -void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset) +static void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset)  {  	struct ast_private *ast = crtc->dev->dev_private;  	u32 addr; @@ -451,9 +460,13 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)  	case DRM_MODE_DPMS_STANDBY:  	case DRM_MODE_DPMS_SUSPEND:  		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0); +		if (ast->tx_chip_type == AST_TX_DP501) +			ast_set_dp501_video_output(crtc->dev, 1);  		ast_crtc_load_lut(crtc);  		break;  	case DRM_MODE_DPMS_OFF: +		if (ast->tx_chip_type == AST_TX_DP501) +			ast_set_dp501_video_output(crtc->dev, 0);  		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20);  		break;  	} @@ -490,7 +503,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,  		ast_bo_unreserve(bo);  	} -	ast_fb = to_ast_framebuffer(crtc->fb); +	ast_fb = to_ast_framebuffer(crtc->primary->fb);  	obj = ast_fb->obj;  	bo = gem_to_ast_bo(obj); @@ -623,7 +636,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = {  	.destroy = ast_crtc_destroy,  }; -int ast_crtc_init(struct drm_device *dev) +static int ast_crtc_init(struct drm_device *dev)  {  	struct ast_crtc *crtc;  	int i; @@ -710,7 +723,7 @@ static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = {  	.mode_set = ast_encoder_mode_set,  }; -int ast_encoder_init(struct drm_device *dev) +static int ast_encoder_init(struct drm_device *dev)  {  	struct ast_encoder *ast_encoder; @@ -729,10 +742,24 @@ int ast_encoder_init(struct drm_device *dev)  static int ast_get_modes(struct drm_connector *connector)  {  	struct ast_connector *ast_connector = to_ast_connector(connector); +	struct ast_private *ast = connector->dev->dev_private;  	struct edid *edid;  	int ret; - -	edid = drm_get_edid(connector, &ast_connector->i2c->adapter); +	bool flags = false; +	if (ast->tx_chip_type == AST_TX_DP501) { +		ast->dp501_maxclk = 0xff; +		edid = kmalloc(128, GFP_KERNEL); +		if (!edid) +			return -ENOMEM; + +		flags = ast_dp501_read_edid(connector->dev, (u8 *)edid); +		if (flags) +			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev); +		else +			kfree(edid); +	} +	if (!flags) +		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);  	if (edid) {  		drm_mode_connector_update_edid_property(&ast_connector->base, edid);  		ret = drm_add_edid_modes(connector, edid); @@ -746,7 +773,56 @@ static int ast_get_modes(struct drm_connector *connector)  static int ast_mode_valid(struct drm_connector *connector,  			  struct drm_display_mode *mode)  { -	return MODE_OK; +	struct ast_private *ast = connector->dev->dev_private; +	int flags = MODE_NOMODE; +	uint32_t jtemp; + +	if (ast->support_wide_screen) { +		if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050)) +			return MODE_OK; +		if ((mode->hdisplay == 1280) && (mode->vdisplay == 800)) +			return MODE_OK; +		if ((mode->hdisplay == 1440) && (mode->vdisplay == 900)) +			return MODE_OK; +		if ((mode->hdisplay == 1360) && (mode->vdisplay == 768)) +			return MODE_OK; +		if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) +			return MODE_OK; + +		if ((ast->chip == AST2100) || (ast->chip == AST2200) || (ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST1180)) { +			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080)) +				return MODE_OK; + +			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) { +				jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); +				if (jtemp & 0x01) +					return MODE_NOMODE; +				else +					return MODE_OK; +			} +		} +	} +	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 1280: +		if (mode->vdisplay == 1024) flags = MODE_OK; +		break; +	case 1600: +		if (mode->vdisplay == 1200) flags = MODE_OK; +		break; +	default: +		return flags; +	} + +	return flags;  }  static void ast_connector_destroy(struct drm_connector *connector) @@ -777,7 +853,7 @@ static const struct drm_connector_funcs ast_connector_funcs = {  	.destroy = ast_connector_destroy,  }; -int ast_connector_init(struct drm_device *dev) +static int ast_connector_init(struct drm_device *dev)  {  	struct ast_connector *ast_connector;  	struct drm_connector *connector; @@ -810,7 +886,7 @@ int ast_connector_init(struct drm_device *dev)  }  /* allocate cursor cache and pin at start of VRAM */ -int ast_cursor_init(struct drm_device *dev) +static int ast_cursor_init(struct drm_device *dev)  {  	struct ast_private *ast = dev->dev_private;  	int size; @@ -847,7 +923,7 @@ fail:  	return ret;  } -void ast_cursor_fini(struct drm_device *dev) +static void ast_cursor_fini(struct drm_device *dev)  {  	struct ast_private *ast = dev->dev_private;  	ttm_bo_kunmap(&ast->cache_kmap); @@ -965,7 +1041,7 @@ static void ast_i2c_destroy(struct ast_i2c_chan *i2c)  	kfree(i2c);  } -void ast_show_cursor(struct drm_crtc *crtc) +static void ast_show_cursor(struct drm_crtc *crtc)  {  	struct ast_private *ast = crtc->dev->dev_private;  	u8 jreg; @@ -976,7 +1052,7 @@ void ast_show_cursor(struct drm_crtc *crtc)  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);  } -void ast_hide_cursor(struct drm_crtc *crtc) +static void ast_hide_cursor(struct drm_crtc *crtc)  {  	struct ast_private *ast = crtc->dev->dev_private;  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);  | 
