Subversion Repositories Kolibri OS

Rev

Rev 4569 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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.  
  38. struct vmw_screen_object_display {
  39.         unsigned num_implicit;
  40.  
  41.         struct vmw_framebuffer *implicit_fb;
  42. };
  43.  
  44. /**
  45.  * Display unit using screen objects.
  46.  */
  47. struct vmw_screen_object_unit {
  48.         struct vmw_display_unit base;
  49.  
  50.         unsigned long buffer_size; /**< Size of allocated buffer */
  51.         struct vmw_dma_buffer *buffer; /**< Backing store buffer */
  52.  
  53.         bool defined;
  54.         bool active_implicit;
  55. };
  56.  
  57. static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
  58. {
  59. //   vmw_display_unit_cleanup(&sou->base);
  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.  
  100. /**
  101.  * Send the fifo command to create a screen.
  102.  */
  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.  
  154. /**
  155.  * Send the fifo command to destroy a screen.
  156.  */
  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;
  167.                 SVGAFifoCmdDestroyScreen body;
  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.  
  198. /**
  199.  * Free the backing store.
  200.  */
  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.  
  215. /**
  216.  * Allocate the backing store for the buffer.
  217.  */
  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,
  239.                               &vmw_vram_ne_placement,
  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->primary->fb = NULL;
  311.                 crtc->x = 0;
  312.                 crtc->y = 0;
  313.                 crtc->enabled = false;
  314.  
  315.                 vmw_sou_del_active(dev_priv, sou);
  316.  
  317.                 vmw_sou_backing_free(dev_priv, sou);
  318.  
  319.                 return 0;
  320.         }
  321.  
  322.  
  323.         /* we now know we want to set a mode */
  324.         mode = set->mode;
  325.         fb = set->fb;
  326.  
  327.         if (set->x + mode->hdisplay > fb->width ||
  328.             set->y + mode->vdisplay > fb->height) {
  329.                 DRM_ERROR("set outside of framebuffer\n");
  330.                 return -EINVAL;
  331.         }
  332.  
  333. //   vmw_fb_off(dev_priv);
  334.  
  335.         if (mode->hdisplay != crtc->mode.hdisplay ||
  336.             mode->vdisplay != crtc->mode.vdisplay) {
  337.                 /* no need to check if depth is different, because backing
  338.                  * store depth is forced to 4 by the device.
  339.                  */
  340.  
  341.                 ret = vmw_sou_fifo_destroy(dev_priv, sou);
  342.                 /* the hardware has hung don't do anything more */
  343.                 if (unlikely(ret != 0))
  344.                         return ret;
  345.  
  346.                 vmw_sou_backing_free(dev_priv, sou);
  347.         }
  348.  
  349.         if (!sou->buffer) {
  350.                 /* forced to depth 4 by the device */
  351.                 size_t size = mode->hdisplay * mode->vdisplay * 4;
  352.                 ret = vmw_sou_backing_alloc(dev_priv, sou, size);
  353.                 if (unlikely(ret != 0))
  354.                         return ret;
  355.         }
  356.  
  357.         ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
  358.         if (unlikely(ret != 0)) {
  359.                 /*
  360.                  * We are in a bit of a situation here, the hardware has
  361.                  * hung and we may or may not have a buffer hanging of
  362.                  * the screen object, best thing to do is not do anything
  363.                  * if we where defined, if not just turn the crtc of.
  364.                  * Not what userspace wants but it needs to htfu.
  365.                  */
  366.                 if (sou->defined)
  367.                         return ret;
  368.  
  369.                 connector->encoder = NULL;
  370.                 encoder->crtc = NULL;
  371.                 crtc->primary->fb = NULL;
  372.                 crtc->x = 0;
  373.                 crtc->y = 0;
  374.                 crtc->enabled = false;
  375.  
  376.                 return ret;
  377.         }
  378.  
  379.         vmw_sou_add_active(dev_priv, sou, vfb);
  380.  
  381.         connector->encoder = encoder;
  382.         encoder->crtc = crtc;
  383.         crtc->mode = *mode;
  384.         crtc->primary->fb = fb;
  385.         crtc->x = set->x;
  386.         crtc->y = set->y;
  387.         crtc->enabled = true;
  388.  
  389.         return 0;
  390. }
  391.  
  392. static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
  393.         .save = vmw_du_crtc_save,
  394.         .restore = vmw_du_crtc_restore,
  395. //   .cursor_set = vmw_du_crtc_cursor_set,
  396. //   .cursor_move = vmw_du_crtc_cursor_move,
  397.         .gamma_set = vmw_du_crtc_gamma_set,
  398.         .destroy = vmw_sou_crtc_destroy,
  399.         .set_config = vmw_sou_crtc_set_config,
  400. //   .page_flip = vmw_du_page_flip,
  401. };
  402.  
  403. /*
  404.  * Screen Object Display Unit encoder functions
  405.  */
  406.  
  407. static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
  408. {
  409.         vmw_sou_destroy(vmw_encoder_to_sou(encoder));
  410. }
  411.  
  412. static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
  413.         .destroy = vmw_sou_encoder_destroy,
  414. };
  415.  
  416. /*
  417.  * Screen Object Display Unit connector functions
  418.  */
  419.  
  420. static void vmw_sou_connector_destroy(struct drm_connector *connector)
  421. {
  422.         vmw_sou_destroy(vmw_connector_to_sou(connector));
  423. }
  424.  
  425. static struct drm_connector_funcs vmw_legacy_connector_funcs = {
  426.         .dpms = vmw_du_connector_dpms,
  427.         .save = vmw_du_connector_save,
  428.         .restore = vmw_du_connector_restore,
  429.         .detect = vmw_du_connector_detect,
  430.         .fill_modes = vmw_du_connector_fill_modes,
  431.         .set_property = vmw_du_connector_set_property,
  432.         .destroy = vmw_sou_connector_destroy,
  433. };
  434.  
  435. static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
  436. {
  437.         struct vmw_screen_object_unit *sou;
  438.         struct drm_device *dev = dev_priv->dev;
  439.         struct drm_connector *connector;
  440.         struct drm_encoder *encoder;
  441.         struct drm_crtc *crtc;
  442.  
  443.         sou = kzalloc(sizeof(*sou), GFP_KERNEL);
  444.         if (!sou)
  445.                 return -ENOMEM;
  446.  
  447.         sou->base.unit = unit;
  448.         crtc = &sou->base.crtc;
  449.         encoder = &sou->base.encoder;
  450.         connector = &sou->base.connector;
  451.  
  452.         sou->active_implicit = false;
  453.  
  454.         sou->base.pref_active = (unit == 0);
  455.         sou->base.pref_width = dev_priv->initial_width;
  456.         sou->base.pref_height = dev_priv->initial_height;
  457.         sou->base.pref_mode = NULL;
  458.         sou->base.is_implicit = true;
  459.  
  460.         drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
  461.                            DRM_MODE_CONNECTOR_VIRTUAL);
  462.         connector->status = vmw_du_connector_detect(connector, true);
  463.  
  464.         drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
  465.                          DRM_MODE_ENCODER_VIRTUAL);
  466.         drm_mode_connector_attach_encoder(connector, encoder);
  467.         encoder->possible_crtcs = (1 << unit);
  468.         encoder->possible_clones = 0;
  469.  
  470.         (void) drm_connector_register(connector);
  471.  
  472.         drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
  473.  
  474.         drm_mode_crtc_set_gamma_size(crtc, 256);
  475.  
  476.         drm_object_attach_property(&connector->base,
  477.                                       dev->mode_config.dirty_info_property,
  478.                                       1);
  479.  
  480.         return 0;
  481. }
  482.  
  483. int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
  484. {
  485.         struct drm_device *dev = dev_priv->dev;
  486.         int i, ret;
  487.  
  488.         if (dev_priv->sou_priv) {
  489.                 DRM_INFO("sou system already on\n");
  490.                 return -EINVAL;
  491.         }
  492.  
  493.         if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
  494.                 DRM_INFO("Not using screen objects,"
  495.                          " missing cap SCREEN_OBJECT_2\n");
  496.                 return -ENOSYS;
  497.         }
  498.  
  499.         ret = -ENOMEM;
  500.         dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
  501.         if (unlikely(!dev_priv->sou_priv))
  502.                 goto err_no_mem;
  503.  
  504.         dev_priv->sou_priv->num_implicit = 0;
  505.         dev_priv->sou_priv->implicit_fb = NULL;
  506.  
  507.  
  508.         ret = drm_mode_create_dirty_info_property(dev);
  509.         if (unlikely(ret != 0))
  510.                 goto err_vblank_cleanup;
  511.  
  512.         for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
  513.                 vmw_sou_init(dev_priv, i);
  514.  
  515.         DRM_INFO("Screen objects system initialized\n");
  516.  
  517.         return 0;
  518.  
  519. err_vblank_cleanup:
  520. //   drm_vblank_cleanup(dev);
  521. err_free:
  522.         kfree(dev_priv->sou_priv);
  523.         dev_priv->sou_priv = NULL;
  524. err_no_mem:
  525.         return ret;
  526. }
  527.  
  528. int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
  529. {
  530.         struct drm_device *dev = dev_priv->dev;
  531.  
  532.         if (!dev_priv->sou_priv)
  533.                 return -ENOSYS;
  534.  
  535. //   drm_vblank_cleanup(dev);
  536.  
  537.         kfree(dev_priv->sou_priv);
  538.  
  539.         return 0;
  540. }
  541.  
  542. /**
  543.  * Returns if this unit can be page flipped.
  544.  * Must be called with the mode_config mutex held.
  545.  */
  546. bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv,
  547.                                      struct drm_crtc *crtc)
  548. {
  549.         struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
  550.  
  551.         if (!sou->base.is_implicit)
  552.                 return true;
  553.  
  554.         if (dev_priv->sou_priv->num_implicit != 1)
  555.                 return false;
  556.  
  557.         return true;
  558. }
  559.  
  560. /**
  561.  * Update the implicit fb to the current fb of this crtc.
  562.  * Must be called with the mode_config mutex held.
  563.  */
  564. void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
  565.                                               struct drm_crtc *crtc)
  566. {
  567.         struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
  568.  
  569.         BUG_ON(!sou->base.is_implicit);
  570.  
  571.         dev_priv->sou_priv->implicit_fb =
  572.                 vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
  573. }
  574.  
  575. #include "bitmap.h"
  576.  
  577. typedef struct
  578. {
  579.     kobj_t     header;
  580.  
  581.     uint32_t  *data;
  582.     uint32_t   hot_x;
  583.     uint32_t   hot_y;
  584.  
  585.     struct list_head   list;
  586. //    struct drm_i915_gem_object  *cobj;
  587. }cursor_t;
  588.  
  589.  
  590. struct tag_display
  591. {
  592.     int  x;
  593.     int  y;
  594.     int  width;
  595.     int  height;
  596.     int  bpp;
  597.     int  vrefresh;
  598.     int  pitch;
  599.     int  lfb;
  600.  
  601.     int  supported_modes;
  602.     struct drm_device    *ddev;
  603.     struct drm_connector *connector;
  604.     struct drm_crtc      *crtc;
  605.  
  606.     struct list_head   cursors;
  607.  
  608.     cursor_t   *cursor;
  609.     int       (*init_cursor)(cursor_t*);
  610.     cursor_t* (__stdcall *select_cursor)(cursor_t*);
  611.     void      (*show_cursor)(int show);
  612.     void      (__stdcall *move_cursor)(cursor_t *cursor, int x, int y);
  613.     void      (__stdcall *restore_cursor)(int x, int y);
  614.     void      (*disable_mouse)(void);
  615.     u32  mask_seqno;
  616.     u32  check_mouse;
  617.     u32  check_m_pixel;
  618.     u32  dirty;
  619.     void (*update)(void);
  620. };
  621.  
  622. bool set_mode(struct drm_device *dev, struct drm_connector *connector,
  623.               videomode_t *reqmode, bool strict)
  624. {
  625.     struct drm_display_mode  *mode = NULL, *tmpmode;
  626.     struct vmw_private *dev_priv = vmw_priv(dev);
  627.     struct vmw_screen_object_unit *sou;
  628.     display_t *os_display;
  629.  
  630.     bool ret = false;
  631.  
  632. //    dbgprintf("width %d height %d vrefresh %d\n",
  633. //               reqmode->width, reqmode->height, reqmode->freq);
  634.  
  635.     list_for_each_entry(tmpmode, &connector->modes, head)
  636.     {
  637.         if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
  638.             (drm_mode_height(tmpmode)   == reqmode->height) &&
  639.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  640.         {
  641.             mode = tmpmode;
  642.             goto do_set;
  643.         }
  644.     };
  645.  
  646.     if( (mode == NULL) && (strict == false) )
  647.     {
  648.         list_for_each_entry(tmpmode, &connector->modes, head)
  649.         {
  650.             if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
  651.                 (drm_mode_height(tmpmode) == reqmode->height) )
  652.             {
  653.                 mode = tmpmode;
  654.                 goto do_set;
  655.             }
  656.         };
  657.     };
  658.  
  659. do_set:
  660.  
  661.     if( mode != NULL )
  662.     {
  663.         struct drm_framebuffer   *fb;
  664.         struct drm_encoder       *encoder;
  665.         struct drm_crtc          *crtc;
  666.  
  667. //        char  con_edid[128];
  668.         const char *con_name;
  669.         const char *enc_name;
  670.  
  671.         encoder = connector->encoder;
  672.         crtc = encoder->crtc;
  673.  
  674.  
  675. //        fb = list_first_entry(&dev->mode_config.fb_kernel_list,
  676. //                              struct drm_framebuffer, filp_head);
  677.  
  678. //        memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  679.  
  680. //        dbgprintf("Manufacturer: %s Model %x Serial Number %u\n",
  681. //        manufacturer_name(con_edid + 0x08),
  682. //        (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  683. //        (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  684. //            + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  685.  
  686.         con_name = drm_get_connector_name(connector);
  687.         enc_name = drm_get_encoder_name(encoder);
  688.  
  689.         dbgprintf("set mode %d %d connector %s encoder %s\n",
  690.                    mode->hdisplay, mode->vdisplay, con_name, enc_name);
  691.  
  692.         os_display = GetDisplay();
  693.  
  694. #if 0
  695.         sou = vmw_crtc_to_sou(crtc);
  696.         sou->defined = true;
  697.  
  698.         ret = vmw_sou_fifo_destroy(dev_priv, sou);
  699.         if (unlikely(ret != 0))
  700.             return ret;
  701.  
  702.         ret = vmw_sou_fifo_create(dev_priv, sou, 0, 0, mode);
  703.  
  704. #else   /*   sledgehammer  */
  705.  
  706.         vmw_write(dev_priv,SVGA_REG_WIDTH,  mode->hdisplay);
  707.         vmw_write(dev_priv,SVGA_REG_HEIGHT, mode->vdisplay);
  708.         vmw_write(dev_priv,SVGA_REG_BITS_PER_PIXEL, 32);
  709.         os_display->select_cursor(os_display->cursor);
  710.         ret = 0;
  711. #endif
  712.         if (ret == 0)
  713.         {
  714.             os_display->width    = mode->hdisplay;
  715.             os_display->height   = mode->vdisplay;
  716.             os_display->pitch    = mode->hdisplay*4;
  717.             os_display->vrefresh = drm_mode_vrefresh(mode);
  718.  
  719.             sysSetScreen(os_display->width, os_display->height, os_display->pitch);
  720.  
  721.             dbgprintf("new mode %d x %d pitch %d\n",
  722.                        os_display->width, os_display->height, os_display->pitch);
  723.         }
  724.         else
  725.             DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  726.                        os_display->width, os_display->height, crtc);
  727.     }
  728.  
  729.     return ret;
  730. };
  731.