aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-03-16 18:12:31 -0400
committerDave Airlie <airlied@redhat.com>2016-03-16 18:12:31 -0400
commit70a09f36d02584fe0025fa14a5cbf276240b2fd4 (patch)
tree721f77fb4c78cf731fff70bd3095bc74b047d350
parent189df01d1cf27b88b3c41f9378453178f76925a8 (diff)
parent5476aa46ff0377229f780c42e77b7e7e756040c7 (diff)
Merge tag 'vmwgfx-next-160316' of git://people.freedesktop.org/~thomash/linux into drm-next
Pull request of 2016-03-16 * tag 'vmwgfx-next-160316' of git://people.freedesktop.org/~thomash/linux: drm/vmwgfx: Bump driver minor drm/vmwgfx: Allow the UPDATE_LAYOUT ioctl from control nodes drm/vmwgfx: Send a hotplug event at master_set drm/vmwgfx: Default to explicit crtc placement for screen targets and screen objects drm/vmwgfx: Calculate the cursor position based on the crtc gui origin drm/vmwgfx: Add connector properties to switch between explicit and implicit placement drm/vmwgfx: Add suggested screen x and y connector properties drm/vmwgfx: Add implicit framebuffer checks to the screen target code drm/vmwgfx: Break out implicit fb code drm/vmwgfx: Rework screen target page flips v2 drm/vmwgfx: Fix screen object page flips for large framebuffers drm/vmwgfx: Fix a screen object framebuffer dirty corner case drm/vmwgfx: Add DXGenMips support
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c22
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c163
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h16
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c19
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c179
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c453
8 files changed, 496 insertions, 368 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0ee76e523a90..6cbb7d4bdd11 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -195,7 +195,7 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
195 DRM_MASTER | DRM_AUTH), 195 DRM_MASTER | DRM_AUTH),
196 VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT, 196 VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
197 vmw_kms_update_layout_ioctl, 197 vmw_kms_update_layout_ioctl,
198 DRM_MASTER), 198 DRM_MASTER | DRM_CONTROL_ALLOW),
199 VMW_IOCTL_DEF(VMW_CREATE_SHADER, 199 VMW_IOCTL_DEF(VMW_CREATE_SHADER,
200 vmw_shader_define_ioctl, 200 vmw_shader_define_ioctl,
201 DRM_AUTH | DRM_RENDER_ALLOW), 201 DRM_AUTH | DRM_RENDER_ALLOW),
@@ -1204,6 +1204,7 @@ static int vmw_master_set(struct drm_device *dev,
1204 } 1204 }
1205 1205
1206 dev_priv->active_master = vmaster; 1206 dev_priv->active_master = vmaster;
1207 drm_sysfs_hotplug_event(dev);
1207 1208
1208 return 0; 1209 return 0;
1209} 1210}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 5cb1b1687cd4..019a6ca3e8e9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -40,9 +40,9 @@
40#include <drm/ttm/ttm_module.h> 40#include <drm/ttm/ttm_module.h>
41#include "vmwgfx_fence.h" 41#include "vmwgfx_fence.h"
42 42
43#define VMWGFX_DRIVER_DATE "20150810" 43#define VMWGFX_DRIVER_DATE "20160210"
44#define VMWGFX_DRIVER_MAJOR 2 44#define VMWGFX_DRIVER_MAJOR 2
45#define VMWGFX_DRIVER_MINOR 9 45#define VMWGFX_DRIVER_MINOR 10
46#define VMWGFX_DRIVER_PATCHLEVEL 0 46#define VMWGFX_DRIVER_PATCHLEVEL 0
47#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 47#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
48#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) 48#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
@@ -407,8 +407,11 @@ struct vmw_private {
407 void *fb_info; 407 void *fb_info;
408 enum vmw_display_unit_type active_display_unit; 408 enum vmw_display_unit_type active_display_unit;
409 struct vmw_legacy_display *ldu_priv; 409 struct vmw_legacy_display *ldu_priv;
410 struct vmw_screen_object_display *sou_priv;
411 struct vmw_overlay *overlay_priv; 410 struct vmw_overlay *overlay_priv;
411 struct drm_property *hotplug_mode_update_property;
412 struct drm_property *implicit_placement_property;
413 unsigned num_implicit;
414 struct vmw_framebuffer *implicit_fb;
412 415
413 /* 416 /*
414 * Context and surface management. 417 * Context and surface management.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 5da5de0cb522..723ba16c6084 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -3009,6 +3009,26 @@ out_unref:
3009 return ret; 3009 return ret;
3010} 3010}
3011 3011
3012/**
3013 * vmw_cmd_dx_genmips - Validate an SVGA_3D_CMD_DX_GENMIPS command
3014 *
3015 * @dev_priv: Pointer to a device private struct.
3016 * @sw_context: The software context being used for this batch.
3017 * @header: Pointer to the command header in the command stream.
3018 */
3019static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv,
3020 struct vmw_sw_context *sw_context,
3021 SVGA3dCmdHeader *header)
3022{
3023 struct {
3024 SVGA3dCmdHeader header;
3025 SVGA3dCmdDXGenMips body;
3026 } *cmd = container_of(header, typeof(*cmd), header);
3027
3028 return vmw_view_id_val_add(sw_context, vmw_view_sr,
3029 cmd->body.shaderResourceViewId);
3030}
3031
3012static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, 3032static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
3013 struct vmw_sw_context *sw_context, 3033 struct vmw_sw_context *sw_context,
3014 void *buf, uint32_t *size) 3034 void *buf, uint32_t *size)
@@ -3297,7 +3317,7 @@ static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
3297 &vmw_cmd_dx_clear_depthstencil_view, true, false, true), 3317 &vmw_cmd_dx_clear_depthstencil_view, true, false, true),
3298 VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY, &vmw_cmd_invalid, 3318 VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY, &vmw_cmd_invalid,
3299 true, false, true), 3319 true, false, true),
3300 VMW_CMD_DEF(SVGA_3D_CMD_DX_GENMIPS, &vmw_cmd_invalid, 3320 VMW_CMD_DEF(SVGA_3D_CMD_DX_GENMIPS, &vmw_cmd_dx_genmips,
3301 true, false, true), 3321 true, false, true),
3302 VMW_CMD_DEF(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE, 3322 VMW_CMD_DEF(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE,
3303 &vmw_cmd_dx_check_subresource, true, false, true), 3323 &vmw_cmd_dx_check_subresource, true, false, true),
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index b221a8c40282..4742ec4ead27 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -236,8 +236,8 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
236 struct vmw_display_unit *du = vmw_crtc_to_du(crtc); 236 struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
237 bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false; 237 bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false;
238 238
239 du->cursor_x = x + crtc->x; 239 du->cursor_x = x + du->set_gui_x;
240 du->cursor_y = y + crtc->y; 240 du->cursor_y = y + du->set_gui_y;
241 241
242 /* 242 /*
243 * FIXME: Unclear whether there's any global state touched by the 243 * FIXME: Unclear whether there's any global state touched by the
@@ -663,9 +663,8 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
663 break; 663 break;
664 case vmw_du_screen_object: 664 case vmw_du_screen_object:
665 ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base, 665 ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base,
666 clips, num_clips, increment, 666 clips, NULL, num_clips,
667 true, 667 increment, true, NULL);
668 NULL);
669 break; 668 break;
670 case vmw_du_legacy: 669 case vmw_du_legacy:
671 ret = vmw_kms_ldu_do_dmabuf_dirty(dev_priv, &vfbd->base, 0, 0, 670 ret = vmw_kms_ldu_do_dmabuf_dirty(dev_priv, &vfbd->base, 0, 0,
@@ -1109,6 +1108,22 @@ int vmw_kms_present(struct vmw_private *dev_priv,
1109 return 0; 1108 return 0;
1110} 1109}
1111 1110
1111static void
1112vmw_kms_create_hotplug_mode_update_property(struct vmw_private *dev_priv)
1113{
1114 if (dev_priv->hotplug_mode_update_property)
1115 return;
1116
1117 dev_priv->hotplug_mode_update_property =
1118 drm_property_create_range(dev_priv->dev,
1119 DRM_MODE_PROP_IMMUTABLE,
1120 "hotplug_mode_update", 0, 1);
1121
1122 if (!dev_priv->hotplug_mode_update_property)
1123 return;
1124
1125}
1126
1112int vmw_kms_init(struct vmw_private *dev_priv) 1127int vmw_kms_init(struct vmw_private *dev_priv)
1113{ 1128{
1114 struct drm_device *dev = dev_priv->dev; 1129 struct drm_device *dev = dev_priv->dev;
@@ -1121,6 +1136,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
1121 dev->mode_config.max_width = dev_priv->texture_max_width; 1136 dev->mode_config.max_width = dev_priv->texture_max_width;
1122 dev->mode_config.max_height = dev_priv->texture_max_height; 1137 dev->mode_config.max_height = dev_priv->texture_max_height;
1123 1138
1139 drm_mode_create_suggested_offset_properties(dev);
1140 vmw_kms_create_hotplug_mode_update_property(dev_priv);
1141
1124 ret = vmw_kms_stdu_init_display(dev_priv); 1142 ret = vmw_kms_stdu_init_display(dev_priv);
1125 if (ret) { 1143 if (ret) {
1126 ret = vmw_kms_sou_init_display(dev_priv); 1144 ret = vmw_kms_sou_init_display(dev_priv);
@@ -1360,15 +1378,28 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
1360 du->pref_active = true; 1378 du->pref_active = true;
1361 du->gui_x = rects[du->unit].x; 1379 du->gui_x = rects[du->unit].x;
1362 du->gui_y = rects[du->unit].y; 1380 du->gui_y = rects[du->unit].y;
1381 drm_object_property_set_value
1382 (&con->base, dev->mode_config.suggested_x_property,
1383 du->gui_x);
1384 drm_object_property_set_value
1385 (&con->base, dev->mode_config.suggested_y_property,
1386 du->gui_y);
1363 } else { 1387 } else {
1364 du->pref_width = 800; 1388 du->pref_width = 800;
1365 du->pref_height = 600; 1389 du->pref_height = 600;
1366 du->pref_active = false; 1390 du->pref_active = false;
1391 drm_object_property_set_value
1392 (&con->base, dev->mode_config.suggested_x_property,
1393 0);
1394 drm_object_property_set_value
1395 (&con->base, dev->mode_config.suggested_y_property,
1396 0);
1367 } 1397 }
1368 con->status = vmw_du_connector_detect(con, true); 1398 con->status = vmw_du_connector_detect(con, true);
1369 } 1399 }
1370 1400
1371 mutex_unlock(&dev->mode_config.mutex); 1401 mutex_unlock(&dev->mode_config.mutex);
1402 drm_sysfs_hotplug_event(dev);
1372 1403
1373 return 0; 1404 return 0;
1374} 1405}
@@ -1591,6 +1622,12 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
1591 struct drm_property *property, 1622 struct drm_property *property,
1592 uint64_t val) 1623 uint64_t val)
1593{ 1624{
1625 struct vmw_display_unit *du = vmw_connector_to_du(connector);
1626 struct vmw_private *dev_priv = vmw_priv(connector->dev);
1627
1628 if (property == dev_priv->implicit_placement_property)
1629 du->is_implicit = val;
1630
1594 return 0; 1631 return 0;
1595} 1632}
1596 1633
@@ -2096,3 +2133,119 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
2096 2133
2097 return 0; 2134 return 0;
2098} 2135}
2136
2137/**
2138 * vmw_kms_del_active - unregister a crtc binding to the implicit framebuffer
2139 *
2140 * @dev_priv: Pointer to a device private struct.
2141 * @du: The display unit of the crtc.
2142 */
2143void vmw_kms_del_active(struct vmw_private *dev_priv,
2144 struct vmw_display_unit *du)
2145{
2146 lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
2147
2148 if (du->active_implicit) {
2149 if (--(dev_priv->num_implicit) == 0)
2150 dev_priv->implicit_fb = NULL;
2151 du->active_implicit = false;
2152 }
2153}
2154
2155/**
2156 * vmw_kms_add_active - register a crtc binding to an implicit framebuffer
2157 *
2158 * @vmw_priv: Pointer to a device private struct.
2159 * @du: The display unit of the crtc.
2160 * @vfb: The implicit framebuffer
2161 *
2162 * Registers a binding to an implicit framebuffer.
2163 */
2164void vmw_kms_add_active(struct vmw_private *dev_priv,
2165 struct vmw_display_unit *du,
2166 struct vmw_framebuffer *vfb)
2167{
2168 lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
2169
2170 WARN_ON_ONCE(!dev_priv->num_implicit && dev_priv->implicit_fb);
2171
2172 if (!du->active_implicit && du->is_implicit) {
2173 dev_priv->implicit_fb = vfb;
2174 du->active_implicit = true;
2175 dev_priv->num_implicit++;
2176 }
2177}
2178
2179/**
2180 * vmw_kms_screen_object_flippable - Check whether we can page-flip a crtc.
2181 *
2182 * @dev_priv: Pointer to device-private struct.
2183 * @crtc: The crtc we want to flip.
2184 *
2185 * Returns true or false depending whether it's OK to flip this crtc
2186 * based on the criterion that we must not have more than one implicit
2187 * frame-buffer at any one time.
2188 */
2189bool vmw_kms_crtc_flippable(struct vmw_private *dev_priv,
2190 struct drm_crtc *crtc)
2191{
2192 struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
2193
2194 lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
2195
2196 if (!du->is_implicit)
2197 return true;
2198
2199 if (dev_priv->num_implicit != 1)
2200 return false;
2201
2202 return true;
2203}
2204
2205/**
2206 * vmw_kms_update_implicit_fb - Update the implicit fb.
2207 *
2208 * @dev_priv: Pointer to device-private struct.
2209 * @crtc: The crtc the new implicit frame-buffer is bound to.
2210 */
2211void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
2212 struct drm_crtc *crtc)
2213{
2214 struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
2215 struct vmw_framebuffer *vfb;
2216
2217 lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
2218
2219 if (!du->is_implicit)
2220 return;
2221
2222 vfb = vmw_framebuffer_to_vfb(crtc->primary->fb);
2223 WARN_ON_ONCE(dev_priv->num_implicit != 1 &&
2224 dev_priv->implicit_fb != vfb);
2225
2226 dev_priv->implicit_fb = vfb;
2227}
2228
2229/**
2230 * vmw_kms_create_implicit_placement_proparty - Set up the implicit placement
2231 * property.
2232 *
2233 * @dev_priv: Pointer to a device private struct.
2234 * @immutable: Whether the property is immutable.
2235 *
2236 * Sets up the implicit placement property unless it's already set up.
2237 */
2238void
2239vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
2240 bool immutable)
2241{
2242 if (dev_priv->implicit_placement_property)
2243 return;
2244
2245 dev_priv->implicit_placement_property =
2246 drm_property_create_range(dev_priv->dev,
2247 immutable ?
2248 DRM_MODE_PROP_IMMUTABLE : 0,
2249 "implicit_placement", 0, 1);
2250
2251}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index edd81503516d..57203212c501 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -178,6 +178,9 @@ struct vmw_display_unit {
178 int gui_x; 178 int gui_x;
179 int gui_y; 179 int gui_y;
180 bool is_implicit; 180 bool is_implicit;
181 bool active_implicit;
182 int set_gui_x;
183 int set_gui_y;
181}; 184};
182 185
183#define vmw_crtc_to_du(x) \ 186#define vmw_crtc_to_du(x) \
@@ -254,6 +257,18 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
254 struct drm_crtc **p_crtc, 257 struct drm_crtc **p_crtc,
255 struct drm_display_mode **p_mode); 258 struct drm_display_mode **p_mode);
256void vmw_guess_mode_timing(struct drm_display_mode *mode); 259void vmw_guess_mode_timing(struct drm_display_mode *mode);
260void vmw_kms_del_active(struct vmw_private *dev_priv,
261 struct vmw_display_unit *du);
262void vmw_kms_add_active(struct vmw_private *dev_priv,
263 struct vmw_display_unit *du,
264 struct vmw_framebuffer *vfb);
265bool vmw_kms_crtc_flippable(struct vmw_private *dev_priv,
266 struct drm_crtc *crtc);
267void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
268 struct drm_crtc *crtc);
269void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
270 bool immutable);
271
257 272
258/* 273/*
259 * Legacy display unit functions - vmwgfx_ldu.c 274 * Legacy display unit functions - vmwgfx_ldu.c
@@ -287,6 +302,7 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
287int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv, 302int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,
288 struct vmw_framebuffer *framebuffer, 303 struct vmw_framebuffer *framebuffer,
289 struct drm_clip_rect *clips, 304 struct drm_clip_rect *clips,
305 struct drm_vmw_rect *vclips,
290 unsigned num_clips, int increment, 306 unsigned num_clips, int increment,
291 bool interruptible, 307 bool interruptible,
292 struct vmw_fence_obj **out_fence); 308 struct vmw_fence_obj **out_fence);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index b6fa44fe8929..63ccd9871ec9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -288,6 +288,8 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
288 crtc->y = set->y; 288 crtc->y = set->y;
289 crtc->mode = *mode; 289 crtc->mode = *mode;
290 crtc->enabled = true; 290 crtc->enabled = true;
291 ldu->base.set_gui_x = set->x;
292 ldu->base.set_gui_y = set->y;
291 293
292 vmw_ldu_add_active(dev_priv, ldu, vfb); 294 vmw_ldu_add_active(dev_priv, ldu, vfb);
293 295
@@ -375,8 +377,19 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
375 drm_mode_crtc_set_gamma_size(crtc, 256); 377 drm_mode_crtc_set_gamma_size(crtc, 256);
376 378
377 drm_object_attach_property(&connector->base, 379 drm_object_attach_property(&connector->base,
378 dev->mode_config.dirty_info_property, 380 dev->mode_config.dirty_info_property,
379 1); 381 1);
382 drm_object_attach_property(&connector->base,
383 dev_priv->hotplug_mode_update_property, 1);
384 drm_object_attach_property(&connector->base,
385 dev->mode_config.suggested_x_property, 0);
386 drm_object_attach_property(&connector->base,
387 dev->mode_config.suggested_y_property, 0);
388 if (dev_priv->implicit_placement_property)
389 drm_object_attach_property
390 (&connector->base,
391 dev_priv->implicit_placement_property,
392 1);
380 393
381 return 0; 394 return 0;
382} 395}
@@ -412,6 +425,8 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
412 if (ret != 0) 425 if (ret != 0)
413 goto err_vblank_cleanup; 426 goto err_vblank_cleanup;
414 427
428 vmw_kms_create_implicit_placement_property(dev_priv, true);
429
415 if (dev_priv->capabilities & SVGA_CAP_MULTIMON) 430 if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
416 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) 431 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
417 vmw_ldu_init(dev_priv, i); 432 vmw_ldu_init(dev_priv, i);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index c5a1a08b0449..0ea22fd112c9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -74,19 +74,6 @@ struct vmw_kms_sou_dirty_cmd {
74 SVGA3dCmdBlitSurfaceToScreen body; 74 SVGA3dCmdBlitSurfaceToScreen body;
75}; 75};
76 76
77
78/*
79 * Other structs.
80 */
81
82struct vmw_screen_object_display {
83 unsigned num_implicit;
84
85 struct vmw_framebuffer *implicit_fb;
86 SVGAFifoCmdDefineGMRFB cur;
87 struct vmw_dma_buffer *pinned_gmrfb;
88};
89
90/** 77/**
91 * Display unit using screen objects. 78 * Display unit using screen objects.
92 */ 79 */
@@ -97,7 +84,6 @@ struct vmw_screen_object_unit {
97 struct vmw_dma_buffer *buffer; /**< Backing store buffer */ 84 struct vmw_dma_buffer *buffer; /**< Backing store buffer */
98 85
99 bool defined; 86 bool defined;
100 bool active_implicit;
101}; 87};
102 88
103static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) 89static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
@@ -116,33 +102,6 @@ static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
116 vmw_sou_destroy(vmw_crtc_to_sou(crtc)); 102 vmw_sou_destroy(vmw_crtc_to_sou(crtc));
117} 103}
118 104
119static void vmw_sou_del_active(struct vmw_private *vmw_priv,
120 struct vmw_screen_object_unit *sou)
121{
122 struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
123
124 if (sou->active_implicit) {
125 if (--(ld->num_implicit) == 0)
126 ld->implicit_fb = NULL;
127 sou->active_implicit = false;
128 }
129}
130
131static void vmw_sou_add_active(struct vmw_private *vmw_priv,
132 struct vmw_screen_object_unit *sou,
133 struct vmw_framebuffer *vfb)
134{
135 struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
136
137 BUG_ON(!ld->num_implicit && ld->implicit_fb);
138
139 if (!sou->active_implicit && sou->base.is_implicit) {
140 ld->implicit_fb = vfb;
141 sou->active_implicit = true;
142 ld->num_implicit++;
143 }
144}
145
146/** 105/**
147 * Send the fifo command to create a screen. 106 * Send the fifo command to create a screen.
148 */ 107 */
@@ -185,6 +144,8 @@ static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
185 cmd->obj.root.x = sou->base.gui_x; 144 cmd->obj.root.x = sou->base.gui_x;
186 cmd->obj.root.y = sou->base.gui_y; 145 cmd->obj.root.y = sou->base.gui_y;
187 } 146 }
147 sou->base.set_gui_x = cmd->obj.root.x;
148 sou->base.set_gui_y = cmd->obj.root.y;
188 149
189 /* Ok to assume that buffer is pinned in vram */ 150 /* Ok to assume that buffer is pinned in vram */
190 vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr); 151 vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
@@ -323,13 +284,13 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
323 return -EINVAL; 284 return -EINVAL;
324 } 285 }
325 286
326 /* sou only supports one fb active at the time */ 287 /* Only one active implicit frame-buffer at a time. */
327 if (sou->base.is_implicit && 288 if (sou->base.is_implicit &&
328 dev_priv->sou_priv->implicit_fb && vfb && 289 dev_priv->implicit_fb && vfb &&
329 !(dev_priv->sou_priv->num_implicit == 1 && 290 !(dev_priv->num_implicit == 1 &&
330 sou->active_implicit) && 291 sou->base.active_implicit) &&
331 dev_priv->sou_priv->implicit_fb != vfb) { 292 dev_priv->implicit_fb != vfb) {
332 DRM_ERROR("Multiple framebuffers not supported\n"); 293 DRM_ERROR("Multiple implicit framebuffers not supported.\n");
333 return -EINVAL; 294 return -EINVAL;
334 } 295 }
335 296
@@ -351,7 +312,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
351 crtc->y = 0; 312 crtc->y = 0;
352 crtc->enabled = false; 313 crtc->enabled = false;
353 314
354 vmw_sou_del_active(dev_priv, sou); 315 vmw_kms_del_active(dev_priv, &sou->base);
355 316
356 vmw_sou_backing_free(dev_priv, sou); 317 vmw_sou_backing_free(dev_priv, sou);
357 318
@@ -415,7 +376,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
415 return ret; 376 return ret;
416 } 377 }
417 378
418 vmw_sou_add_active(dev_priv, sou, vfb); 379 vmw_kms_add_active(dev_priv, &sou->base, vfb);
419 380
420 connector->encoder = encoder; 381 connector->encoder = encoder;
421 encoder->crtc = crtc; 382 encoder->crtc = crtc;
@@ -428,39 +389,6 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
428 return 0; 389 return 0;
429} 390}
430 391
431/**
432 * Returns if this unit can be page flipped.
433 * Must be called with the mode_config mutex held.
434 */
435static bool vmw_sou_screen_object_flippable(struct vmw_private *dev_priv,
436 struct drm_crtc *crtc)
437{
438 struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
439
440 if (!sou->base.is_implicit)
441 return true;
442
443 if (dev_priv->sou_priv->num_implicit != 1)
444 return false;
445
446 return true;
447}
448
449/**
450 * Update the implicit fb to the current fb of this crtc.
451 * Must be called with the mode_config mutex held.
452 */
453static void vmw_sou_update_implicit_fb(struct vmw_private *dev_priv,
454 struct drm_crtc *crtc)
455{
456 struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
457
458 BUG_ON(!sou->base.is_implicit);
459
460 dev_priv->sou_priv->implicit_fb =
461 vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
462}
463
464static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, 392static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
465 struct drm_framebuffer *fb, 393 struct drm_framebuffer *fb,
466 struct drm_pending_vblank_event *event, 394 struct drm_pending_vblank_event *event,
@@ -470,30 +398,27 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
470 struct drm_framebuffer *old_fb = crtc->primary->fb; 398 struct drm_framebuffer *old_fb = crtc->primary->fb;
471 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); 399 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
472 struct vmw_fence_obj *fence = NULL; 400 struct vmw_fence_obj *fence = NULL;
473 struct drm_clip_rect clips; 401 struct drm_vmw_rect vclips;
474 int ret; 402 int ret;
475 403
476 /* require ScreenObject support for page flipping */ 404 if (!vmw_kms_crtc_flippable(dev_priv, crtc))
477 if (!dev_priv->sou_priv)
478 return -ENOSYS;
479
480 if (!vmw_sou_screen_object_flippable(dev_priv, crtc))
481 return -EINVAL; 405 return -EINVAL;
482 406
483 crtc->primary->fb = fb; 407 crtc->primary->fb = fb;
484 408
485 /* do a full screen dirty update */ 409 /* do a full screen dirty update */
486 clips.x1 = clips.y1 = 0; 410 vclips.x = crtc->x;
487 clips.x2 = fb->width; 411 vclips.y = crtc->y;
488 clips.y2 = fb->height; 412 vclips.w = crtc->mode.hdisplay;
413 vclips.h = crtc->mode.vdisplay;
489 414
490 if (vfb->dmabuf) 415 if (vfb->dmabuf)
491 ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb, 416 ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb,
492 &clips, 1, 1, 417 NULL, &vclips, 1, 1,
493 true, &fence); 418 true, &fence);
494 else 419 else
495 ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, 420 ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb,
496 &clips, NULL, NULL, 421 NULL, &vclips, NULL,
497 0, 0, 1, 1, &fence); 422 0, 0, 1, 1, &fence);
498 423
499 424
@@ -521,7 +446,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
521 vmw_fence_obj_unreference(&fence); 446 vmw_fence_obj_unreference(&fence);
522 447
523 if (vmw_crtc_to_du(crtc)->is_implicit) 448 if (vmw_crtc_to_du(crtc)->is_implicit)
524 vmw_sou_update_implicit_fb(dev_priv, crtc); 449 vmw_kms_update_implicit_fb(dev_priv, crtc);
525 450
526 return ret; 451 return ret;
527 452
@@ -586,13 +511,12 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
586 encoder = &sou->base.encoder; 511 encoder = &sou->base.encoder;
587 connector = &sou->base.connector; 512 connector = &sou->base.connector;
588 513
589 sou->active_implicit = false; 514 sou->base.active_implicit = false;
590
591 sou->base.pref_active = (unit == 0); 515 sou->base.pref_active = (unit == 0);
592 sou->base.pref_width = dev_priv->initial_width; 516 sou->base.pref_width = dev_priv->initial_width;
593 sou->base.pref_height = dev_priv->initial_height; 517 sou->base.pref_height = dev_priv->initial_height;
594 sou->base.pref_mode = NULL; 518 sou->base.pref_mode = NULL;
595 sou->base.is_implicit = true; 519 sou->base.is_implicit = false;
596 520
597 drm_connector_init(dev, connector, &vmw_sou_connector_funcs, 521 drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
598 DRM_MODE_CONNECTOR_VIRTUAL); 522 DRM_MODE_CONNECTOR_VIRTUAL);
@@ -611,8 +535,19 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
611 drm_mode_crtc_set_gamma_size(crtc, 256); 535 drm_mode_crtc_set_gamma_size(crtc, 256);
612 536
613 drm_object_attach_property(&connector->base, 537 drm_object_attach_property(&connector->base,
614 dev->mode_config.dirty_info_property, 538 dev->mode_config.dirty_info_property,
615 1); 539 1);
540 drm_object_attach_property(&connector->base,
541 dev_priv->hotplug_mode_update_property, 1);
542 drm_object_attach_property(&connector->base,
543 dev->mode_config.suggested_x_property, 0);
544 drm_object_attach_property(&connector->base,
545 dev->mode_config.suggested_y_property, 0);
546 if (dev_priv->implicit_placement_property)
547 drm_object_attach_property
548 (&connector->base,
549 dev_priv->implicit_placement_property,
550 sou->base.is_implicit);
616 551
617 return 0; 552 return 0;
618} 553}
@@ -622,11 +557,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
622 struct drm_device *dev = dev_priv->dev; 557 struct drm_device *dev = dev_priv->dev;
623 int i, ret; 558 int i, ret;
624 559
625 if (dev_priv->sou_priv) {
626 DRM_INFO("sou system already on\n");
627 return -EINVAL;
628 }
629
630 if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) { 560 if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
631 DRM_INFO("Not using screen objects," 561 DRM_INFO("Not using screen objects,"
632 " missing cap SCREEN_OBJECT_2\n"); 562 " missing cap SCREEN_OBJECT_2\n");
@@ -634,21 +564,19 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
634 } 564 }
635 565
636 ret = -ENOMEM; 566 ret = -ENOMEM;
637 dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL); 567 dev_priv->num_implicit = 0;
638 if (unlikely(!dev_priv->sou_priv)) 568 dev_priv->implicit_fb = NULL;
639 goto err_no_mem;
640
641 dev_priv->sou_priv->num_implicit = 0;
642 dev_priv->sou_priv->implicit_fb = NULL;
643 569
644 ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); 570 ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
645 if (unlikely(ret != 0)) 571 if (unlikely(ret != 0))
646 goto err_free; 572 return ret;
647 573
648 ret = drm_mode_create_dirty_info_property(dev); 574 ret = drm_mode_create_dirty_info_property(dev);
649 if (unlikely(ret != 0)) 575 if (unlikely(ret != 0))
650 goto err_vblank_cleanup; 576 goto err_vblank_cleanup;
651 577
578 vmw_kms_create_implicit_placement_property(dev_priv, false);
579
652 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) 580 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
653 vmw_sou_init(dev_priv, i); 581 vmw_sou_init(dev_priv, i);
654 582
@@ -660,10 +588,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
660 588
661err_vblank_cleanup: 589err_vblank_cleanup:
662 drm_vblank_cleanup(dev); 590 drm_vblank_cleanup(dev);
663err_free:
664 kfree(dev_priv->sou_priv);
665 dev_priv->sou_priv = NULL;
666err_no_mem:
667 return ret; 591 return ret;
668} 592}
669 593
@@ -671,13 +595,8 @@ int vmw_kms_sou_close_display(struct vmw_private *dev_priv)
671{ 595{
672 struct drm_device *dev = dev_priv->dev; 596 struct drm_device *dev = dev_priv->dev;
673 597
674 if (!dev_priv->sou_priv)
675 return -ENOSYS;
676
677 drm_vblank_cleanup(dev); 598 drm_vblank_cleanup(dev);
678 599
679 kfree(dev_priv->sou_priv);
680
681 return 0; 600 return 0;
682} 601}
683 602
@@ -738,6 +657,11 @@ static void vmw_sou_surface_fifo_commit(struct vmw_kms_dirty *dirty)
738 SVGASignedRect *blit = (SVGASignedRect *) &cmd[1]; 657 SVGASignedRect *blit = (SVGASignedRect *) &cmd[1];
739 int i; 658 int i;
740 659
660 if (!dirty->num_hits) {
661 vmw_fifo_commit(dirty->dev_priv, 0);
662 return;
663 }
664
741 cmd->header.id = SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN; 665 cmd->header.id = SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN;
742 cmd->header.size = sizeof(cmd->body) + region_size; 666 cmd->header.size = sizeof(cmd->body) + region_size;
743 667
@@ -875,6 +799,11 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
875 */ 799 */
876static void vmw_sou_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) 800static void vmw_sou_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
877{ 801{
802 if (!dirty->num_hits) {
803 vmw_fifo_commit(dirty->dev_priv, 0);
804 return;
805 }
806
878 vmw_fifo_commit(dirty->dev_priv, 807 vmw_fifo_commit(dirty->dev_priv,
879 sizeof(struct vmw_kms_sou_dmabuf_blit) * 808 sizeof(struct vmw_kms_sou_dmabuf_blit) *
880 dirty->num_hits); 809 dirty->num_hits);
@@ -909,6 +838,8 @@ static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty)
909 * @dev_priv: Pointer to the device private structure. 838 * @dev_priv: Pointer to the device private structure.
910 * @framebuffer: Pointer to the dma-buffer backed framebuffer. 839 * @framebuffer: Pointer to the dma-buffer backed framebuffer.
911 * @clips: Array of clip rects. 840 * @clips: Array of clip rects.
841 * @vclips: Alternate array of clip rects. Either @clips or @vclips must
842 * be NULL.
912 * @num_clips: Number of clip rects in @clips. 843 * @num_clips: Number of clip rects in @clips.
913 * @increment: Increment to use when looping over @clips. 844 * @increment: Increment to use when looping over @clips.
914 * @interruptible: Whether to perform waits interruptible if possible. 845 * @interruptible: Whether to perform waits interruptible if possible.
@@ -922,6 +853,7 @@ static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty)
922int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv, 853int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,
923 struct vmw_framebuffer *framebuffer, 854 struct vmw_framebuffer *framebuffer,
924 struct drm_clip_rect *clips, 855 struct drm_clip_rect *clips,
856 struct drm_vmw_rect *vclips,
925 unsigned num_clips, int increment, 857 unsigned num_clips, int increment,
926 bool interruptible, 858 bool interruptible,
927 struct vmw_fence_obj **out_fence) 859 struct vmw_fence_obj **out_fence)
@@ -945,7 +877,7 @@ int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,
945 dirty.clip = vmw_sou_dmabuf_clip; 877 dirty.clip = vmw_sou_dmabuf_clip;
946 dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_dmabuf_blit) * 878 dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_dmabuf_blit) *
947 num_clips; 879 num_clips;
948 ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, NULL, 880 ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
949 0, 0, num_clips, increment, &dirty); 881 0, 0, num_clips, increment, &dirty);
950 vmw_kms_helper_buffer_finish(dev_priv, NULL, buf, out_fence, NULL); 882 vmw_kms_helper_buffer_finish(dev_priv, NULL, buf, out_fence, NULL);
951 883
@@ -967,6 +899,11 @@ out_revert:
967 */ 899 */
968static void vmw_sou_readback_fifo_commit(struct vmw_kms_dirty *dirty) 900static void vmw_sou_readback_fifo_commit(struct vmw_kms_dirty *dirty)
969{ 901{
902 if (!dirty->num_hits) {
903 vmw_fifo_commit(dirty->dev_priv, 0);
904 return;
905 }
906
970 vmw_fifo_commit(dirty->dev_priv, 907 vmw_fifo_commit(dirty->dev_priv,
971 sizeof(struct vmw_kms_sou_readback_blit) * 908 sizeof(struct vmw_kms_sou_readback_blit) *
972 dirty->num_hits); 909 dirty->num_hits);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 4ef5ffd7189d..b949102ad864 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -96,7 +96,6 @@ struct vmw_stdu_surface_copy {
96 * content_vfbs dimensions, then this is a pointer into the 96 * content_vfbs dimensions, then this is a pointer into the
97 * corresponding field in content_vfbs. If not, then this 97 * corresponding field in content_vfbs. If not, then this
98 * is a separate buffer to which content_vfbs will blit to. 98 * is a separate buffer to which content_vfbs will blit to.
99 * @content_fb: holds the rendered content, can be a surface or DMA buffer
100 * @content_type: content_fb type 99 * @content_type: content_fb type
101 * @defined: true if the current display unit has been initialized 100 * @defined: true if the current display unit has been initialized
102 */ 101 */
@@ -104,8 +103,6 @@ struct vmw_screen_target_display_unit {
104 struct vmw_display_unit base; 103 struct vmw_display_unit base;
105 104
106 struct vmw_surface *display_srf; 105 struct vmw_surface *display_srf;
107 struct drm_framebuffer *content_fb;
108
109 enum stdu_content_type content_fb_type; 106 enum stdu_content_type content_fb_type;
110 107
111 bool defined; 108 bool defined;
@@ -122,22 +119,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu);
122 *****************************************************************************/ 119 *****************************************************************************/
123 120
124/** 121/**
125 * vmw_stdu_pin_display - pins the resource associated with the display surface
126 *
127 * @stdu: contains the display surface
128 *
129 * Since the display surface can either be a private surface allocated by us,
130 * or it can point to the content surface, we use this function to not pin the
131 * same resource twice.
132 */
133static int vmw_stdu_pin_display(struct vmw_screen_target_display_unit *stdu)
134{
135 return vmw_resource_pin(&stdu->display_srf->res, false);
136}
137
138
139
140/**
141 * vmw_stdu_unpin_display - unpins the resource associated with display surface 122 * vmw_stdu_unpin_display - unpins the resource associated with display surface
142 * 123 *
143 * @stdu: contains the display surface 124 * @stdu: contains the display surface
@@ -153,13 +134,7 @@ static void vmw_stdu_unpin_display(struct vmw_screen_target_display_unit *stdu)
153 struct vmw_resource *res = &stdu->display_srf->res; 134 struct vmw_resource *res = &stdu->display_srf->res;
154 135
155 vmw_resource_unpin(res); 136 vmw_resource_unpin(res);
156 137 vmw_surface_unreference(&stdu->display_srf);
157 if (stdu->content_fb_type != SAME_AS_DISPLAY) {
158 vmw_resource_unreference(&res);
159 stdu->content_fb_type = SAME_AS_DISPLAY;
160 }
161
162 stdu->display_srf = NULL;
163 } 138 }
164} 139}
165 140
@@ -185,6 +160,9 @@ static void vmw_stdu_crtc_destroy(struct drm_crtc *crtc)
185 * 160 *
186 * @dev_priv: VMW DRM device 161 * @dev_priv: VMW DRM device
187 * @stdu: display unit to create a Screen Target for 162 * @stdu: display unit to create a Screen Target for
163 * @mode: The mode to set.
164 * @crtc_x: X coordinate of screen target relative to framebuffer origin.
165 * @crtc_y: Y coordinate of screen target relative to framebuffer origin.
188 * 166 *
189 * Creates a STDU that we can used later. This function is called whenever the 167 * Creates a STDU that we can used later. This function is called whenever the
190 * framebuffer size changes. 168 * framebuffer size changes.
@@ -193,7 +171,9 @@ static void vmw_stdu_crtc_destroy(struct drm_crtc *crtc)
193 * 0 on success, error code on failure 171 * 0 on success, error code on failure
194 */ 172 */
195static int vmw_stdu_define_st(struct vmw_private *dev_priv, 173static int vmw_stdu_define_st(struct vmw_private *dev_priv,
196 struct vmw_screen_target_display_unit *stdu) 174 struct vmw_screen_target_display_unit *stdu,
175 struct drm_display_mode *mode,
176 int crtc_x, int crtc_y)
197{ 177{
198 struct { 178 struct {
199 SVGA3dCmdHeader header; 179 SVGA3dCmdHeader header;
@@ -211,17 +191,19 @@ static int vmw_stdu_define_st(struct vmw_private *dev_priv,
211 cmd->header.size = sizeof(cmd->body); 191 cmd->header.size = sizeof(cmd->body);
212 192
213 cmd->body.stid = stdu->base.unit; 193 cmd->body.stid = stdu->base.unit;
214 cmd->body.width = stdu->display_srf->base_size.width; 194 cmd->body.width = mode->hdisplay;
215 cmd->body.height = stdu->display_srf->base_size.height; 195 cmd->body.height = mode->vdisplay;
216 cmd->body.flags = (0 == cmd->body.stid) ? SVGA_STFLAG_PRIMARY : 0; 196 cmd->body.flags = (0 == cmd->body.stid) ? SVGA_STFLAG_PRIMARY : 0;
217 cmd->body.dpi = 0; 197 cmd->body.dpi = 0;
218 cmd->body.xRoot = stdu->base.crtc.x; 198 if (stdu->base.is_implicit) {
219 cmd->body.yRoot = stdu->base.crtc.y; 199 cmd->body.xRoot = crtc_x;
220 200 cmd->body.yRoot = crtc_y;
221 if (!stdu->base.is_implicit) { 201 } else {
222 cmd->body.xRoot = stdu->base.gui_x; 202 cmd->body.xRoot = stdu->base.gui_x;
223 cmd->body.yRoot = stdu->base.gui_y; 203 cmd->body.yRoot = stdu->base.gui_y;
224 } 204 }
205 stdu->base.set_gui_x = cmd->body.xRoot;
206 stdu->base.set_gui_y = cmd->body.yRoot;
225 207
226 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 208 vmw_fifo_commit(dev_priv, sizeof(*cmd));
227 209
@@ -392,126 +374,43 @@ static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
392 return ret; 374 return ret;
393} 375}
394 376
395
396
397/** 377/**
398 * vmw_stdu_crtc_set_config - Sets a mode 378 * vmw_stdu_bind_fb - Bind an fb to a defined screen target
399 * 379 *
400 * @set: mode parameters 380 * @dev_priv: Pointer to a device private struct.
401 * 381 * @crtc: The crtc holding the screen target.
402 * This function is the device-specific portion of the DRM CRTC mode set. 382 * @mode: The mode currently used by the screen target. Must be non-NULL.
403 * For the SVGA device, we do this by defining a Screen Target, binding a 383 * @new_fb: The new framebuffer to bind. Must be non-NULL.
404 * GB Surface to that target, and finally update the screen target.
405 * 384 *
406 * RETURNS: 385 * RETURNS:
407 * 0 on success, error code otherwise 386 * 0 on success, error code on failure.
408 */ 387 */
409static int vmw_stdu_crtc_set_config(struct drm_mode_set *set) 388static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
389 struct drm_crtc *crtc,
390 struct drm_display_mode *mode,
391 struct drm_framebuffer *new_fb)
410{ 392{
411 struct vmw_private *dev_priv; 393 struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
412 struct vmw_screen_target_display_unit *stdu; 394 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
413 struct vmw_framebuffer *vfb; 395 struct vmw_surface *new_display_srf = NULL;
396 enum stdu_content_type new_content_type;
414 struct vmw_framebuffer_surface *new_vfbs; 397 struct vmw_framebuffer_surface *new_vfbs;
415 struct drm_display_mode *mode; 398 int ret;
416 struct drm_framebuffer *new_fb;
417 struct drm_crtc *crtc;
418 struct drm_encoder *encoder;
419 struct drm_connector *connector;
420 int ret;
421
422
423 if (!set || !set->crtc)
424 return -EINVAL;
425
426 crtc = set->crtc;
427 crtc->x = set->x;
428 crtc->y = set->y;
429 stdu = vmw_crtc_to_stdu(crtc);
430 mode = set->mode;
431 new_fb = set->fb;
432 dev_priv = vmw_priv(crtc->dev);
433
434
435 if (set->num_connectors > 1) {
436 DRM_ERROR("Too many connectors\n");
437 return -EINVAL;
438 }
439
440 if (set->num_connectors == 1 &&
441 set->connectors[0] != &stdu->base.connector) {
442 DRM_ERROR("Connectors don't match %p %p\n",
443 set->connectors[0], &stdu->base.connector);
444 return -EINVAL;
445 }
446
447
448 /* Since they always map one to one these are safe */
449 connector = &stdu->base.connector;
450 encoder = &stdu->base.encoder;
451
452
453 /*
454 * After this point the CRTC will be considered off unless a new fb
455 * is bound
456 */
457 if (stdu->defined) {
458 /* Unbind current surface by binding an invalid one */
459 ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
460 if (unlikely(ret != 0))
461 return ret;
462
463 /* Update Screen Target, display will now be blank */
464 if (crtc->primary->fb) {
465 vmw_stdu_update_st(dev_priv, stdu);
466 if (unlikely(ret != 0))
467 return ret;
468 }
469
470 crtc->primary->fb = NULL;
471 crtc->enabled = false;
472 encoder->crtc = NULL;
473 connector->encoder = NULL;
474
475 vmw_stdu_unpin_display(stdu);
476 stdu->content_fb = NULL;
477 stdu->content_fb_type = SAME_AS_DISPLAY;
478
479 ret = vmw_stdu_destroy_st(dev_priv, stdu);
480 /* The hardware is hung, give up */
481 if (unlikely(ret != 0))
482 return ret;
483 }
484
485
486 /* Any of these conditions means the caller wants CRTC off */
487 if (set->num_connectors == 0 || !mode || !new_fb)
488 return 0;
489
490
491 if (set->x + mode->hdisplay > new_fb->width ||
492 set->y + mode->vdisplay > new_fb->height) {
493 DRM_ERROR("Set outside of framebuffer\n");
494 return -EINVAL;
495 }
496 399
497 stdu->content_fb = new_fb; 400 WARN_ON_ONCE(!stdu->defined);
498 vfb = vmw_framebuffer_to_vfb(stdu->content_fb);
499 401
500 if (vfb->dmabuf) 402 if (!vfb->dmabuf && new_fb->width == mode->hdisplay &&
501 stdu->content_fb_type = SEPARATE_DMA; 403 new_fb->height == mode->vdisplay)
404 new_content_type = SAME_AS_DISPLAY;
405 else if (vfb->dmabuf)
406 new_content_type = SEPARATE_DMA;
407 else
408 new_content_type = SEPARATE_SURFACE;
502 409
503 /* 410 if (new_content_type != SAME_AS_DISPLAY &&
504 * If the requested mode is different than the width and height 411 !stdu->display_srf) {
505 * of the FB or if the content buffer is a DMA buf, then allocate
506 * a display FB that matches the dimension of the mode
507 */
508 if (mode->hdisplay != new_fb->width ||
509 mode->vdisplay != new_fb->height ||
510 stdu->content_fb_type != SAME_AS_DISPLAY) {
511 struct vmw_surface content_srf; 412 struct vmw_surface content_srf;
512 struct drm_vmw_size display_base_size = {0}; 413 struct drm_vmw_size display_base_size = {0};
513 struct vmw_surface *display_srf;
514
515 414
516 display_base_size.width = mode->hdisplay; 415 display_base_size.width = mode->hdisplay;
517 display_base_size.height = mode->vdisplay; 416 display_base_size.height = mode->vdisplay;
@@ -521,7 +420,7 @@ static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
521 * If content buffer is a DMA buf, then we have to construct 420 * If content buffer is a DMA buf, then we have to construct
522 * surface info 421 * surface info
523 */ 422 */
524 if (stdu->content_fb_type == SEPARATE_DMA) { 423 if (new_content_type == SEPARATE_DMA) {
525 424
526 switch (new_fb->bits_per_pixel) { 425 switch (new_fb->bits_per_pixel) {
527 case 32: 426 case 32:
@@ -538,17 +437,13 @@ static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
538 437
539 default: 438 default:
540 DRM_ERROR("Invalid format\n"); 439 DRM_ERROR("Invalid format\n");
541 ret = -EINVAL; 440 return -EINVAL;
542 goto err_unref_content;
543 } 441 }
544 442
545 content_srf.flags = 0; 443 content_srf.flags = 0;
546 content_srf.mip_levels[0] = 1; 444 content_srf.mip_levels[0] = 1;
547 content_srf.multisample_count = 0; 445 content_srf.multisample_count = 0;
548 } else { 446 } else {
549
550 stdu->content_fb_type = SEPARATE_SURFACE;
551
552 new_vfbs = vmw_framebuffer_to_vfbs(new_fb); 447 new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
553 content_srf = *new_vfbs->surface; 448 content_srf = *new_vfbs->surface;
554 } 449 }
@@ -563,26 +458,136 @@ static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
563 content_srf.multisample_count, 458 content_srf.multisample_count,
564 0, 459 0,
565 display_base_size, 460 display_base_size,
566 &display_srf); 461 &new_display_srf);
567 if (unlikely(ret != 0)) { 462 if (unlikely(ret != 0)) {
568 DRM_ERROR("Cannot allocate a display FB.\n"); 463 DRM_ERROR("Could not allocate screen target surface.\n");
569 goto err_unref_content; 464 return ret;
570 } 465 }
571 466 } else if (new_content_type == SAME_AS_DISPLAY) {
572 stdu->display_srf = display_srf;
573 } else {
574 new_vfbs = vmw_framebuffer_to_vfbs(new_fb); 467 new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
575 stdu->display_srf = new_vfbs->surface; 468 new_display_srf = vmw_surface_reference(new_vfbs->surface);
576 } 469 }
577 470
471 if (new_display_srf) {
472 /* Pin new surface before flipping */
473 ret = vmw_resource_pin(&new_display_srf->res, false);
474 if (ret)
475 goto out_srf_unref;
476
477 ret = vmw_stdu_bind_st(dev_priv, stdu, &new_display_srf->res);
478 if (ret)
479 goto out_srf_unpin;
480
481 /* Unpin and unreference old surface */
482 vmw_stdu_unpin_display(stdu);
578 483
579 ret = vmw_stdu_pin_display(stdu); 484 /* Transfer the reference */
580 if (unlikely(ret != 0)) { 485 stdu->display_srf = new_display_srf;
581 stdu->display_srf = NULL; 486 new_display_srf = NULL;
582 goto err_unref_content;
583 } 487 }
584 488
585 vmw_svga_enable(dev_priv); 489 crtc->primary->fb = new_fb;
490 stdu->content_fb_type = new_content_type;
491 return 0;
492
493out_srf_unpin:
494 vmw_resource_unpin(&new_display_srf->res);
495out_srf_unref:
496 vmw_surface_unreference(&new_display_srf);
497 return ret;
498}
499
500/**
501 * vmw_stdu_crtc_set_config - Sets a mode
502 *
503 * @set: mode parameters
504 *
505 * This function is the device-specific portion of the DRM CRTC mode set.
506 * For the SVGA device, we do this by defining a Screen Target, binding a
507 * GB Surface to that target, and finally update the screen target.
508 *
509 * RETURNS:
510 * 0 on success, error code otherwise
511 */
512static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
513{
514 struct vmw_private *dev_priv;
515 struct vmw_framebuffer *vfb;
516 struct vmw_screen_target_display_unit *stdu;
517 struct drm_display_mode *mode;
518 struct drm_framebuffer *new_fb;
519 struct drm_crtc *crtc;
520 struct drm_encoder *encoder;
521 struct drm_connector *connector;
522 bool turning_off;
523 int ret;
524
525
526 if (!set || !set->crtc)
527 return -EINVAL;
528
529 crtc = set->crtc;
530 stdu = vmw_crtc_to_stdu(crtc);
531 mode = set->mode;
532 new_fb = set->fb;
533 dev_priv = vmw_priv(crtc->dev);
534 turning_off = set->num_connectors == 0 || !mode || !new_fb;
535 vfb = (new_fb) ? vmw_framebuffer_to_vfb(new_fb) : NULL;
536
537 if (set->num_connectors > 1) {
538 DRM_ERROR("Too many connectors\n");
539 return -EINVAL;
540 }
541
542 if (set->num_connectors == 1 &&
543 set->connectors[0] != &stdu->base.connector) {
544 DRM_ERROR("Connectors don't match %p %p\n",
545 set->connectors[0], &stdu->base.connector);
546 return -EINVAL;
547 }
548
549 if (!turning_off && (set->x + mode->hdisplay > new_fb->width ||
550 set->y + mode->vdisplay > new_fb->height)) {
551 DRM_ERROR("Set outside of framebuffer\n");
552 return -EINVAL;
553 }
554
555 /* Only one active implicit frame-buffer at a time. */
556 if (!turning_off && stdu->base.is_implicit && dev_priv->implicit_fb &&
557 !(dev_priv->num_implicit == 1 && stdu->base.active_implicit)
558 && dev_priv->implicit_fb != vfb) {
559 DRM_ERROR("Multiple implicit framebuffers not supported.\n");
560 return -EINVAL;
561 }
562
563 /* Since they always map one to one these are safe */
564 connector = &stdu->base.connector;
565 encoder = &stdu->base.encoder;
566
567 if (stdu->defined) {
568 ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
569 if (ret)
570 return ret;
571
572 vmw_stdu_unpin_display(stdu);
573 (void) vmw_stdu_update_st(dev_priv, stdu);
574 vmw_kms_del_active(dev_priv, &stdu->base);
575
576 ret = vmw_stdu_destroy_st(dev_priv, stdu);
577 if (ret)
578 return ret;
579
580 crtc->primary->fb = NULL;
581 crtc->enabled = false;
582 encoder->crtc = NULL;
583 connector->encoder = NULL;
584 stdu->content_fb_type = SAME_AS_DISPLAY;
585 crtc->x = set->x;
586 crtc->y = set->y;
587 }
588
589 if (turning_off)
590 return 0;
586 591
587 /* 592 /*
588 * Steps to displaying a surface, assume surface is already 593 * Steps to displaying a surface, assume surface is already
@@ -592,35 +597,33 @@ static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
592 * 3. update that screen target (this is done later by 597 * 3. update that screen target (this is done later by
593 * vmw_kms_stdu_do_surface_dirty_or_present) 598 * vmw_kms_stdu_do_surface_dirty_or_present)
594 */ 599 */
595 ret = vmw_stdu_define_st(dev_priv, stdu); 600 /*
596 if (unlikely(ret != 0)) 601 * Note on error handling: We can't really restore the crtc to
597 goto err_unpin_display_and_content; 602 * it's original state on error, but we at least update the
603 * current state to what's submitted to hardware to enable
604 * future recovery.
605 */
606 vmw_svga_enable(dev_priv);
607 ret = vmw_stdu_define_st(dev_priv, stdu, mode, set->x, set->y);
608 if (ret)
609 return ret;
598 610
599 ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); 611 crtc->x = set->x;
600 if (unlikely(ret != 0)) 612 crtc->y = set->y;
601 goto err_unpin_destroy_st; 613 crtc->mode = *mode;
602 614
615 ret = vmw_stdu_bind_fb(dev_priv, crtc, mode, new_fb);
616 if (ret)
617 return ret;
603 618
619 vmw_kms_add_active(dev_priv, &stdu->base, vfb);
620 crtc->enabled = true;
604 connector->encoder = encoder; 621 connector->encoder = encoder;
605 encoder->crtc = crtc; 622 encoder->crtc = crtc;
606 623
607 crtc->mode = *mode; 624 return 0;
608 crtc->primary->fb = new_fb;
609 crtc->enabled = true;
610
611 return ret;
612
613err_unpin_destroy_st:
614 vmw_stdu_destroy_st(dev_priv, stdu);
615err_unpin_display_and_content:
616 vmw_stdu_unpin_display(stdu);
617err_unref_content:
618 stdu->content_fb = NULL;
619 return ret;
620} 625}
621 626
622
623
624/** 627/**
625 * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target 628 * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
626 * 629 *
@@ -648,59 +651,34 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
648{ 651{
649 struct vmw_private *dev_priv = vmw_priv(crtc->dev); 652 struct vmw_private *dev_priv = vmw_priv(crtc->dev);
650 struct vmw_screen_target_display_unit *stdu; 653 struct vmw_screen_target_display_unit *stdu;
654 struct drm_vmw_rect vclips;
655 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
651 int ret; 656 int ret;
652 657
653 if (crtc == NULL)
654 return -EINVAL;
655
656 dev_priv = vmw_priv(crtc->dev); 658 dev_priv = vmw_priv(crtc->dev);
657 stdu = vmw_crtc_to_stdu(crtc); 659 stdu = vmw_crtc_to_stdu(crtc);
658 crtc->primary->fb = new_fb;
659 stdu->content_fb = new_fb;
660
661 if (stdu->display_srf) {
662 /*
663 * If the display surface is the same as the content surface
664 * then remove the reference
665 */
666 if (stdu->content_fb_type == SAME_AS_DISPLAY) {
667 if (stdu->defined) {
668 /* Unbind the current surface */
669 ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
670 if (unlikely(ret != 0))
671 goto err_out;
672 }
673 vmw_stdu_unpin_display(stdu);
674 stdu->display_srf = NULL;
675 }
676 }
677
678
679 if (!new_fb) {
680 /* Blanks the display */
681 (void) vmw_stdu_update_st(dev_priv, stdu);
682
683 return 0;
684 }
685 660
661 if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc))
662 return -EINVAL;
686 663
687 if (stdu->content_fb_type == SAME_AS_DISPLAY) { 664 ret = vmw_stdu_bind_fb(dev_priv, crtc, &crtc->mode, new_fb);
688 stdu->display_srf = vmw_framebuffer_to_vfbs(new_fb)->surface; 665 if (ret)
689 ret = vmw_stdu_pin_display(stdu); 666 return ret;
690 if (ret) {
691 stdu->display_srf = NULL;
692 goto err_out;
693 }
694 667
695 /* Bind display surface */ 668 if (stdu->base.is_implicit)
696 ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); 669 vmw_kms_update_implicit_fb(dev_priv, crtc);
697 if (unlikely(ret != 0))
698 goto err_unpin_display_and_content;
699 }
700 670
701 /* Update display surface: after this point everything is bound */ 671 vclips.x = crtc->x;
702 ret = vmw_stdu_update_st(dev_priv, stdu); 672 vclips.y = crtc->y;
703 if (unlikely(ret != 0)) 673 vclips.w = crtc->mode.hdisplay;
674 vclips.h = crtc->mode.vdisplay;
675 if (vfb->dmabuf)
676 ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips,
677 1, 1, true, false);
678 else
679 ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, &vclips,
680 NULL, 0, 0, 1, 1, NULL);
681 if (ret)
704 return ret; 682 return ret;
705 683
706 if (event) { 684 if (event) {
@@ -721,14 +699,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
721 vmw_fifo_flush(dev_priv, false); 699 vmw_fifo_flush(dev_priv, false);
722 } 700 }
723 701
724 return ret; 702 return 0;
725
726err_unpin_display_and_content:
727 vmw_stdu_unpin_display(stdu);
728err_out:
729 crtc->primary->fb = NULL;
730 stdu->content_fb = NULL;
731 return ret;
732} 703}
733 704
734 705
@@ -1138,7 +1109,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
1138 stdu->base.pref_active = (unit == 0); 1109 stdu->base.pref_active = (unit == 0);
1139 stdu->base.pref_width = dev_priv->initial_width; 1110 stdu->base.pref_width = dev_priv->initial_width;
1140 stdu->base.pref_height = dev_priv->initial_height; 1111 stdu->base.pref_height = dev_priv->initial_height;
1141 stdu->base.is_implicit = true; 1112 stdu->base.is_implicit = false;
1142 1113
1143 drm_connector_init(dev, connector, &vmw_stdu_connector_funcs, 1114 drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
1144 DRM_MODE_CONNECTOR_VIRTUAL); 1115 DRM_MODE_CONNECTOR_VIRTUAL);
@@ -1159,7 +1130,17 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
1159 drm_object_attach_property(&connector->base, 1130 drm_object_attach_property(&connector->base,
1160 dev->mode_config.dirty_info_property, 1131 dev->mode_config.dirty_info_property,
1161 1); 1132 1);
1162 1133 drm_object_attach_property(&connector->base,
1134 dev_priv->hotplug_mode_update_property, 1);
1135 drm_object_attach_property(&connector->base,
1136 dev->mode_config.suggested_x_property, 0);
1137 drm_object_attach_property(&connector->base,
1138 dev->mode_config.suggested_y_property, 0);
1139 if (dev_priv->implicit_placement_property)
1140 drm_object_attach_property
1141 (&connector->base,
1142 dev_priv->implicit_placement_property,
1143 stdu->base.is_implicit);
1163 return 0; 1144 return 0;
1164} 1145}
1165 1146
@@ -1224,6 +1205,8 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
1224 1205
1225 dev_priv->active_display_unit = vmw_du_screen_target; 1206 dev_priv->active_display_unit = vmw_du_screen_target;
1226 1207
1208 vmw_kms_create_implicit_placement_property(dev_priv, false);
1209
1227 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) { 1210 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) {
1228 ret = vmw_stdu_init(dev_priv, i); 1211 ret = vmw_stdu_init(dev_priv, i);
1229 1212