Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vmwgfx_scrn.c
Go to the documentation of this file.
1 /**************************************************************************
2  *
3  * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include "vmwgfx_kms.h"
29 
30 
31 #define vmw_crtc_to_sou(x) \
32  container_of(x, struct vmw_screen_object_unit, base.crtc)
33 #define vmw_encoder_to_sou(x) \
34  container_of(x, struct vmw_screen_object_unit, base.encoder)
35 #define vmw_connector_to_sou(x) \
36  container_of(x, struct vmw_screen_object_unit, base.connector)
37 
39  unsigned num_implicit;
40 
42 };
43 
49 
50  unsigned long buffer_size;
53  bool defined;
55 };
56 
57 static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
58 {
60  kfree(sou);
61 }
62 
63 
64 /*
65  * Screen Object Display Unit CRTC functions
66  */
67 
68 static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
69 {
70  vmw_sou_destroy(vmw_crtc_to_sou(crtc));
71 }
72 
73 static void vmw_sou_del_active(struct vmw_private *vmw_priv,
74  struct vmw_screen_object_unit *sou)
75 {
76  struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
77 
78  if (sou->active_implicit) {
79  if (--(ld->num_implicit) == 0)
80  ld->implicit_fb = NULL;
81  sou->active_implicit = false;
82  }
83 }
84 
85 static void vmw_sou_add_active(struct vmw_private *vmw_priv,
86  struct vmw_screen_object_unit *sou,
87  struct vmw_framebuffer *vfb)
88 {
89  struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
90 
91  BUG_ON(!ld->num_implicit && ld->implicit_fb);
92 
93  if (!sou->active_implicit && sou->base.is_implicit) {
94  ld->implicit_fb = vfb;
95  sou->active_implicit = true;
96  ld->num_implicit++;
97  }
98 }
99 
103 static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
104  struct vmw_screen_object_unit *sou,
105  uint32_t x, uint32_t y,
106  struct drm_display_mode *mode)
107 {
108  size_t fifo_size;
109 
110  struct {
111  struct {
112  uint32_t cmdType;
113  } header;
114  SVGAScreenObject obj;
115  } *cmd;
116 
117  BUG_ON(!sou->buffer);
118 
119  fifo_size = sizeof(*cmd);
120  cmd = vmw_fifo_reserve(dev_priv, fifo_size);
121  /* The hardware has hung, nothing we can do about it here. */
122  if (unlikely(cmd == NULL)) {
123  DRM_ERROR("Fifo reserve failed.\n");
124  return -ENOMEM;
125  }
126 
127  memset(cmd, 0, fifo_size);
128  cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
129  cmd->obj.structSize = sizeof(SVGAScreenObject);
130  cmd->obj.id = sou->base.unit;
131  cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
132  (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
133  cmd->obj.size.width = mode->hdisplay;
134  cmd->obj.size.height = mode->vdisplay;
135  if (sou->base.is_implicit) {
136  cmd->obj.root.x = x;
137  cmd->obj.root.y = y;
138  } else {
139  cmd->obj.root.x = sou->base.gui_x;
140  cmd->obj.root.y = sou->base.gui_y;
141  }
142 
143  /* Ok to assume that buffer is pinned in vram */
144  vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
145  cmd->obj.backingStore.pitch = mode->hdisplay * 4;
146 
147  vmw_fifo_commit(dev_priv, fifo_size);
148 
149  sou->defined = true;
150 
151  return 0;
152 }
153 
157 static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
158  struct vmw_screen_object_unit *sou)
159 {
160  size_t fifo_size;
161  int ret;
162 
163  struct {
164  struct {
165  uint32_t cmdType;
166  } header;
168  } *cmd;
169 
170  /* no need to do anything */
171  if (unlikely(!sou->defined))
172  return 0;
173 
174  fifo_size = sizeof(*cmd);
175  cmd = vmw_fifo_reserve(dev_priv, fifo_size);
176  /* the hardware has hung, nothing we can do about it here */
177  if (unlikely(cmd == NULL)) {
178  DRM_ERROR("Fifo reserve failed.\n");
179  return -ENOMEM;
180  }
181 
182  memset(cmd, 0, fifo_size);
183  cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
184  cmd->body.screenId = sou->base.unit;
185 
186  vmw_fifo_commit(dev_priv, fifo_size);
187 
188  /* Force sync */
189  ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
190  if (unlikely(ret != 0))
191  DRM_ERROR("Failed to sync with HW");
192  else
193  sou->defined = false;
194 
195  return ret;
196 }
197 
201 static void vmw_sou_backing_free(struct vmw_private *dev_priv,
202  struct vmw_screen_object_unit *sou)
203 {
204  struct ttm_buffer_object *bo;
205 
206  if (unlikely(sou->buffer == NULL))
207  return;
208 
209  bo = &sou->buffer->base;
210  ttm_bo_unref(&bo);
211  sou->buffer = NULL;
212  sou->buffer_size = 0;
213 }
214 
218 static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
219  struct vmw_screen_object_unit *sou,
220  unsigned long size)
221 {
222  int ret;
223 
224  if (sou->buffer_size == size)
225  return 0;
226 
227  if (sou->buffer)
228  vmw_sou_backing_free(dev_priv, sou);
229 
230  sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
231  if (unlikely(sou->buffer == NULL))
232  return -ENOMEM;
233 
234  /* After we have alloced the backing store might not be able to
235  * resume the overlays, this is preferred to failing to alloc.
236  */
237  vmw_overlay_pause_all(dev_priv);
238  ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
240  false, &vmw_dmabuf_bo_free);
241  vmw_overlay_resume_all(dev_priv);
242 
243  if (unlikely(ret != 0))
244  sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
245  else
246  sou->buffer_size = size;
247 
248  return ret;
249 }
250 
251 static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
252 {
253  struct vmw_private *dev_priv;
254  struct vmw_screen_object_unit *sou;
255  struct drm_connector *connector;
256  struct drm_display_mode *mode;
257  struct drm_encoder *encoder;
258  struct vmw_framebuffer *vfb;
259  struct drm_framebuffer *fb;
260  struct drm_crtc *crtc;
261  int ret = 0;
262 
263  if (!set)
264  return -EINVAL;
265 
266  if (!set->crtc)
267  return -EINVAL;
268 
269  /* get the sou */
270  crtc = set->crtc;
271  sou = vmw_crtc_to_sou(crtc);
272  vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
273  dev_priv = vmw_priv(crtc->dev);
274 
275  if (set->num_connectors > 1) {
276  DRM_ERROR("to many connectors\n");
277  return -EINVAL;
278  }
279 
280  if (set->num_connectors == 1 &&
281  set->connectors[0] != &sou->base.connector) {
282  DRM_ERROR("connector doesn't match %p %p\n",
283  set->connectors[0], &sou->base.connector);
284  return -EINVAL;
285  }
286 
287  /* sou only supports one fb active at the time */
288  if (sou->base.is_implicit &&
289  dev_priv->sou_priv->implicit_fb && vfb &&
290  !(dev_priv->sou_priv->num_implicit == 1 &&
291  sou->active_implicit) &&
292  dev_priv->sou_priv->implicit_fb != vfb) {
293  DRM_ERROR("Multiple framebuffers not supported\n");
294  return -EINVAL;
295  }
296 
297  /* since they always map one to one these are safe */
298  connector = &sou->base.connector;
299  encoder = &sou->base.encoder;
300 
301  /* should we turn the crtc off */
302  if (set->num_connectors == 0 || !set->mode || !set->fb) {
303  ret = vmw_sou_fifo_destroy(dev_priv, sou);
304  /* the hardware has hung don't do anything more */
305  if (unlikely(ret != 0))
306  return ret;
307 
308  connector->encoder = NULL;
309  encoder->crtc = NULL;
310  crtc->fb = NULL;
311  crtc->x = 0;
312  crtc->y = 0;
313 
314  vmw_sou_del_active(dev_priv, sou);
315 
316  vmw_sou_backing_free(dev_priv, sou);
317 
318  return 0;
319  }
320 
321 
322  /* we now know we want to set a mode */
323  mode = set->mode;
324  fb = set->fb;
325 
326  if (set->x + mode->hdisplay > fb->width ||
327  set->y + mode->vdisplay > fb->height) {
328  DRM_ERROR("set outside of framebuffer\n");
329  return -EINVAL;
330  }
331 
332  vmw_fb_off(dev_priv);
333 
334  if (mode->hdisplay != crtc->mode.hdisplay ||
335  mode->vdisplay != crtc->mode.vdisplay) {
336  /* no need to check if depth is different, because backing
337  * store depth is forced to 4 by the device.
338  */
339 
340  ret = vmw_sou_fifo_destroy(dev_priv, sou);
341  /* the hardware has hung don't do anything more */
342  if (unlikely(ret != 0))
343  return ret;
344 
345  vmw_sou_backing_free(dev_priv, sou);
346  }
347 
348  if (!sou->buffer) {
349  /* forced to depth 4 by the device */
350  size_t size = mode->hdisplay * mode->vdisplay * 4;
351  ret = vmw_sou_backing_alloc(dev_priv, sou, size);
352  if (unlikely(ret != 0))
353  return ret;
354  }
355 
356  ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
357  if (unlikely(ret != 0)) {
358  /*
359  * We are in a bit of a situation here, the hardware has
360  * hung and we may or may not have a buffer hanging of
361  * the screen object, best thing to do is not do anything
362  * if we where defined, if not just turn the crtc of.
363  * Not what userspace wants but it needs to htfu.
364  */
365  if (sou->defined)
366  return ret;
367 
368  connector->encoder = NULL;
369  encoder->crtc = NULL;
370  crtc->fb = NULL;
371  crtc->x = 0;
372  crtc->y = 0;
373 
374  return ret;
375  }
376 
377  vmw_sou_add_active(dev_priv, sou, vfb);
378 
379  connector->encoder = encoder;
380  encoder->crtc = crtc;
381  crtc->mode = *mode;
382  crtc->fb = fb;
383  crtc->x = set->x;
384  crtc->y = set->y;
385 
386  return 0;
387 }
388 
389 static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
390  .save = vmw_du_crtc_save,
391  .restore = vmw_du_crtc_restore,
392  .cursor_set = vmw_du_crtc_cursor_set,
393  .cursor_move = vmw_du_crtc_cursor_move,
394  .gamma_set = vmw_du_crtc_gamma_set,
395  .destroy = vmw_sou_crtc_destroy,
396  .set_config = vmw_sou_crtc_set_config,
397  .page_flip = vmw_du_page_flip,
398 };
399 
400 /*
401  * Screen Object Display Unit encoder functions
402  */
403 
404 static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
405 {
406  vmw_sou_destroy(vmw_encoder_to_sou(encoder));
407 }
408 
409 static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
410  .destroy = vmw_sou_encoder_destroy,
411 };
412 
413 /*
414  * Screen Object Display Unit connector functions
415  */
416 
417 static void vmw_sou_connector_destroy(struct drm_connector *connector)
418 {
419  vmw_sou_destroy(vmw_connector_to_sou(connector));
420 }
421 
422 static struct drm_connector_funcs vmw_legacy_connector_funcs = {
423  .dpms = vmw_du_connector_dpms,
424  .save = vmw_du_connector_save,
425  .restore = vmw_du_connector_restore,
426  .detect = vmw_du_connector_detect,
427  .fill_modes = vmw_du_connector_fill_modes,
428  .set_property = vmw_du_connector_set_property,
429  .destroy = vmw_sou_connector_destroy,
430 };
431 
432 static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
433 {
434  struct vmw_screen_object_unit *sou;
435  struct drm_device *dev = dev_priv->dev;
436  struct drm_connector *connector;
437  struct drm_encoder *encoder;
438  struct drm_crtc *crtc;
439 
440  sou = kzalloc(sizeof(*sou), GFP_KERNEL);
441  if (!sou)
442  return -ENOMEM;
443 
444  sou->base.unit = unit;
445  crtc = &sou->base.crtc;
446  encoder = &sou->base.encoder;
447  connector = &sou->base.connector;
448 
449  sou->active_implicit = false;
450 
451  sou->base.pref_active = (unit == 0);
452  sou->base.pref_width = dev_priv->initial_width;
453  sou->base.pref_height = dev_priv->initial_height;
454  sou->base.pref_mode = NULL;
455  sou->base.is_implicit = true;
456 
457  drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
459  connector->status = vmw_du_connector_detect(connector, true);
460 
461  drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
463  drm_mode_connector_attach_encoder(connector, encoder);
464  encoder->possible_crtcs = (1 << unit);
465  encoder->possible_clones = 0;
466 
467  drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
468 
469  drm_mode_crtc_set_gamma_size(crtc, 256);
470 
472  dev->mode_config.dirty_info_property,
473  1);
474 
475  return 0;
476 }
477 
479 {
480  struct drm_device *dev = dev_priv->dev;
481  int i, ret;
482 
483  if (dev_priv->sou_priv) {
484  DRM_INFO("sou system already on\n");
485  return -EINVAL;
486  }
487 
488  if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_SCREEN_OBJECT_2)) {
489  DRM_INFO("Not using screen objects,"
490  " missing cap SCREEN_OBJECT_2\n");
491  return -ENOSYS;
492  }
493 
494  ret = -ENOMEM;
495  dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
496  if (unlikely(!dev_priv->sou_priv))
497  goto err_no_mem;
498 
499  dev_priv->sou_priv->num_implicit = 0;
500  dev_priv->sou_priv->implicit_fb = NULL;
501 
503  if (unlikely(ret != 0))
504  goto err_free;
505 
507  if (unlikely(ret != 0))
508  goto err_vblank_cleanup;
509 
510  for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
511  vmw_sou_init(dev_priv, i);
512 
513  DRM_INFO("Screen objects system initialized\n");
514 
515  return 0;
516 
517 err_vblank_cleanup:
518  drm_vblank_cleanup(dev);
519 err_free:
520  kfree(dev_priv->sou_priv);
521  dev_priv->sou_priv = NULL;
522 err_no_mem:
523  return ret;
524 }
525 
527 {
528  struct drm_device *dev = dev_priv->dev;
529 
530  if (!dev_priv->sou_priv)
531  return -ENOSYS;
532 
533  drm_vblank_cleanup(dev);
534 
535  kfree(dev_priv->sou_priv);
536 
537  return 0;
538 }
539 
545  struct drm_crtc *crtc)
546 {
547  struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
548 
549  if (!sou->base.is_implicit)
550  return true;
551 
552  if (dev_priv->sou_priv->num_implicit != 1)
553  return false;
554 
555  return true;
556 }
557 
563  struct drm_crtc *crtc)
564 {
565  struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
566 
567  BUG_ON(!sou->base.is_implicit);
568 
569  dev_priv->sou_priv->implicit_fb =
570  vmw_framebuffer_to_vfb(sou->base.crtc.fb);
571 }