Add patch from Jonathon Jongsma to fix modes in qxl (rhbz 1212201)
This commit is contained in:
		
							parent
							
								
									7a6072325a
								
							
						
					
					
						commit
						a0d9621008
					
				
							
								
								
									
										148
									
								
								drm-qxl-validate-monitors-config-modes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								drm-qxl-validate-monitors-config-modes.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,148 @@ | ||||
| From 9851cf5d02703ab60b58a2335481cc195c72ff9c Mon Sep 17 00:00:00 2001 | ||||
| From: Jonathon Jongsma <jjongsma@redhat.com> | ||||
| Date: Thu, 20 Aug 2015 12:04:32 -0700 | ||||
| Subject: [PATCH] drm/qxl: validate monitors config modes | ||||
| 
 | ||||
| Due to some recent changes in | ||||
| drm_helper_probe_single_connector_modes_merge_bits(), old custom modes | ||||
| were not being pruned properly. In current kernels, | ||||
| drm_mode_validate_basic() is called to sanity-check each mode in the | ||||
| list. If the sanity-check passes, the mode's status gets set to to | ||||
| MODE_OK. In older kernels this check was not done, so old custom modes | ||||
| would still have a status of MODE_UNVERIFIED at this point, and would | ||||
| therefore be pruned later in the function. | ||||
| 
 | ||||
| As a result of this new behavior, the list of modes for a device always | ||||
| includes every custom mode ever configured for the device, with the | ||||
| largest one listed first. Since desktop environments usually choose the | ||||
| first preferred mode when a hotplug event is emitted, this had the | ||||
| result of making it very difficult for the user to reduce the size of | ||||
| the display. | ||||
| 
 | ||||
| The qxl driver did implement the mode_valid connector function, but it | ||||
| was empty. In order to restore the old behavior where old custom modes | ||||
| are pruned, we implement a proper mode_valid function for the qxl | ||||
| driver. This function now checks each mode against the last configured | ||||
| custom mode and the list of standard modes. If the mode doesn't match | ||||
| any of these, its status is set to MODE_BAD so that it will be pruned as | ||||
| expected. | ||||
| 
 | ||||
| Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com> | ||||
| Cc: stable at vger.kernel.org | ||||
| ---
 | ||||
|  drivers/gpu/drm/qxl/qxl_display.c | 66 ++++++++++++++++++++++++--------------- | ||||
|  drivers/gpu/drm/qxl/qxl_drv.h     |  2 ++ | ||||
|  2 files changed, 42 insertions(+), 26 deletions(-) | ||||
| 
 | ||||
| diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
 | ||||
| index a8dbb3ef4e3c..7c6225c84ba6 100644
 | ||||
| --- a/drivers/gpu/drm/qxl/qxl_display.c
 | ||||
| +++ b/drivers/gpu/drm/qxl/qxl_display.c
 | ||||
| @@ -160,9 +160,35 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
 | ||||
|  	*pwidth = head->width; | ||||
|  	*pheight = head->height; | ||||
|  	drm_mode_probed_add(connector, mode); | ||||
| +	/* remember the last custom size for mode validation */
 | ||||
| +	qdev->monitors_config_width = mode->hdisplay;
 | ||||
| +	qdev->monitors_config_height = mode->vdisplay;
 | ||||
|  	return 1; | ||||
|  } | ||||
|   | ||||
| +static struct mode_size {
 | ||||
| +	int w;
 | ||||
| +	int h;
 | ||||
| +} common_modes[] = {
 | ||||
| +	{ 640,  480},
 | ||||
| +	{ 720,  480},
 | ||||
| +	{ 800,  600},
 | ||||
| +	{ 848,  480},
 | ||||
| +	{1024,  768},
 | ||||
| +	{1152,  768},
 | ||||
| +	{1280,  720},
 | ||||
| +	{1280,  800},
 | ||||
| +	{1280,  854},
 | ||||
| +	{1280,  960},
 | ||||
| +	{1280, 1024},
 | ||||
| +	{1440,  900},
 | ||||
| +	{1400, 1050},
 | ||||
| +	{1680, 1050},
 | ||||
| +	{1600, 1200},
 | ||||
| +	{1920, 1080},
 | ||||
| +	{1920, 1200}
 | ||||
| +};
 | ||||
| +
 | ||||
