aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2018-04-20 03:19:03 -0400
committerGerd Hoffmann <kraxel@redhat.com>2018-04-27 02:58:05 -0400
commita6d3c4d79822658e7f2f9c4b73237fe2b057ed67 (patch)
tree515f73bff6567d208e3825392bea3e1dac2c157d /drivers/gpu
parent998010bfae6ebaac68af905bef9f6e276f775254 (diff)
qxl: hook monitors_config updates into crtc, not encoder.
The encoder callbacks are only called in case the video mode changes. So any layout changes without mode changes will go unnoticed. Add qxl_crtc_update_monitors_config(), based on the old qxl_write_monitors_config_for_encoder() function. Hook it into the enable, disable and flush atomic crtc callbacks. Remove monitors_config updates from all other places. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1544322 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: http://patchwork.freedesktop.org/patch/msgid/20180420071904.24276-4-kraxel@redhat.com
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/qxl/qxl_cmd.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c156
2 files changed, 66 insertions, 92 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 850f8d7d37ce..95db20f2145f 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -371,6 +371,7 @@ void qxl_io_flush_surfaces(struct qxl_device *qdev)
371void qxl_io_destroy_primary(struct qxl_device *qdev) 371void qxl_io_destroy_primary(struct qxl_device *qdev)
372{ 372{
373 wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC); 373 wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC);
374 qdev->primary_created = false;
374} 375}
375 376
376void qxl_io_create_primary(struct qxl_device *qdev, 377void qxl_io_create_primary(struct qxl_device *qdev,
@@ -396,6 +397,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,
396 create->type = QXL_SURF_TYPE_PRIMARY; 397 create->type = QXL_SURF_TYPE_PRIMARY;
397 398
398 wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC); 399 wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC);
400 qdev->primary_created = true;
399} 401}
400 402
401void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) 403void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 7d08a26c3a8b..58959733ae16 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -281,6 +281,66 @@ static void qxl_send_monitors_config(struct qxl_device *qdev)
281 qxl_io_monitors_config(qdev); 281 qxl_io_monitors_config(qdev);
282} 282}
283 283
284static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
285 const char *reason)
286{
287 struct drm_device *dev = crtc->dev;
288 struct qxl_device *qdev = dev->dev_private;
289 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
290 struct qxl_head head;
291 int oldcount, i = qcrtc->index;
292
293 if (!qdev->primary_created) {
294 DRM_DEBUG_KMS("no primary surface, skip (%s)\n", reason);
295 return;
296 }
297
298 if (!qdev->monitors_config ||
299 qdev->monitors_config->max_allowed <= i)
300 return;
301
302 head.id = i;
303 head.flags = 0;
304 oldcount = qdev->monitors_config->count;
305 if (crtc->state->active) {
306 struct drm_display_mode *mode = &crtc->mode;
307 head.width = mode->hdisplay;
308 head.height = mode->vdisplay;
309 head.x = crtc->x;
310 head.y = crtc->y;
311 if (qdev->monitors_config->count < i + 1)
312 qdev->monitors_config->count = i + 1;
313 } else if (i > 0) {
314 head.width = 0;
315 head.height = 0;
316 head.x = 0;
317 head.y = 0;
318 if (qdev->monitors_config->count == i + 1)
319 qdev->monitors_config->count = i;
320 } else {
321 DRM_DEBUG_KMS("inactive head 0, skip (%s)\n", reason);
322 return;
323 }
324
325 if (head.width == qdev->monitors_config->heads[i].width &&
326 head.height == qdev->monitors_config->heads[i].height &&
327 head.x == qdev->monitors_config->heads[i].x &&
328 head.y == qdev->monitors_config->heads[i].y &&
329 oldcount == qdev->monitors_config->count)
330 return;
331
332 DRM_DEBUG_KMS("head %d, %dx%d, at +%d+%d, %s (%s)\n",
333 i, head.width, head.height, head.x, head.y,
334 crtc->state->active ? "on" : "off", reason);
335 if (oldcount != qdev->monitors_config->count)
336 DRM_DEBUG_KMS("active heads %d -> %d (%d total)\n",
337 oldcount, qdev->monitors_config->count,
338 qdev->monitors_config->max_allowed);
339
340 qdev->monitors_config->heads[i] = head;
341 qxl_send_monitors_config(qdev);
342}
343
284static void qxl_crtc_atomic_flush(struct drm_crtc *crtc, 344static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
285 struct drm_crtc_state *old_crtc_state) 345 struct drm_crtc_state *old_crtc_state)
286{ 346{
@@ -296,6 +356,8 @@ static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
296 drm_crtc_send_vblank_event(crtc, event); 356 drm_crtc_send_vblank_event(crtc, event);
297 spin_unlock_irqrestore(&dev->event_lock, flags); 357 spin_unlock_irqrestore(&dev->event_lock, flags);
298 } 358 }
359
360 qxl_crtc_update_monitors_config(crtc, "flush");
299} 361}
300 362
301static void qxl_crtc_destroy(struct drm_crtc *crtc) 363static void qxl_crtc_destroy(struct drm_crtc *crtc)
@@ -401,55 +463,20 @@ static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc,
401 return true; 463 return true;
402} 464}
403 465
404static void qxl_monitors_config_set(struct qxl_device *qdev,
405 int index,
406 unsigned x, unsigned y,
407 unsigned width, unsigned height,
408 unsigned surf_id)
409{
410 DRM_DEBUG_KMS("%d:%dx%d+%d+%d\n", index, width, height, x, y);
411 qdev->monitors_config->heads[index].x = x;
412 qdev->monitors_config->heads[index].y = y;
413 qdev->monitors_config->heads[index].width = width;
414 qdev->monitors_config->heads[index].height = height;
415 qdev->monitors_config->heads[index].surface_id = surf_id;
416
417}
418
419static void qxl_mode_set_nofb(struct drm_crtc *crtc)
420{
421 struct qxl_device *qdev = crtc->dev->dev_private;
422 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
423 struct drm_display_mode *mode = &crtc->mode;
424
425 DRM_DEBUG("Mode set (%d,%d)\n",
426 mode->hdisplay, mode->vdisplay);
427
428 qxl_monitors_config_set(qdev, qcrtc->index, 0, 0,
429 mode->hdisplay, mode->vdisplay, 0);
430
431}
432
433static void qxl_crtc_atomic_enable(struct drm_crtc *crtc, 466static void qxl_crtc_atomic_enable(struct drm_crtc *crtc,
434 struct drm_crtc_state *old_state) 467 struct drm_crtc_state *old_state)
435{ 468{
436 DRM_DEBUG("\n"); 469 qxl_crtc_update_monitors_config(crtc, "enable");
437} 470}
438 471
439static void qxl_crtc_atomic_disable(struct drm_crtc *crtc, 472static void qxl_crtc_atomic_disable(struct drm_crtc *crtc,
440 struct drm_crtc_state *old_state) 473 struct drm_crtc_state *old_state)
441{ 474{
442 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); 475 qxl_crtc_update_monitors_config(crtc, "disable");
443 struct qxl_device *qdev = crtc->dev->dev_private;
444
445 qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
446
447 qxl_send_monitors_config(qdev);
448} 476}
449 477
450static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { 478static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
451 .mode_fixup = qxl_crtc_mode_fixup, 479 .mode_fixup = qxl_crtc_mode_fixup,
452 .mode_set_nofb = qxl_mode_set_nofb,
453 .atomic_flush = qxl_crtc_atomic_flush, 480 .atomic_flush = qxl_crtc_atomic_flush,
454 .atomic_enable = qxl_crtc_atomic_enable, 481 .atomic_enable = qxl_crtc_atomic_enable,
455 .atomic_disable = qxl_crtc_atomic_disable, 482 .atomic_disable = qxl_crtc_atomic_disable,
@@ -939,61 +966,8 @@ static void qxl_enc_prepare(struct drm_encoder *encoder)
939 DRM_DEBUG("\n"); 966 DRM_DEBUG("\n");
940} 967}
941 968
942static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev,
943 struct drm_encoder *encoder)
944{
945 int i;
946 struct qxl_output *output = drm_encoder_to_qxl_output(encoder);
947 struct qxl_head *head;
948 struct drm_display_mode *mode;
949
950 BUG_ON(!encoder);
951 /* TODO: ugly, do better */
952 i = output->index;
953 if (!qdev->monitors_config ||
954 qdev->monitors_config->max_allowed <= i) {
955 DRM_ERROR(
956 "head number too large or missing monitors config: %p, %d",
957 qdev->monitors_config,
958 qdev->monitors_config ?
959 qdev->monitors_config->max_allowed : -1);
960 return;
961 }
962 if (!encoder->crtc) {
963 DRM_ERROR("missing crtc on encoder %p\n", encoder);
964 return;
965 }
966 if (i != 0)
967 DRM_DEBUG("missing for multiple monitors: no head holes\n");
968 head = &qdev->monitors_config->heads[i];
969 head->id = i;
970 if (encoder->crtc->enabled) {
971 mode = &encoder->crtc->mode;
972 head->width = mode->hdisplay;
973 head->height = mode->vdisplay;
974 head->x = encoder->crtc->x;
975 head->y = encoder->crtc->y;
976 if (qdev->monitors_config->count < i + 1)
977 qdev->monitors_config->count = i + 1;
978 } else {
979 head->width = 0;
980 head->height = 0;
981 head->x = 0;
982 head->y = 0;
983 }
984 DRM_DEBUG_KMS("setting head %d to +%d+%d %dx%d out of %d\n",
985 i, head->x, head->y, head->width, head->height, qdev->monitors_config->count);
986 head->flags = 0;
987 /* TODO - somewhere else to call this for multiple monitors
988 * (config_commit?) */
989 qxl_send_monitors_config(qdev);
990}
991
992static void qxl_enc_commit(struct drm_encoder *encoder) 969static void qxl_enc_commit(struct drm_encoder *encoder)
993{ 970{
994 struct qxl_device *qdev = encoder->dev->dev_private;
995
996 qxl_write_monitors_config_for_encoder(qdev, encoder);
997 DRM_DEBUG("\n"); 971 DRM_DEBUG("\n");
998} 972}
999 973
@@ -1080,8 +1054,6 @@ static enum drm_connector_status qxl_conn_detect(
1080 qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]); 1054 qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]);
1081 1055
1082 DRM_DEBUG("#%d connected: %d\n", output->index, connected); 1056 DRM_DEBUG("#%d connected: %d\n", output->index, connected);
1083 if (!connected)
1084 qxl_monitors_config_set(qdev, output->index, 0, 0, 0, 0, 0);
1085 1057
1086 return connected ? connector_status_connected 1058 return connected ? connector_status_connected
1087 : connector_status_disconnected; 1059 : connector_status_disconnected;