summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/qxl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/qxl')
-rw-r--r--drivers/gpu/drm/qxl/Kconfig1
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c51
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c1
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h3
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_gem.c6
-rw-r--r--drivers/gpu/drm/qxl/qxl_kms.c42
-rw-r--r--drivers/gpu/drm/qxl/qxl_ttm.c2
8 files changed, 79 insertions, 29 deletions
diff --git a/drivers/gpu/drm/qxl/Kconfig b/drivers/gpu/drm/qxl/Kconfig
index d6c12796023..037d324bf58 100644
--- a/drivers/gpu/drm/qxl/Kconfig
+++ b/drivers/gpu/drm/qxl/Kconfig
@@ -6,6 +6,7 @@ config DRM_QXL
select FB_SYS_IMAGEBLIT
select FB_DEFERRED_IO
select DRM_KMS_HELPER
+ select DRM_KMS_FB_HELPER
select DRM_TTM
help
QXL virtual GPU for Spice virtualization desktop integration. Do not enable this driver unless your distro ships a corresponding X.org QXL driver that can handle kernel modesetting.
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 835caba026d..5e827c29d19 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -107,10 +107,17 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
qxl_io_log(qdev, "failed crc check for client_monitors_config,"
" retrying\n");
}
- drm_helper_hpd_irq_event(qdev->ddev);
+
+ if (!drm_helper_hpd_irq_event(qdev->ddev)) {
+ /* notify that the monitor configuration changed, to
+ adjust at the arbitrary resolution */
+ drm_kms_helper_hotplug_event(qdev->ddev);
+ }
}
-static int qxl_add_monitors_config_modes(struct drm_connector *connector)
+static int qxl_add_monitors_config_modes(struct drm_connector *connector,
+ unsigned *pwidth,
+ unsigned *pheight)
{
struct drm_device *dev = connector->dev;
struct qxl_device *qdev = dev->dev_private;
@@ -126,11 +133,15 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector)
mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
false);
mode->type |= DRM_MODE_TYPE_PREFERRED;
+ *pwidth = head->width;
+ *pheight = head->height;
drm_mode_probed_add(connector, mode);
return 1;
}
-static int qxl_add_common_modes(struct drm_connector *connector)
+static int qxl_add_common_modes(struct drm_connector *connector,
+ unsigned pwidth,
+ unsigned pheight)
{
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode = NULL;
@@ -159,12 +170,9 @@ static int qxl_add_common_modes(struct drm_connector *connector)
};
for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
- if (common_modes[i].w < 320 || common_modes[i].h < 200)
- continue;
-
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
60, false, false, false);
- if (common_modes[i].w == 1024 && common_modes[i].h == 768)
+ if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
mode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
}
@@ -720,16 +728,18 @@ static int qxl_conn_get_modes(struct drm_connector *connector)
{
int ret = 0;
struct qxl_device *qdev = connector->dev->dev_private;
+ unsigned pwidth = 1024;
+ unsigned pheight = 768;
DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config);
/* TODO: what should we do here? only show the configured modes for the
* device, or allow the full list, or both? */
if (qdev->monitors_config && qdev->monitors_config->count) {
- ret = qxl_add_monitors_config_modes(connector);
+ ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
if (ret < 0)
return ret;
}
- ret += qxl_add_common_modes(connector);
+ ret += qxl_add_common_modes(connector, pwidth, pheight);
return ret;
}
@@ -793,7 +803,10 @@ static enum drm_connector_status qxl_conn_detect(
qdev->client_monitors_config->count > output->index &&
qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]));
- DRM_DEBUG("\n");
+ DRM_DEBUG("#%d connected: %d\n", output->index, connected);
+ if (!connected)
+ qxl_monitors_config_set(qdev, output->index, 0, 0, 0, 0, 0);
+
return connected ? connector_status_connected
: connector_status_disconnected;
}
@@ -835,8 +848,21 @@ static const struct drm_encoder_funcs qxl_enc_funcs = {
.destroy = qxl_enc_destroy,
};
+static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev)
+{
+ if (qdev->hotplug_mode_update_property)
+ return 0;
+
+ qdev->hotplug_mode_update_property =
+ drm_property_create_range(qdev->ddev, DRM_MODE_PROP_IMMUTABLE,
+ "hotplug_mode_update", 0, 1);
+
+ return 0;
+}
+
static int qdev_output_init(struct drm_device *dev, int num_output)
{
+ struct qxl_device *qdev = dev->dev_private;
struct qxl_output *qxl_output;
struct drm_connector *connector;
struct drm_encoder *encoder;
@@ -863,6 +889,8 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs);
drm_connector_helper_add(connector, &qxl_connector_helper_funcs);
+ drm_object_attach_property(&connector->base,
+ qdev->hotplug_mode_update_property, 0);
drm_sysfs_connector_add(connector);
return 0;
}
@@ -975,6 +1003,9 @@ int qxl_modeset_init(struct qxl_device *qdev)
qdev->ddev->mode_config.max_height = 8192;
qdev->ddev->mode_config.fb_base = qdev->vram_base;
+
+ qxl_mode_create_hotplug_mode_update_property(qdev);
+
for (i = 0 ; i < qxl_num_crtc; ++i) {
qdev_crtc_init(qdev->ddev, i);
qdev_output_init(qdev->ddev, i);
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 514118ae72d..fee8748bdca 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -225,7 +225,6 @@ static struct drm_driver qxl_driver = {
.debugfs_init = qxl_debugfs_init,
.debugfs_cleanup = qxl_debugfs_takedown,
#endif
- .gem_init_object = qxl_gem_object_init,
.gem_free_object = qxl_gem_object_free,
.gem_open_object = qxl_gem_object_open,
.gem_close_object = qxl_gem_object_close,
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index f7c9adde46a..7bda32f68d3 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -323,6 +323,8 @@ struct qxl_device {
struct work_struct gc_work;
struct work_struct fb_work;
+
+ struct drm_property *hotplug_mode_update_property;
};
/* forward declaration for QXL_INFO_IO */
@@ -412,7 +414,6 @@ int qxl_gem_object_create_with_handle(struct qxl_device *qdev,
struct qxl_surface *surf,
struct qxl_bo **qobj,
uint32_t *handle);
-int qxl_gem_object_init(struct drm_gem_object *obj);
void qxl_gem_object_free(struct drm_gem_object *gobj);
int qxl_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv);
void qxl_gem_object_close(struct drm_gem_object *obj,
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 88722f23343..f437b30ce68 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -108,7 +108,7 @@ static void qxl_fb_dirty_flush(struct fb_info *info)
u32 x1, x2, y1, y2;
/* TODO: hard coding 32 bpp */
- int stride = qfbdev->qfb.base.pitches[0] * 4;
+ int stride = qfbdev->qfb.base.pitches[0];
x1 = qfbdev->dirty.x1;
x2 = qfbdev->dirty.x2;
diff --git a/drivers/gpu/drm/qxl/qxl_gem.c b/drivers/gpu/drm/qxl/qxl_gem.c
index 1648e4125af..b96f0c9d89b 100644
--- a/drivers/gpu/drm/qxl/qxl_gem.c
+++ b/drivers/gpu/drm/qxl/qxl_gem.c
@@ -28,12 +28,6 @@
#include "qxl_drv.h"
#include "qxl_object.h"
-int qxl_gem_object_init(struct drm_gem_object *obj)
-{
- /* we do nothings here */
- return 0;
-}
-
void qxl_gem_object_free(struct drm_gem_object *gobj)
{
struct qxl_bo *qobj = gem_to_qxl_bo(gobj);
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index 9e8da9ee973..e5ca498be92 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -120,7 +120,7 @@ int qxl_device_init(struct qxl_device *qdev,
struct pci_dev *pdev,
unsigned long flags)
{
- int r;
+ int r, sb;
qdev->dev = &pdev->dev;
qdev->ddev = ddev;
@@ -136,21 +136,39 @@ int qxl_device_init(struct qxl_device *qdev,
qdev->rom_base = pci_resource_start(pdev, 2);
qdev->rom_size = pci_resource_len(pdev, 2);
qdev->vram_base = pci_resource_start(pdev, 0);
- qdev->surfaceram_base = pci_resource_start(pdev, 1);
- qdev->surfaceram_size = pci_resource_len(pdev, 1);
qdev->io_base = pci_resource_start(pdev, 3);
qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0));
- qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size);
- DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk)\n",
+
+ if (pci_resource_len(pdev, 4) > 0) {
+ /* 64bit surface bar present */
+ sb = 4;
+ qdev->surfaceram_base = pci_resource_start(pdev, sb);
+ qdev->surfaceram_size = pci_resource_len(pdev, sb);
+ qdev->surface_mapping =
+ io_mapping_create_wc(qdev->surfaceram_base,
+ qdev->surfaceram_size);
+ }
+ if (qdev->surface_mapping == NULL) {
+ /* 64bit surface bar not present (or mapping failed) */
+ sb = 1;
+ qdev->surfaceram_base = pci_resource_start(pdev, sb);
+ qdev->surfaceram_size = pci_resource_len(pdev, sb);
+ qdev->surface_mapping =
+ io_mapping_create_wc(qdev->surfaceram_base,
+ qdev->surfaceram_size);
+ }
+
+ DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk, %s)\n",
(unsigned long long)qdev->vram_base,
(unsigned long long)pci_resource_end(pdev, 0),
(int)pci_resource_len(pdev, 0) / 1024 / 1024,
(int)pci_resource_len(pdev, 0) / 1024,
(unsigned long long)qdev->surfaceram_base,
- (unsigned long long)pci_resource_end(pdev, 1),
+ (unsigned long long)pci_resource_end(pdev, sb),
(int)qdev->surfaceram_size / 1024 / 1024,
- (int)qdev->surfaceram_size / 1024);
+ (int)qdev->surfaceram_size / 1024,
+ (sb == 4) ? "64bit" : "32bit");
qdev->rom = ioremap(qdev->rom_base, qdev->rom_size);
if (!qdev->rom) {
@@ -230,9 +248,13 @@ int qxl_device_init(struct qxl_device *qdev,
qdev->surfaces_mem_slot = setup_slot(qdev, 1,
(unsigned long)qdev->surfaceram_base,
(unsigned long)qdev->surfaceram_base + qdev->surfaceram_size);
- DRM_INFO("main mem slot %d [%lx,%x)\n",
- qdev->main_mem_slot,
- (unsigned long)qdev->vram_base, qdev->rom->ram_header_offset);
+ DRM_INFO("main mem slot %d [%lx,%x]\n",
+ qdev->main_mem_slot,
+ (unsigned long)qdev->vram_base, qdev->rom->ram_header_offset);
+ DRM_INFO("surface mem slot %d [%lx,%lx]\n",
+ qdev->surfaces_mem_slot,
+ (unsigned long)qdev->surfaceram_base,
+ (unsigned long)qdev->surfaceram_size);
qdev->gc_queue = create_singlethread_workqueue("qxl_gc");
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index 037786d7c1d..c7e7e6590c2 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -516,6 +516,8 @@ int qxl_ttm_init(struct qxl_device *qdev)
(unsigned)qdev->vram_size / (1024 * 1024));
DRM_INFO("qxl: %luM of IO pages memory ready (VRAM domain)\n",
((unsigned)num_io_pages * PAGE_SIZE) / (1024 * 1024));
+ DRM_INFO("qxl: %uM of Surface memory size\n",
+ (unsigned)qdev->surfaceram_size / (1024 * 1024));
if (unlikely(qdev->mman.bdev.dev_mapping == NULL))
qdev->mman.bdev.dev_mapping = qdev->ddev->dev_mapping;
r = qxl_ttm_debugfs_init(qdev);