diff options
author | Dave Airlie <airlied@redhat.com> | 2013-07-05 10:55:33 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-07-05 10:55:33 +1000 |
commit | 7c6ca3040e9ac174e6d2189811da603e9c19a150 (patch) | |
tree | 4cf36c62b7a7b6c6a2ad66e4d79d3f5912a3438b | |
parent | 69163ea82732894e8c1e17df4010372ed078efdd (diff) | |
parent | 5ff91e442652ec33a648c3b9ae5025faaff1e813 (diff) |
Merge branch 'qxl-next' of git://people.freedesktop.org/~airlied/linux into drm-next
Adds 3 features that UMS had to the KMS driver.
dynamic resizing - resizing remote-viewer makes guest resize
multiple crtcs - remote-viewer can access > 1 crtc.
suspend/resume/hibernate: guests can do suspend/resume/hibernate now.
* 'qxl-next' of git://people.freedesktop.org/~airlied/linux:
qxl: use drm helper hotplug support
qxl: add suspend/resume/hibernate support.
qxl: add fb and ttm entry points for use by suspend/resume.
qxl: add ring prep code for s/r
qxl: prepare memslot code for suspend/resume
qxl: split monitors_config object creation out.
drm/qxl: set time on drawables from userspace
drm/qxl: add support for > 1 output
drm/qxl: make dynamic resizing work properly.
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_cmd.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_display.c | 229 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.c | 138 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.h | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_fb.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_ioctl.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_kms.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_object.c | 10 |
8 files changed, 326 insertions, 128 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index f86771481317..93c2f2cceb51 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -51,2 +51,7 @@ void qxl_ring_free(struct qxl_ring *ring) +void qxl_ring_init_hdr(struct qxl_ring *ring) +{ + ring->ring->header.notify_on_prod = ring->n_elements; +} + struct qxl_ring * @@ -71,3 +76,3 @@ qxl_ring_create(struct qxl_ring_header *header, if (set_prod_notify) - header->notify_on_prod = ring->n_elements; + qxl_ring_init_hdr(ring); spin_lock_init(&ring->lock); @@ -89,3 +94,3 @@ static int qxl_check_header(struct qxl_ring *ring) -static int qxl_check_idle(struct qxl_ring *ring) +int qxl_check_idle(struct qxl_ring *ring) { @@ -377,4 +382,4 @@ void qxl_io_destroy_primary(struct qxl_device *qdev) -void qxl_io_create_primary(struct qxl_device *qdev, unsigned width, - unsigned height, unsigned offset, struct qxl_bo *bo) +void qxl_io_create_primary(struct qxl_device *qdev, + unsigned offset, struct qxl_bo *bo) { @@ -386,4 +391,4 @@ void qxl_io_create_primary(struct qxl_device *qdev, unsigned width, create->format = bo->surf.format; - create->width = width; - create->height = height; + create->width = bo->surf.width; + create->height = bo->surf.height; create->stride = bo->surf.stride; diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 686a937675cb..f76f5dd7bfc4 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -32,49 +32,5 @@ -static void qxl_crtc_set_to_mode(struct qxl_device *qdev, - struct drm_connector *connector, - struct qxl_head *head) +static bool qxl_head_enabled(struct qxl_head *head) { - struct drm_device *dev = connector->dev; - struct drm_display_mode *mode, *t; - int width = head->width; - int height = head->height; - - if (width < 320 || height < 240) { - qxl_io_log(qdev, "%s: bad head: %dx%d", width, height); - width = 1024; - height = 768; - } - if (width * height * 4 > 16*1024*1024) { - width = 1024; - height = 768; - } - /* TODO: go over regular modes and removed preferred? */ - list_for_each_entry_safe(mode, t, &connector->probed_modes, head) - drm_mode_remove(connector, mode); - mode = drm_cvt_mode(dev, width, height, 60, false, false, false); - mode->type |= DRM_MODE_TYPE_PREFERRED; - mode->status = MODE_OK; - drm_mode_probed_add(connector, mode); - qxl_io_log(qdev, "%s: %d x %d\n", __func__, width, height); -} - -void qxl_crtc_set_from_monitors_config(struct qxl_device *qdev) -{ - struct drm_connector *connector; - int i; - struct drm_device *dev = qdev->ddev; - - i = 0; - qxl_io_log(qdev, "%s: %d, %d\n", __func__, - dev->mode_config.num_connector, - qdev->monitors_config->count); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (i > qdev->monitors_config->count) { - /* crtc will be reported as disabled */ - continue; - } - qxl_crtc_set_to_mode(qdev, connector, - &qdev->monitors_config->heads[i]); - ++i; - } + return head->width && head->height; } @@ -108,3 +64,2 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) - BUG_ON(!qdev->monitors_config); num_monitors = qdev->rom->client_monitors_config.count; @@ -119,4 +74,4 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) if (num_monitors > qdev->monitors_config->max_allowed) { - DRM_INFO("client monitors list will be truncated: %d < %d\n", - qdev->monitors_config->max_allowed, num_monitors); + DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n", + qdev->monitors_config->max_allowed, num_monitors); num_monitors = qdev->monitors_config->max_allowed; @@ -134,14 +89,11 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) &qdev->client_monitors_config->heads[i]; - struct qxl_head *head = &qdev->monitors_config->heads[i]; - client_head->x = head->x = c_rect->left; - client_head->y = head->y = c_rect->top; - client_head->width = head->width = - c_rect->right - c_rect->left; - client_head->height = head->height = - c_rect->bottom - c_rect->top; - client_head->surface_id = head->surface_id = 0; - client_head->id = head->id = i; - client_head->flags = head->flags = 0; - QXL_DEBUG(qdev, "read %dx%d+%d+%d\n", head->width, head->height, - head->x, head->y); + client_head->x = c_rect->left; + client_head->y = c_rect->top; + client_head->width = c_rect->right - c_rect->left; + client_head->height = c_rect->bottom - c_rect->top; + client_head->surface_id = 0; + client_head->id = i; + client_head->flags = 0; + DRM_DEBUG_KMS("read %dx%d+%d+%d\n", client_head->width, client_head->height, + client_head->x, client_head->y); } @@ -157,6 +109,3 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev) } - qxl_crtc_set_from_monitors_config(qdev); - /* fire off a uevent and let userspace tell us what to do */ - qxl_io_log(qdev, "calling drm_sysfs_hotplug_event\n"); - drm_sysfs_hotplug_event(qdev->ddev); + drm_helper_hpd_irq_event(qdev->ddev); } @@ -172,5 +121,5 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector) - if (!qdev->monitors_config) + if (!qdev->client_monitors_config) return 0; - head = &qdev->monitors_config->heads[h]; + head = &qdev->client_monitors_config->heads[h]; @@ -501,3 +450,3 @@ qxl_send_monitors_config(struct qxl_device *qdev) - if (head->y > 8192 || head->y < head->x || + if (head->y > 8192 || head->x > 8192 || head->width > 8192 || head->height > 8192) { @@ -512,12 +461,15 @@ qxl_send_monitors_config(struct qxl_device *qdev) -static void qxl_monitors_config_set_single(struct qxl_device *qdev, - unsigned x, unsigned y, - unsigned width, unsigned height) +static void qxl_monitors_config_set(struct qxl_device *qdev, + int index, + unsigned x, unsigned y, + unsigned width, unsigned height, + unsigned surf_id) { - DRM_DEBUG("%dx%d+%d+%d\n", width, height, x, y); - qdev->monitors_config->count = 1; - qdev->monitors_config->heads[0].x = x; - qdev->monitors_config->heads[0].y = y; - qdev->monitors_config->heads[0].width = width; - qdev->monitors_config->heads[0].height = height; + DRM_DEBUG_KMS("%d:%dx%d+%d+%d\n", index, width, height, x, y); + qdev->monitors_config->heads[index].x = x; + qdev->monitors_config->heads[index].y = y; + qdev->monitors_config->heads[index].width = width; + qdev->monitors_config->heads[index].height = height; + qdev->monitors_config->heads[index].surface_id = surf_id; + } @@ -535,2 +487,3 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, struct qxl_bo *bo, *old_bo = NULL; + struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); uint32_t width, height, base_offset; @@ -538,3 +491,3 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, int ret; - + int surf_id; if (!crtc->fb) { @@ -562,3 +515,4 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, - recreate_primary = true; + if (qcrtc->index == 0) + recreate_primary = true; @@ -583,4 +537,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, bo->surf.height, bo->surf.stride, bo->surf.format); - qxl_io_create_primary(qdev, width, height, base_offset, bo); + qxl_io_create_primary(qdev, base_offset, bo); bo->is_primary = true; + surf_id = 0; + } else { + surf_id = bo->surface_id; } @@ -594,7 +551,5 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, - if (qdev->monitors_config->count == 0) { - qxl_monitors_config_set_single(qdev, x, y, - mode->hdisplay, - mode->vdisplay); - } + qxl_monitors_config_set(qdev, qcrtc->index, x, y, + mode->hdisplay, + mode->vdisplay, surf_id); return 0; @@ -614,4 +569,25 @@ static void qxl_crtc_commit(struct drm_crtc *crtc) +static void qxl_crtc_disable(struct drm_crtc *crtc) +{ + struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct qxl_device *qdev = dev->dev_private; + if (crtc->fb) { + struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->fb); + struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); + int ret; + ret = qxl_bo_reserve(bo, false); + qxl_bo_unpin(bo); + qxl_bo_unreserve(bo); + crtc->fb = NULL; + } + + qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0); + + qxl_send_monitors_config(qdev); +} + static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { .dpms = qxl_crtc_dpms, + .disable = qxl_crtc_disable, .mode_fixup = qxl_crtc_mode_fixup, @@ -622,3 +598,3 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { -static int qdev_crtc_init(struct drm_device *dev, int num_crtc) +static int qdev_crtc_init(struct drm_device *dev, int crtc_id) { @@ -631,3 +607,3 @@ static int qdev_crtc_init(struct drm_device *dev, int num_crtc) drm_crtc_init(dev, &qxl_crtc->base, &qxl_crtc_funcs); - + qxl_crtc->index = crtc_id; drm_mode_crtc_set_gamma_size(&qxl_crtc->base, 256); @@ -659,2 +635,3 @@ static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev, int i; + struct qxl_output *output = drm_encoder_to_qxl_output(encoder); struct qxl_head *head; @@ -664,9 +641,3 @@ static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev, /* TODO: ugly, do better */ - for (i = 0 ; (encoder->possible_crtcs != (1 << i)) && i < 32; ++i) - ; - if (encoder->possible_crtcs != (1 << i)) { - DRM_ERROR("encoder has wrong possible_crtcs: %x\n", - encoder->possible_crtcs); - return; - } + i = output->index; if (!qdev->monitors_config || @@ -688,3 +659,2 @@ static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev, head->id = i; - head->surface_id = 0; if (encoder->crtc->enabled) { @@ -703,4 +673,4 @@ static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev, } - DRM_DEBUG("setting head %d to +%d+%d %dx%d\n", - i, head->x, head->y, head->width, head->height); + DRM_DEBUG_KMS("setting head %d to +%d+%d %dx%d out of %d\n", + i, head->x, head->y, head->width, head->height, qdev->monitors_config->count); head->flags = 0; @@ -799,4 +769,5 @@ static enum drm_connector_status qxl_conn_detect( connected = (output->index == 0) || - (qdev->monitors_config && - qdev->monitors_config->count > output->index); + (qdev->client_monitors_config && + qdev->client_monitors_config->count > output->index && + qxl_head_enabled(&qdev->client_monitors_config->heads[output->index])); @@ -864,2 +835,4 @@ static int qdev_output_init(struct drm_device *dev, int num_output) + /* we get HPD via client monitors config */ + connector->polled = DRM_CONNECTOR_POLL_HPD; encoder->possible_crtcs = 1 << num_output; @@ -903,12 +876,10 @@ static const struct drm_mode_config_funcs qxl_mode_funcs = { -int qxl_modeset_init(struct qxl_device *qdev) +int qxl_create_monitors_object(struct qxl_device *qdev) { - int i; int ret; struct drm_gem_object *gobj; - int max_allowed = QXL_NUM_OUTPUTS; + int max_allowed = qxl_num_crtc; int monitors_config_size = sizeof(struct qxl_monitors_config) + - max_allowed * sizeof(struct qxl_head); + max_allowed * sizeof(struct qxl_head); - drm_mode_config_init(qdev->ddev); ret = qxl_gem_object_create(qdev, monitors_config_size, 0, @@ -921,3 +892,17 @@ int qxl_modeset_init(struct qxl_device *qdev) qdev->monitors_config_bo = gem_to_qxl_bo(gobj); + + ret = qxl_bo_reserve(qdev->monitors_config_bo, false); + if (ret) + return ret; + + ret = qxl_bo_pin(qdev->monitors_config_bo, QXL_GEM_DOMAIN_VRAM, NULL); + if (ret) { + qxl_bo_unreserve(qdev->monitors_config_bo); + return ret; + } + + qxl_bo_unreserve(qdev->monitors_config_bo); + qxl_bo_kmap(qdev->monitors_config_bo, NULL); + qdev->monitors_config = qdev->monitors_config_bo->kptr; @@ -928,2 +913,34 @@ int qxl_modeset_init(struct qxl_device *qdev) qdev->monitors_config->max_allowed = max_allowed; + return 0; +} + +int qxl_destroy_monitors_object(struct qxl_device *qdev) +{ + int ret; + + qdev->monitors_config = NULL; + qdev->ram_header->monitors_config = 0; + + qxl_bo_kunmap(qdev->monitors_config_bo); + ret = qxl_bo_reserve(qdev->monitors_config_bo, false); + if (ret) + return ret; + + qxl_bo_unpin(qdev->monitors_config_bo); + qxl_bo_unreserve(qdev->monitors_config_bo); + + qxl_bo_unref(&qdev->monitors_config_bo); + return 0; +} + +int qxl_modeset_init(struct qxl_device *qdev) +{ + int i; + int ret; + + drm_mode_config_init(qdev->ddev); + + ret = qxl_create_monitors_object(qdev); + if (ret) + return ret; @@ -938,3 +955,3 @@ int qxl_modeset_init(struct qxl_device *qdev) qdev->ddev->mode_config.fb_base = qdev->vram_base; - for (i = 0 ; i < QXL_NUM_OUTPUTS; ++i) { + for (i = 0 ; i < qxl_num_crtc; ++i) { qdev_crtc_init(qdev->ddev, i); @@ -955,2 +972,4 @@ void qxl_modeset_fini(struct qxl_device *qdev) qxl_fbdev_fini(qdev); + + qxl_destroy_monitors_object(qdev); if (qdev->mode_info.mode_config_initialized) { diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index aa291d8a98a2..df0b577a6608 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -35,4 +35,5 @@ #include "drm/drm.h" - +#include "drm_crtc_helper.h" #include "qxl_drv.h" +#include "qxl_object.h" @@ -49,2 +50,3 @@ MODULE_DEVICE_TABLE(pci, pciidlist); static int qxl_modeset = -1; +int qxl_num_crtc = 4; @@ -53,2 +55,5 @@ module_param_named(modeset, qxl_modeset, int, 0400); +MODULE_PARM_DESC(num_heads, "Number of virtual crtcs to expose (default 4)"); +module_param_named(num_heads, qxl_num_crtc, int, 0400); + static struct drm_driver qxl_driver; @@ -75,9 +80,2 @@ qxl_pci_remove(struct pci_dev *pdev) -static struct pci_driver qxl_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, - .probe = qxl_pci_probe, - .remove = qxl_pci_remove, -}; - static const struct file_operations qxl_fops = { @@ -92,2 +90,126 @@ static const struct file_operations qxl_fops = { +static int qxl_drm_freeze(struct drm_device *dev) +{ + struct pci_dev *pdev = dev->pdev; + struct qxl_device *qdev = dev->dev_private; + struct drm_crtc *crtc; + + drm_kms_helper_poll_disable(dev); + + console_lock(); + qxl_fbdev_set_suspend(qdev, 1); + console_unlock(); + + /* unpin the front buffers */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + if (crtc->enabled) + (*crtc_funcs->disable)(crtc); + } + + qxl_destroy_monitors_object(qdev); + qxl_surf_evict(qdev); + qxl_vram_evict(qdev); + + while (!qxl_check_idle(qdev->command_ring)); + while (!qxl_check_idle(qdev->release_ring)) + qxl_queue_garbage_collect(qdev, 1); + + pci_save_state(pdev); + + return 0; +} + +static int qxl_drm_resume(struct drm_device *dev, bool thaw) +{ + struct qxl_device *qdev = dev->dev_private; + + qdev->ram_header->int_mask = QXL_INTERRUPT_MASK; + if (!thaw) { + qxl_reinit_memslots(qdev); + qxl_ring_init_hdr(qdev->release_ring); + } + + qxl_create_monitors_object(qdev); + drm_helper_resume_force_mode(dev); + + console_lock(); + qxl_fbdev_set_suspend(qdev, 0); + console_unlock(); + + drm_kms_helper_poll_enable(dev); + return 0; +} + +static int qxl_pm_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + int error; + + error = qxl_drm_freeze(drm_dev); + if (error) + return error; + + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + return 0; +} + +static int qxl_pm_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + if (pci_enable_device(pdev)) { + return -EIO; + } + + return qxl_drm_resume(drm_dev, false); +} + +static int qxl_pm_thaw(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + + return qxl_drm_resume(drm_dev, true); +} + +static int qxl_pm_freeze(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + + return qxl_drm_freeze(drm_dev); +} + +static int qxl_pm_restore(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct qxl_device *qdev = drm_dev->dev_private; + + qxl_io_reset(qdev); + return qxl_drm_resume(drm_dev, false); +} + +static const struct dev_pm_ops qxl_pm_ops = { + .suspend = qxl_pm_suspend, + .resume = qxl_pm_resume, + .freeze = qxl_pm_freeze, + .thaw = qxl_pm_thaw, + .poweroff = qxl_pm_freeze, + .restore = qxl_pm_restore, +}; +static struct pci_driver qxl_pci_driver = { + .name = DRIVER_NAME, + .id_table = pciidlist, + .probe = qxl_pci_probe, + .remove = qxl_pci_remove, + .driver.pm = &qxl_pm_ops, +}; + static struct drm_driver qxl_driver = { diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 43d06ab28a21..aacb791464a3 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -57,4 +57,2 @@ -#define QXL_NUM_OUTPUTS 1 - #define QXL_DEBUGFS_MAX_COMPONENTS 32 @@ -62,2 +60,3 @@ extern int qxl_log_level; +extern int qxl_num_crtc; @@ -141,2 +140,3 @@ struct qxl_crtc { struct drm_crtc base; + int index; int cur_x; @@ -158,3 +158,3 @@ struct qxl_framebuffer { #define drm_connector_to_qxl_output(x) container_of(x, struct qxl_output, base) -#define drm_encoder_to_qxl_output(x) container_of(x, struct qxl_output, base) +#define drm_encoder_to_qxl_output(x) container_of(x, struct qxl_output, enc) #define to_qxl_framebuffer(x) container_of(x, struct qxl_framebuffer, base) @@ -333,2 +333,6 @@ void qxl_bo_fini(struct qxl_device *qdev); +void qxl_reinit_memslots(struct qxl_device *qdev); +int qxl_surf_evict(struct qxl_device *qdev); +int qxl_vram_evict(struct qxl_device *qdev); + struct qxl_ring *qxl_ring_create(struct qxl_ring_header *header, @@ -340,2 +344,4 @@ struct qxl_ring *qxl_ring_create(struct qxl_ring_header *header, void qxl_ring_free(struct qxl_ring *ring); +void qxl_ring_init_hdr(struct qxl_ring *ring); +int qxl_check_idle(struct qxl_ring *ring); @@ -367,2 +373,3 @@ int qxl_get_handle_for_primary_fb(struct qxl_device *qdev, uint32_t *handle); +void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state); @@ -376,2 +383,4 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev); void qxl_send_monitors_config(struct qxl_device *qdev); +int qxl_create_monitors_object(struct qxl_device *qdev); +int qxl_destroy_monitors_object(struct qxl_device *qdev); @@ -437,3 +446,3 @@ void qxl_update_screen(struct qxl_device *qxl); void qxl_io_create_primary(struct qxl_device *qdev, - unsigned width, unsigned height, unsigned offset, + unsigned offset, struct qxl_bo *bo); @@ -530,2 +539,3 @@ irqreturn_t qxl_irq_handler(DRM_IRQ_ARGS); int qxl_fb_init(struct qxl_device *qdev); +bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj); diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index 4b955b04ce1e..76f39d88d684 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -540,3 +540,3 @@ int qxl_fbdev_init(struct qxl_device *qdev) ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper, - 1 /* num_crtc - QXL supports just 1 */, + qxl_num_crtc /* num_crtc - QXL supports just 1 */, QXLFB_CONN_LIMIT); @@ -562,2 +562,12 @@ void qxl_fbdev_fini(struct qxl_device *qdev) +void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state) +{ + fb_set_suspend(qdev->mode_info.qfbdev->helper.fbdev, state); +} +bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj) +{ + if (qobj == gem_to_qxl_bo(qdev->mode_info.qfbdev->qfb.obj)) + return true; + return false; +} diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index a4b71b25fa53..6ba49d9922f2 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -185,2 +185,8 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data, unwritten = __copy_from_user_inatomic_nocache(fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), (void *)(unsigned long)user_cmd.command, user_cmd.command_size); + + { + struct qxl_drawable *draw = fb_cmd; + + draw->mm_time = qdev->rom->mm_clock; + } qxl_bo_kunmap_atomic_page(qdev, cmd_bo, fb_cmd); diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index e27ce2a907cf..9e8da9ee9731 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -28,2 +28,3 @@ +#include <drm/drm_crtc_helper.h> #include <linux/io-mapping.h> @@ -74,2 +75,10 @@ static bool qxl_check_device(struct qxl_device *qdev) +static void setup_hw_slot(struct qxl_device *qdev, int slot_index, + struct qxl_memslot *slot) +{ + qdev->ram_header->mem_slot.mem_start = slot->start_phys_addr; + qdev->ram_header->mem_slot.mem_end = slot->end_phys_addr; + qxl_io_memslot_add(qdev, slot_index); +} + static uint8_t setup_slot(struct qxl_device *qdev, uint8_t slot_index_offset, @@ -80,3 +89,2 @@ static uint8_t setup_slot(struct qxl_device *qdev, uint8_t slot_index_offset, uint8_t slot_index; - struct qxl_ram_header *ram_header = qdev->ram_header; @@ -86,5 +94,5 @@ static uint8_t setup_slot(struct qxl_device *qdev, uint8_t slot_index_offset, slot->end_phys_addr = end_phys_addr; - ram_header->mem_slot.mem_start = slot->start_phys_addr; - ram_header->mem_slot.mem_end = slot->end_phys_addr; - qxl_io_memslot_add(qdev, slot_index); + + setup_hw_slot(qdev, slot_index, slot); + slot->generation = qdev->rom->slot_generation; @@ -97,2 +105,8 @@ static uint8_t setup_slot(struct qxl_device *qdev, uint8_t slot_index_offset, +void qxl_reinit_memslots(struct qxl_device *qdev) +{ + setup_hw_slot(qdev, qdev->main_mem_slot, &qdev->mem_slots[qdev->main_mem_slot]); + setup_hw_slot(qdev, qdev->surfaces_mem_slot, &qdev->mem_slots[qdev->surfaces_mem_slot]); +} + static void qxl_gc_work(struct work_struct *work) @@ -296,2 +310,4 @@ int qxl_driver_load(struct drm_device *dev, unsigned long flags) + drm_kms_helper_poll_init(qdev->ddev); + return 0; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index d9b12e7bc6e1..1191fe7788c9 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -365 +365,11 @@ int qxl_bo_list_add(struct qxl_reloc_list *reloc_list, struct qxl_bo *bo) } + +int qxl_surf_evict(struct qxl_device *qdev) +{ + return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_PRIV0); +} + +int qxl_vram_evict(struct qxl_device *qdev) +{ + return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_VRAM); +} |