Commit e6b46ee7 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-vmware-next' into drm-core-next

* drm-vmware-next:
  drm/vmwgfx: Bump minor and driver date
  drm/vmwgfx: Save at least one screen layout
  drm/vmwgfx: Add modinfo version
  drm/vmwgfx: Add a parameter to get the max fb size
  drm/vmwgfx: Don't flush fb if we're in the suspended state.
  drm/vmwgfx: Prune modes based on available VRAM size
  drm/vmwgfx: Take the ttm lock around the dirty ioctl
  drm: vmwgfx: Add a struct drm_file parameter to the dirty framebuffer callback
  drm/vmwgfx: Add new-style PM hooks to improve hibernation behavior
  drm/vmwgfx: Fix ACPI S3 & S4 functionality.
  drm/vmwgfx: Really support other depths than 32
parents fb7ba211 8aea5287
...@@ -1854,7 +1854,8 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, ...@@ -1854,7 +1854,8 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
} }
if (fb->funcs->dirty) { if (fb->funcs->dirty) {
ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips); ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
clips, num_clips);
} else { } else {
ret = -ENOSYS; ret = -ENOSYS;
goto out_err2; goto out_err2;
......
...@@ -597,6 +597,8 @@ static void vmw_lastclose(struct drm_device *dev) ...@@ -597,6 +597,8 @@ static void vmw_lastclose(struct drm_device *dev)
static void vmw_master_init(struct vmw_master *vmaster) static void vmw_master_init(struct vmw_master *vmaster)
{ {
ttm_lock_init(&vmaster->lock); ttm_lock_init(&vmaster->lock);
INIT_LIST_HEAD(&vmaster->fb_surf);
mutex_init(&vmaster->fb_surf_mutex);
} }
static int vmw_master_create(struct drm_device *dev, static int vmw_master_create(struct drm_device *dev,
...@@ -608,7 +610,7 @@ static int vmw_master_create(struct drm_device *dev, ...@@ -608,7 +610,7 @@ static int vmw_master_create(struct drm_device *dev,
if (unlikely(vmaster == NULL)) if (unlikely(vmaster == NULL))
return -ENOMEM; return -ENOMEM;
ttm_lock_init(&vmaster->lock); vmw_master_init(vmaster);
ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
master->driver_priv = vmaster; master->driver_priv = vmaster;
...@@ -699,6 +701,7 @@ static void vmw_master_drop(struct drm_device *dev, ...@@ -699,6 +701,7 @@ static void vmw_master_drop(struct drm_device *dev,
vmw_fp->locked_master = drm_master_get(file_priv->master); vmw_fp->locked_master = drm_master_get(file_priv->master);
ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
vmw_kms_idle_workqueues(vmaster);
if (unlikely((ret != 0))) { if (unlikely((ret != 0))) {
DRM_ERROR("Unable to lock TTM at VT switch.\n"); DRM_ERROR("Unable to lock TTM at VT switch.\n");
...@@ -751,15 +754,16 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, ...@@ -751,15 +754,16 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
* Buffer contents is moved to swappable memory. * Buffer contents is moved to swappable memory.
*/ */
ttm_bo_swapout_all(&dev_priv->bdev); ttm_bo_swapout_all(&dev_priv->bdev);
break; break;
case PM_POST_HIBERNATION: case PM_POST_HIBERNATION:
case PM_POST_SUSPEND: case PM_POST_SUSPEND:
case PM_POST_RESTORE:
ttm_suspend_unlock(&vmaster->lock); ttm_suspend_unlock(&vmaster->lock);
break; break;
case PM_RESTORE_PREPARE: case PM_RESTORE_PREPARE:
break; break;
case PM_POST_RESTORE:
break;
default: default:
break; break;
} }
...@@ -770,21 +774,98 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, ...@@ -770,21 +774,98 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
* These might not be needed with the virtual SVGA device. * These might not be needed with the virtual SVGA device.
*/ */
int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev);
if (dev_priv->num_3d_resources != 0) {
DRM_INFO("Can't suspend or hibernate "
"while 3D resources are active.\n");
return -EBUSY;
}
pci_save_state(pdev); pci_save_state(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot); pci_set_power_state(pdev, PCI_D3hot);
return 0; return 0;
} }
int vmw_pci_resume(struct pci_dev *pdev) static int vmw_pci_resume(struct pci_dev *pdev)
{ {
pci_set_power_state(pdev, PCI_D0); pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev); pci_restore_state(pdev);
return pci_enable_device(pdev); return pci_enable_device(pdev);
} }
static int vmw_pm_suspend(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
struct pm_message dummy;
dummy.event = 0;
return vmw_pci_suspend(pdev, dummy);
}
static int vmw_pm_resume(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
return vmw_pci_resume(pdev);
}
static int vmw_pm_prepare(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev);
/**
* Release 3d reference held by fbdev and potentially
* stop fifo.
*/
dev_priv->suspended = true;
if (dev_priv->enable_fb)
vmw_3d_resource_dec(dev_priv);
if (dev_priv->num_3d_resources != 0) {
DRM_INFO("Can't suspend or hibernate "
"while 3D resources are active.\n");
if (dev_priv->enable_fb)
vmw_3d_resource_inc(dev_priv);
dev_priv->suspended = false;
return -EBUSY;
}
return 0;
}
static void vmw_pm_complete(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev);
/**
* Reclaim 3d reference held by fbdev and potentially
* start fifo.
*/
if (dev_priv->enable_fb)
vmw_3d_resource_inc(dev_priv);
dev_priv->suspended = false;
}
static const struct dev_pm_ops vmw_pm_ops = {
.prepare = vmw_pm_prepare,
.complete = vmw_pm_complete,
.suspend = vmw_pm_suspend,
.resume = vmw_pm_resume,
};
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_MODESET, DRIVER_MODESET,
...@@ -824,8 +905,9 @@ static struct drm_driver driver = { ...@@ -824,8 +905,9 @@ static struct drm_driver driver = {
.id_table = vmw_pci_id_list, .id_table = vmw_pci_id_list,
.probe = vmw_probe, .probe = vmw_probe,
.remove = vmw_remove, .remove = vmw_remove,
.suspend = vmw_pci_suspend, .driver = {
.resume = vmw_pci_resume .pm = &vmw_pm_ops
}
}, },
.name = VMWGFX_DRIVER_NAME, .name = VMWGFX_DRIVER_NAME,
.desc = VMWGFX_DRIVER_DESC, .desc = VMWGFX_DRIVER_DESC,
...@@ -860,3 +942,7 @@ module_exit(vmwgfx_exit); ...@@ -860,3 +942,7 @@ module_exit(vmwgfx_exit);
MODULE_AUTHOR("VMware Inc. and others"); MODULE_AUTHOR("VMware Inc. and others");
MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device"); MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device");
MODULE_LICENSE("GPL and additional rights"); MODULE_LICENSE("GPL and additional rights");
MODULE_VERSION(__stringify(VMWGFX_DRIVER_MAJOR) "."
__stringify(VMWGFX_DRIVER_MINOR) "."
__stringify(VMWGFX_DRIVER_PATCHLEVEL) "."
"0");
...@@ -39,9 +39,9 @@ ...@@ -39,9 +39,9 @@
#include "ttm/ttm_execbuf_util.h" #include "ttm/ttm_execbuf_util.h"
#include "ttm/ttm_module.h" #include "ttm/ttm_module.h"
#define VMWGFX_DRIVER_DATE "20100209" #define VMWGFX_DRIVER_DATE "20100927"
#define VMWGFX_DRIVER_MAJOR 1 #define VMWGFX_DRIVER_MAJOR 1
#define VMWGFX_DRIVER_MINOR 2 #define VMWGFX_DRIVER_MINOR 4
#define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
...@@ -151,6 +151,8 @@ struct vmw_overlay; ...@@ -151,6 +151,8 @@ struct vmw_overlay;
struct vmw_master { struct vmw_master {
struct ttm_lock lock; struct ttm_lock lock;
struct mutex fb_surf_mutex;
struct list_head fb_surf;
}; };
struct vmw_vga_topology_state { struct vmw_vga_topology_state {
...@@ -286,6 +288,7 @@ struct vmw_private { ...@@ -286,6 +288,7 @@ struct vmw_private {
struct vmw_master *active_master; struct vmw_master *active_master;
struct vmw_master fbdev_master; struct vmw_master fbdev_master;
struct notifier_block pm_nb; struct notifier_block pm_nb;
bool suspended;
struct mutex release_mutex; struct mutex release_mutex;
uint32_t num_3d_resources; uint32_t num_3d_resources;
...@@ -518,6 +521,10 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv, ...@@ -518,6 +521,10 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv,
unsigned bbp, unsigned depth); unsigned bbp, unsigned depth);
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
uint32_t pitch,
uint32_t height);
u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
/** /**
......
...@@ -144,6 +144,13 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var, ...@@ -144,6 +144,13 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
return -EINVAL; return -EINVAL;
} }
if (!vmw_kms_validate_mode_vram(vmw_priv,
info->fix.line_length,
var->yoffset + var->yres)) {
DRM_ERROR("Requested geom can not fit in framebuffer\n");
return -EINVAL;
}
return 0; return 0;
} }
...@@ -205,6 +212,9 @@ static void vmw_fb_dirty_flush(struct vmw_fb_par *par) ...@@ -205,6 +212,9 @@ static void vmw_fb_dirty_flush(struct vmw_fb_par *par)
SVGAFifoCmdUpdate body; SVGAFifoCmdUpdate body;
} *cmd; } *cmd;
if (vmw_priv->suspended)
return;
spin_lock_irqsave(&par->dirty.lock, flags); spin_lock_irqsave(&par->dirty.lock, flags);
if (!par->dirty.active) { if (!par->dirty.active) {
spin_unlock_irqrestore(&par->dirty.lock, flags); spin_unlock_irqrestore(&par->dirty.lock, flags);
......
...@@ -54,6 +54,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, ...@@ -54,6 +54,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
case DRM_VMW_PARAM_FIFO_CAPS: case DRM_VMW_PARAM_FIFO_CAPS:
param->value = dev_priv->fifo.capabilities; param->value = dev_priv->fifo.capabilities;
break; break;
case DRM_VMW_PARAM_MAX_FB_SIZE:
param->value = dev_priv->vram_size;
break;
default: default:
DRM_ERROR("Illegal vmwgfx get param request: %d\n", DRM_ERROR("Illegal vmwgfx get param request: %d\n",
param->param); param->param);
......
This diff is collapsed.
...@@ -427,7 +427,9 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, ...@@ -427,7 +427,9 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
{ {
struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector); struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(dev);
struct drm_display_mode *mode = NULL; struct drm_display_mode *mode = NULL;
struct drm_display_mode *bmode;
struct drm_display_mode prefmode = { DRM_MODE("preferred", struct drm_display_mode prefmode = { DRM_MODE("preferred",
DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
...@@ -443,6 +445,8 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, ...@@ -443,6 +445,8 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
mode->hdisplay = ldu->pref_width; mode->hdisplay = ldu->pref_width;
mode->vdisplay = ldu->pref_height; mode->vdisplay = ldu->pref_height;
mode->vrefresh = drm_mode_vrefresh(mode); mode->vrefresh = drm_mode_vrefresh(mode);
if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
mode->vdisplay)) {
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
if (ldu->pref_mode) { if (ldu->pref_mode) {
...@@ -452,13 +456,19 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, ...@@ -452,13 +456,19 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
ldu->pref_mode = mode; ldu->pref_mode = mode;
} }
}
for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
if (vmw_ldu_connector_builtin[i].hdisplay > max_width || bmode = &vmw_ldu_connector_builtin[i];
vmw_ldu_connector_builtin[i].vdisplay > max_height) if (bmode->hdisplay > max_width ||
bmode->vdisplay > max_height)
continue;
if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
bmode->vdisplay))
continue; continue;
mode = drm_mode_duplicate(dev, &vmw_ldu_connector_builtin[i]); mode = drm_mode_duplicate(dev, bmode);
if (!mode) if (!mode)
return 0; return 0;
mode->vrefresh = drm_mode_vrefresh(mode); mode->vrefresh = drm_mode_vrefresh(mode);
......
...@@ -221,7 +221,8 @@ struct drm_framebuffer_funcs { ...@@ -221,7 +221,8 @@ struct drm_framebuffer_funcs {
* the semantics and arguments have a one to one mapping * the semantics and arguments have a one to one mapping
* on this function. * on this function.
*/ */
int (*dirty)(struct drm_framebuffer *framebuffer, unsigned flags, int (*dirty)(struct drm_framebuffer *framebuffer,
struct drm_file *file_priv, unsigned flags,
unsigned color, struct drm_clip_rect *clips, unsigned color, struct drm_clip_rect *clips,
unsigned num_clips); unsigned num_clips);
}; };
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#define DRM_VMW_PARAM_FIFO_OFFSET 3 #define DRM_VMW_PARAM_FIFO_OFFSET 3
#define DRM_VMW_PARAM_HW_CAPS 4 #define DRM_VMW_PARAM_HW_CAPS 4
#define DRM_VMW_PARAM_FIFO_CAPS 5 #define DRM_VMW_PARAM_FIFO_CAPS 5
#define DRM_VMW_PARAM_MAX_FB_SIZE 6
/** /**
* struct drm_vmw_getparam_arg * struct drm_vmw_getparam_arg
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment