diff options
Diffstat (limited to 'drivers/gpu/drm/ast/ast_mode.c')
| -rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 88 | 
1 files changed, 70 insertions, 18 deletions
| diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index cb9614984285..a718646a66b8 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1358,13 +1358,13 @@ static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)  	 * Protect access to I/O registers from concurrent modesetting  	 * by acquiring the I/O-register lock.  	 */ -	mutex_lock(&ast->ioregs_lock); +	mutex_lock(&ast->modeset_lock);  	edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter);  	if (!edid)  		goto err_mutex_unlock; -	mutex_unlock(&ast->ioregs_lock); +	mutex_unlock(&ast->modeset_lock);  	count = drm_add_edid_modes(connector, edid);  	kfree(edid); @@ -1372,7 +1372,7 @@ static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)  	return count;  err_mutex_unlock: -	mutex_unlock(&ast->ioregs_lock); +	mutex_unlock(&ast->modeset_lock);  err_drm_connector_update_edid_property:  	drm_connector_update_edid_property(connector, NULL);  	return 0; @@ -1464,13 +1464,13 @@ static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector  	 * Protect access to I/O registers from concurrent modesetting  	 * by acquiring the I/O-register lock.  	 */ -	mutex_lock(&ast->ioregs_lock); +	mutex_lock(&ast->modeset_lock);  	edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter);  	if (!edid)  		goto err_mutex_unlock; -	mutex_unlock(&ast->ioregs_lock); +	mutex_unlock(&ast->modeset_lock);  	count = drm_add_edid_modes(connector, edid);  	kfree(edid); @@ -1478,7 +1478,7 @@ static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector  	return count;  err_mutex_unlock: -	mutex_unlock(&ast->ioregs_lock); +	mutex_unlock(&ast->modeset_lock);  err_drm_connector_update_edid_property:  	drm_connector_update_edid_property(connector, NULL);  	return 0; @@ -1670,13 +1670,13 @@ static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)  	 * Protect access to I/O registers from concurrent modesetting  	 * by acquiring the I/O-register lock.  	 */ -	mutex_lock(&ast->ioregs_lock); +	mutex_lock(&ast->modeset_lock);  	succ = ast_astdp_read_edid(connector->dev, edid);  	if (succ < 0)  		goto err_mutex_unlock; -	mutex_unlock(&ast->ioregs_lock); +	mutex_unlock(&ast->modeset_lock);  	drm_connector_update_edid_property(connector, edid);  	count = drm_add_edid_modes(connector, edid); @@ -1685,7 +1685,7 @@ static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)  	return count;  err_mutex_unlock: -	mutex_unlock(&ast->ioregs_lock); +	mutex_unlock(&ast->modeset_lock);  	kfree(edid);  err_drm_connector_update_edid_property:  	drm_connector_update_edid_property(connector, NULL); @@ -1767,6 +1767,30 @@ static const struct drm_encoder_funcs ast_bmc_encoder_funcs = {  	.destroy = drm_encoder_cleanup,  }; +static int ast_bmc_connector_helper_detect_ctx(struct drm_connector *connector, +					       struct drm_modeset_acquire_ctx *ctx, +					       bool force) +{ +	struct ast_bmc_connector *bmc_connector = to_ast_bmc_connector(connector); +	struct drm_connector *physical_connector = bmc_connector->physical_connector; + +	/* +	 * Most user-space compositors cannot handle more than one connected +	 * connector per CRTC. Hence, we only mark the BMC as connected if the +	 * physical connector is disconnected. If the physical connector's status +	 * is connected or unknown, the BMC remains disconnected. This has no +	 * effect on the output of the BMC. +	 * +	 * FIXME: Remove this logic once user-space compositors can handle more +	 *        than one connector per CRTC. The BMC should always be connected. +	 */ + +	if (physical_connector && physical_connector->status == connector_status_disconnected) +		return connector_status_connected; + +	return connector_status_disconnected; +} +  static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)  {  	return drm_add_modes_noedid(connector, 4096, 4096); @@ -1774,6 +1798,7 @@ static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)  static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = {  	.get_modes = ast_bmc_connector_helper_get_modes, +	.detect_ctx = ast_bmc_connector_helper_detect_ctx,  };  static const struct drm_connector_funcs ast_bmc_connector_funcs = { @@ -1784,12 +1809,33 @@ static const struct drm_connector_funcs ast_bmc_connector_funcs = {  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,  }; -static int ast_bmc_output_init(struct ast_device *ast) +static int ast_bmc_connector_init(struct drm_device *dev, +				  struct ast_bmc_connector *bmc_connector, +				  struct drm_connector *physical_connector) +{ +	struct drm_connector *connector = &bmc_connector->base; +	int ret; + +	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); + +	bmc_connector->physical_connector = physical_connector; + +	return 0; +} + +static int ast_bmc_output_init(struct ast_device *ast, +			       struct drm_connector *physical_connector)  {  	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; +	struct ast_bmc_connector *bmc_connector = &ast->output.bmc.bmc_connector; +	struct drm_connector *connector = &bmc_connector->base;  	int ret;  	ret = drm_encoder_init(dev, encoder, @@ -1799,13 +1845,10 @@ static int ast_bmc_output_init(struct ast_device *ast)  		return ret;  	encoder->possible_crtcs = drm_crtc_mask(crtc); -	ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs, -				 DRM_MODE_CONNECTOR_VIRTUAL); +	ret = ast_bmc_connector_init(dev, bmc_connector, physical_connector);  	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; @@ -1827,9 +1870,9 @@ static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *s  	 * display modes. Protect access to I/O registers by acquiring  	 * the I/O-register lock. Released in atomic_flush().  	 */ -	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 = { @@ -1864,8 +1907,13 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = {  int ast_mode_config_init(struct ast_device *ast)  {  	struct drm_device *dev = &ast->base; +	struct drm_connector *physical_connector = NULL;  	int ret; +	ret = drmm_mutex_init(dev, &ast->modeset_lock); +	if (ret) +		return ret; +  	ret = drmm_mode_config_init(dev);  	if (ret)  		return ret; @@ -1904,23 +1952,27 @@ int ast_mode_config_init(struct ast_device *ast)  		ret = ast_vga_output_init(ast);  		if (ret)  			return ret; +		physical_connector = &ast->output.vga.vga_connector.base;  	}  	if (ast->tx_chip_types & AST_TX_SIL164_BIT) {  		ret = ast_sil164_output_init(ast);  		if (ret)  			return ret; +		physical_connector = &ast->output.sil164.sil164_connector.base;  	}  	if (ast->tx_chip_types & AST_TX_DP501_BIT) {  		ret = ast_dp501_output_init(ast);  		if (ret)  			return ret; +		physical_connector = &ast->output.dp501.connector;  	}  	if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {  		ret = ast_astdp_output_init(ast);  		if (ret)  			return ret; +		physical_connector = &ast->output.astdp.connector;  	} -	ret = ast_bmc_output_init(ast); +	ret = ast_bmc_output_init(ast, physical_connector);  	if (ret)  		return ret; | 
