drm/qxl: add qxl_add_mode helper function

Add a helper function to add custom video modes to a connector.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Noralf Trønnes <noralf@tronnes.org>
Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-22-kraxel@redhat.com
This commit is contained in:
Gerd Hoffmann 2019-01-18 13:20:18 +01:00
parent feba24de70
commit 1b043677d4
1 changed files with 49 additions and 35 deletions

View File

@ -212,15 +212,36 @@ static int qxl_check_framebuffer(struct qxl_device *qdev,
return qxl_check_mode(qdev, bo->surf.width, bo->surf.height);
}
static int qxl_add_monitors_config_modes(struct drm_connector *connector,
unsigned *pwidth,
unsigned *pheight)
static int qxl_add_mode(struct drm_connector *connector,
unsigned int width,
unsigned int height,
bool preferred)
{
struct drm_device *dev = connector->dev;
struct qxl_device *qdev = dev->dev_private;
struct drm_display_mode *mode = NULL;
int rc;
rc = qxl_check_mode(qdev, width, height);
if (rc != 0)
return 0;
mode = drm_cvt_mode(dev, width, height, 60, false, false, false);
if (preferred)
mode->type |= DRM_MODE_TYPE_PREFERRED;
mode->hdisplay = width;
mode->vdisplay = height;
drm_mode_set_name(mode);
drm_mode_probed_add(connector, mode);
return 1;
}
static int qxl_add_monitors_config_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct qxl_device *qdev = dev->dev_private;
struct qxl_output *output = drm_connector_to_qxl_output(connector);
int h = output->index;
struct drm_display_mode *mode = NULL;
struct qxl_head *head;
if (!qdev->monitors_config)
@ -235,19 +256,7 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
head = &qdev->client_monitors_config->heads[h];
DRM_DEBUG_KMS("head %d is %dx%d\n", h, head->width, head->height);
mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
false);
mode->type |= DRM_MODE_TYPE_PREFERRED;
mode->hdisplay = head->width;
mode->vdisplay = head->height;
drm_mode_set_name(mode);
*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;
return qxl_add_mode(connector, head->width, head->height, true);
}
static struct mode_size {
@ -273,22 +282,16 @@ static struct mode_size {
{1920, 1200}
};
static int qxl_add_common_modes(struct drm_connector *connector,
unsigned int pwidth,
unsigned int pheight)
static int qxl_add_common_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode = NULL;
int i;
int i, ret = 0;
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);
if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
mode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
}
return i - 1;
for (i = 0; i < ARRAY_SIZE(common_modes); i++)
ret += qxl_add_mode(connector,
common_modes[i].w,
common_modes[i].h,
false);
return ret;
}
static void qxl_send_monitors_config(struct qxl_device *qdev)
@ -991,14 +994,25 @@ free_mem:
static int qxl_conn_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct qxl_device *qdev = dev->dev_private;
struct qxl_output *output = drm_connector_to_qxl_output(connector);
unsigned int pwidth = 1024;
unsigned int pheight = 768;
int ret = 0;
ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
if (ret < 0)
return ret;
ret += qxl_add_common_modes(connector, pwidth, pheight);
if (qdev->client_monitors_config) {
struct qxl_head *head;
head = &qdev->client_monitors_config->heads[output->index];
if (head->width)
pwidth = head->width;
if (head->height)
pheight = head->height;
}
ret += qxl_add_common_modes(connector);
ret += qxl_add_monitors_config_modes(connector);
drm_set_preferred_mode(connector, pwidth, pheight);
return ret;
}