|  static int qxl_add_common_modes(struct drm_connector *connector, | ||||
|                                  unsigned pwidth, | ||||
|                                  unsigned pheight) | ||||
| @@ -170,29 +196,6 @@ static int qxl_add_common_modes(struct drm_connector *connector,
 | ||||
|  	struct drm_device *dev = connector->dev; | ||||
|  	struct drm_display_mode *mode = NULL; | ||||
|  	int i; | ||||
| -	struct mode_size {
 | ||||
| -		int w;
 | ||||
| -		int h;
 | ||||
| -	} common_modes[] = {
 | ||||
| -		{ 640,  480},
 | ||||
| -		{ 720,  480},
 | ||||
| -		{ 800,  600},
 | ||||
| -		{ 848,  480},
 | ||||
| -		{1024,  768},
 | ||||
| -		{1152,  768},
 | ||||
| -		{1280,  720},
 | ||||
| -		{1280,  800},
 | ||||
| -		{1280,  854},
 | ||||
| -		{1280,  960},
 | ||||
| -		{1280, 1024},
 | ||||
| -		{1440,  900},
 | ||||
| -		{1400, 1050},
 | ||||
| -		{1680, 1050},
 | ||||
| -		{1600, 1200},
 | ||||
| -		{1920, 1080},
 | ||||
| -		{1920, 1200}
 | ||||
| -	};
 | ||||
| -
 | ||||
|  	for (i = 0; i < ARRAY_SIZE(common_modes); i++) { | ||||
|  		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, | ||||
|  				    60, false, false, false); | ||||
| @@ -823,11 +826,22 @@ static int qxl_conn_get_modes(struct drm_connector *connector)
 | ||||
|  static int qxl_conn_mode_valid(struct drm_connector *connector, | ||||
|  			       struct drm_display_mode *mode) | ||||
|  { | ||||
| +	struct drm_device *ddev = connector->dev;
 | ||||
| +	struct qxl_device *qdev = ddev->dev_private;
 | ||||
| +	int i;
 | ||||
| +
 | ||||
|  	/* TODO: is this called for user defined modes? (xrandr --add-mode) | ||||
|  	 * TODO: check that the mode fits in the framebuffer */ | ||||
| -	DRM_DEBUG("%s: %dx%d status=%d\n", mode->name, mode->hdisplay,
 | ||||
| -		  mode->vdisplay, mode->status);
 | ||||
| -	return MODE_OK;
 | ||||
| +
 | ||||
| +	if(qdev->monitors_config_width == mode->hdisplay &&
 | ||||
| +	   qdev->monitors_config_height == mode->vdisplay)
 | ||||
| +		return MODE_OK;
 | ||||
| +
 | ||||
| +	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
 | ||||
| +		if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay)
 | ||||
| +			return MODE_OK;
 | ||||
| +	}
 | ||||
| +	return MODE_BAD;
 | ||||
|  } | ||||
|   | ||||
|  static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector) | ||||
| diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
 | ||||
| index d8549690801d..01a86948eb8c 100644
 | ||||
| --- a/drivers/gpu/drm/qxl/qxl_drv.h
 | ||||
| +++ b/drivers/gpu/drm/qxl/qxl_drv.h
 | ||||
| @@ -325,6 +325,8 @@ struct qxl_device {
 | ||||
|  	struct work_struct fb_work; | ||||
|   | ||||
|  	struct drm_property *hotplug_mode_update_property; | ||||
| +	int monitors_config_width;
 | ||||
| +	int monitors_config_height;
 | ||||
|  }; | ||||
|   | ||||
|  /* forward declaration for QXL_INFO_IO */ | ||||
| -- 
 | ||||
| 2.4.3 | ||||
| 
 | ||||
| @ -599,6 +599,9 @@ Patch512: ext4-dont-manipulate-recovery-flag-when-freezing.patch | ||||
| #rhbz 1257534 | ||||
| Patch513: nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch | ||||
| 
 | ||||
| #rhbz 1212201 | ||||
| Patch514: drm-qxl-validate-monitors-config-modes.patch | ||||
| 
 | ||||
| Patch904: kdbus.patch | ||||
| 
 | ||||
| # END OF PATCH DEFINITIONS | ||||
| @ -2039,6 +2042,7 @@ fi | ||||
| * Thu Aug 27 2015 Josh Boyer <jwboyer@fedoraproject.org> - 4.2.0-0.rc8.git2.1 | ||||
| - Linux v4.2-rc8-10-gf9ed72dde34e | ||||
| - Add patch from Hans de Goede to fix nv46 based cards (rhbz 1257534) | ||||
| - Add patch from Jonathon Jongsma to fix modes in qxl (rhbz 1212201) | ||||
| 
 | ||||
| * Wed Aug 26 2015 Josh Boyer <jwboyer@fedoraproject.org> - 4.2.0-0.rc8.git1.1 | ||||
| - Linux v4.2-rc8-7-gf5db4b31b315 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user