Subversion Repositories Kolibri OS

Rev

Rev 4111 | Rev 5078 | 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. 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.     ENTER();
  120.  
  121.         fifo_size = sizeof(*cmd);
  122.         cmd = vmw_fifo_reserve(dev_priv, fifo_size);
  123.         /* The hardware has hung, nothing we can do about it here. */
  124.         if (unlikely(cmd == NULL)) {
  125.                 DRM_ERROR("Fifo reserve failed.\n");
  126.                 return -ENOMEM;
  127.         }
  128.  
  129.         memset(cmd, 0, fifo_size);
  130.         cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
  131.         cmd->obj.structSize = sizeof(SVGAScreenObject);
  132.         cmd->obj.id = sou->base.unit;
  133.         cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
  134.                 (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
  135.         cmd->obj.size.width = mode->hdisplay;
  136.         cmd->obj.size.height = mode->vdisplay;
  137.         if (sou->base.is_implicit) {
  138.                 cmd->obj.root.x = x;
  139.                 cmd->obj.root.y = y;
  140.         } else {
  141.                 cmd->obj.root.x = sou->base.gui_x;
  142.                 cmd->obj.root.y = sou->base.gui_y;
  143.         }
  144.  
  145.         /* Ok to assume that buffer is pinned in vram */
  146. //   vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
  147.  
  148.     cmd->obj.backingStore.ptr.gmrId = SVGA_GMR_FRAMEBUFFER;
  149.     cmd->obj.backingStore.ptr.offset = 0;
  150.         cmd->obj.backingStore.pitch = mode->hdisplay * 4;
  151.  
  152.         vmw_fifo_commit(dev_priv, fifo_size);
  153.  
  154.         sou->defined = true;
  155.  
  156.     LEAVE();
  157.  
  158.         return 0;
  159. }
  160.  
  161. /**
  162.  * Send the fifo command to destroy a screen.
  163.  */
  164. static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
  165.                                 struct vmw_screen_object_unit *sou)
  166. {
  167.         size_t fifo_size;
  168.         int ret;
  169.  
  170.         struct {
  171.                 struct {
  172.                         uint32_t cmdType;
  173.                 } header;
  174.                 SVGAFifoCmdDestroyScreen body;
  175.         } *cmd;
  176.  
  177.         /* no need to do anything */
  178.         if (unlikely(!sou->defined))
  179.                 return 0;
  180.  
  181.         fifo_size = sizeof(*cmd);
  182.         cmd = vmw_fifo_reserve(dev_priv, fifo_size);
  183.         /* the hardware has hung, nothing we can do about it here */
  184.         if (unlikely(cmd == NULL)) {
  185.                 DRM_ERROR("Fifo reserve failed.\n");
  186.                 return -ENOMEM;
  187.         }
  188.  
  189.         memset(cmd, 0, fifo_size);
  190.         cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
  191.         cmd->body.screenId = sou->base.unit;
  192.  
  193.         vmw_fifo_commit(dev_priv, fifo_size);
  194.  
  195.         /* Force sync */
  196.         ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
  197.         if (unlikely(ret != 0))
  198.                 DRM_ERROR("Failed to sync with HW");
  199.         else
  200.                 sou->defined = false;
  201.  
  202.         return ret;
  203. }
  204.  
  205. /**
  206.  * Free the backing store.
  207.  */
  208. static void vmw_sou_backing_free(struct vmw_private *dev_priv,
  209.                                  struct vmw_screen_object_unit *sou)
  210. {
  211.         struct ttm_buffer_object *bo;
  212.  
  213.         if (unlikely(sou->buffer == NULL))
  214.                 return;
  215.  
  216.         bo = &sou->buffer->base;
  217.         ttm_bo_unref(&bo);
  218.         sou->buffer = NULL;
  219.         sou->buffer_size = 0;
  220. }
  221.  
  222. /**
  223.  * Allocate the backing store for the buffer.
  224.  */
  225. static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
  226.                                  struct vmw_screen_object_unit *sou,
  227.                                  unsigned long size)
  228. {
  229.         int ret;
  230.  
  231.         if (sou->buffer_size == size)
  232.                 return 0;
  233.  
  234.         if (sou->buffer)
  235.                 vmw_sou_backing_free(dev_priv, sou);
  236.  
  237.         sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
  238.         if (unlikely(sou->buffer == NULL))
  239.                 return -ENOMEM;
  240.  
  241.         /* After we have alloced the backing store might not be able to
  242.          * resume the overlays, this is preferred to failing to alloc.
  243.          */
  244. //    vmw_overlay_pause_all(dev_priv);
  245.         ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
  246.                               &vmw_vram_ne_placement,
  247.                               false, &vmw_dmabuf_bo_free);
  248. //   vmw_overlay_resume_all(dev_priv);
  249.  
  250.         if (unlikely(ret != 0))
  251.                 sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
  252.         else
  253.                 sou->buffer_size = size;
  254.  
  255.         return ret;
  256. }
  257.  
  258. static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
  259. {
  260.         struct vmw_private *dev_priv;
  261.         struct vmw_screen_object_unit *sou;
  262.         struct drm_connector *connector;
  263.         struct drm_display_mode *mode;
  264.         struct drm_encoder *encoder;
  265.         struct vmw_framebuffer *vfb;
  266.         struct drm_framebuffer *fb;
  267.         struct drm_crtc *crtc;
  268.         int ret = 0;
  269.  
  270.         if (!set)
  271.                 return -EINVAL;
  272.  
  273.         if (!set->crtc)
  274.                 return -EINVAL;
  275.  
  276.         /* get the sou */
  277.         crtc = set->crtc;
  278.         sou = vmw_crtc_to_sou(crtc);
  279.         vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
  280.         dev_priv = vmw_priv(crtc->dev);
  281.  
  282.         if (set->num_connectors > 1) {
  283.                 DRM_ERROR("to many connectors\n");
  284.                 return -EINVAL;
  285.         }
  286.  
  287.         if (set->num_connectors == 1 &&
  288.             set->connectors[0] != &sou->base.connector) {
  289.                 DRM_ERROR("connector doesn't match %p %p\n",
  290.                         set->connectors[0], &sou->base.connector);
  291.                 return -EINVAL;
  292.         }
  293.  
  294.         /* sou only supports one fb active at the time */
  295.         if (sou->base.is_implicit &&
  296.             dev_priv->sou_priv->implicit_fb && vfb &&
  297.             !(dev_priv->sou_priv->num_implicit == 1 &&
  298.               sou->active_implicit) &&
  299.             dev_priv->sou_priv->implicit_fb != vfb) {
  300.                 DRM_ERROR("Multiple framebuffers not supported\n");
  301.                 return -EINVAL;
  302.         }
  303.  
  304.         /* since they always map one to one these are safe */
  305.         connector = &sou->base.connector;
  306.         encoder = &sou->base.encoder;
  307.  
  308.         /* should we turn the crtc off */
  309.         if (set->num_connectors == 0 || !set->mode || !set->fb) {
  310.                 ret = vmw_sou_fifo_destroy(dev_priv, sou);
  311.                 /* the hardware has hung don't do anything more */
  312.                 if (unlikely(ret != 0))
  313.                         return ret;
  314.  
  315.                 connector->encoder = NULL;
  316.                 encoder->crtc = NULL;
  317.                 crtc->fb = NULL;
  318.                 crtc->x = 0;
  319.                 crtc->y = 0;
  320.                 crtc->enabled = false;
  321.  
  322.                 vmw_sou_del_active(dev_priv, sou);
  323.  
  324.                 vmw_sou_backing_free(dev_priv, sou);
  325.  
  326.                 return 0;
  327.         }
  328.  
  329.  
  330.         /* we now know we want to set a mode */
  331.         mode = set->mode;
  332.         fb = set->fb;
  333.  
  334.         if (set->x + mode->hdisplay > fb->width ||
  335.             set->y + mode->vdisplay > fb->height) {
  336.                 DRM_ERROR("set outside of framebuffer\n");
  337.                 return -EINVAL;
  338.         }
  339.  
  340. //   vmw_fb_off(dev_priv);
  341.  
  342.         if (mode->hdisplay != crtc->mode.hdisplay ||
  343.             mode->vdisplay != crtc->mode.vdisplay) {
  344.                 /* no need to check if depth is different, because backing
  345.                  * store depth is forced to 4 by the device.
  346.                  */
  347.  
  348.                 ret = vmw_sou_fifo_destroy(dev_priv, sou);
  349.                 /* the hardware has hung don't do anything more */
  350.                 if (unlikely(ret != 0))
  351.                         return ret;
  352.  
  353.                 vmw_sou_backing_free(dev_priv, sou);
  354.         }
  355.  
  356.         if (!sou->buffer) {
  357.                 /* forced to depth 4 by the device */
  358.                 size_t size = mode->hdisplay * mode->vdisplay * 4;
  359.                 ret = vmw_sou_backing_alloc(dev_priv, sou, size);
  360.                 if (unlikely(ret != 0))
  361.                         return ret;
  362.         }
  363.  
  364.         ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
  365.         if (unlikely(ret != 0)) {
  366.                 /*
  367.                  * We are in a bit of a situation here, the hardware has
  368.                  * hung and we may or may not have a buffer hanging of
  369.                  * the screen object, best thing to do is not do anything
  370.                  * if we where defined, if not just turn the crtc of.
  371.                  * Not what userspace wants but it needs to htfu.
  372.                  */
  373.                 if (sou->defined)
  374.                         return ret;
  375.  
  376.                 connector->encoder = NULL;
  377.                 encoder->crtc = NULL;
  378.                 crtc->fb = NULL;
  379.                 crtc->x = 0;
  380.                 crtc->y = 0;
  381.                 crtc->enabled = false;
  382.  
  383.                 return ret;
  384.         }
  385.  
  386.         vmw_sou_add_active(dev_priv, sou, vfb);
  387.  
  388.         connector->encoder = encoder;
  389.         encoder->crtc = crtc;
  390.         crtc->mode = *mode;
  391.         crtc->fb = fb;
  392.         crtc->x = set->x;
  393.         crtc->y = set->y;
  394.         crtc->enabled = true;
  395.  
  396.         return 0;
  397. }
  398.  
  399. static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
  400.         .save = vmw_du_crtc_save,
  401.         .restore = vmw_du_crtc_restore,
  402. //   .cursor_set = vmw_du_crtc_cursor_set,
  403. //   .cursor_move = vmw_du_crtc_cursor_move,
  404.         .gamma_set = vmw_du_crtc_gamma_set,
  405.         .destroy = vmw_sou_crtc_destroy,
  406.         .set_config = vmw_sou_crtc_set_config,
  407. //   .page_flip = vmw_du_page_flip,
  408. };
  409.  
  410. /*
  411.  * Screen Object Display Unit encoder functions
  412.  */
  413.  
  414. static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
  415. {
  416.         vmw_sou_destroy(vmw_encoder_to_sou(encoder));
  417. }
  418.  
  419. static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
  420.         .destroy = vmw_sou_encoder_destroy,
  421. };
  422.  
  423. /*
  424.  * Screen Object Display Unit connector functions
  425.  */
  426.  
  427. static void vmw_sou_connector_destroy(struct drm_connector *connector)
  428. {
  429.         vmw_sou_destroy(vmw_connector_to_sou(connector));
  430. }
  431.  
  432. static struct drm_connector_funcs vmw_legacy_connector_funcs = {
  433.         .dpms = vmw_du_connector_dpms,
  434.         .save = vmw_du_connector_save,
  435.         .restore = vmw_du_connector_restore,
  436.         .detect = vmw_du_connector_detect,
  437.         .fill_modes = vmw_du_connector_fill_modes,
  438.         .set_property = vmw_du_connector_set_property,
  439.         .destroy = vmw_sou_connector_destroy,
  440. };
  441.  
  442. static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
  443. {
  444.         struct vmw_screen_object_unit *sou;
  445.         struct drm_device *dev = dev_priv->dev;
  446.         struct drm_connector *connector;
  447.         struct drm_encoder *encoder;
  448.         struct drm_crtc *crtc;
  449.  
  450.     ENTER();
  451.  
  452.         sou = kzalloc(sizeof(*sou), GFP_KERNEL);
  453.         if (!sou)
  454.                 return -ENOMEM;
  455.  
  456.         sou->base.unit = unit;
  457.         crtc = &sou->base.crtc;
  458.         encoder = &sou->base.encoder;
  459.         connector = &sou->base.connector;
  460.  
  461.         sou->active_implicit = false;
  462.  
  463.         sou->base.pref_active = (unit == 0);
  464.         sou->base.pref_width = dev_priv->initial_width;
  465.         sou->base.pref_height = dev_priv->initial_height;
  466.         sou->base.pref_mode = NULL;
  467.         sou->base.is_implicit = true;
  468.  
  469.         drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
  470.                            DRM_MODE_CONNECTOR_VIRTUAL);
  471.         connector->status = vmw_du_connector_detect(connector, true);
  472.  
  473.         drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
  474.                          DRM_MODE_ENCODER_VIRTUAL);
  475.         drm_mode_connector_attach_encoder(connector, encoder);
  476.         encoder->possible_crtcs = (1 << unit);
  477.         encoder->possible_clones = 0;
  478.  
  479.         drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
  480.  
  481.         drm_mode_crtc_set_gamma_size(crtc, 256);
  482.  
  483.         drm_object_attach_property(&connector->base,
  484.                                       dev->mode_config.dirty_info_property,
  485.                                       1);
  486.     LEAVE();
  487.         return 0;
  488. }
  489.  
  490. int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
  491. {
  492.         struct drm_device *dev = dev_priv->dev;
  493.         int i, ret;
  494.  
  495.     ENTER();
  496.  
  497.         if (dev_priv->sou_priv) {
  498.                 DRM_INFO("sou system already on\n");
  499.                 return -EINVAL;
  500.         }
  501.  
  502.         if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
  503.                 DRM_INFO("Not using screen objects,"
  504.                          " missing cap SCREEN_OBJECT_2\n");
  505.                 return -ENOSYS;
  506.         }
  507.  
  508.         ret = -ENOMEM;
  509.         dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
  510.         if (unlikely(!dev_priv->sou_priv))
  511.                 goto err_no_mem;
  512.  
  513.         dev_priv->sou_priv->num_implicit = 0;
  514.         dev_priv->sou_priv->implicit_fb = NULL;
  515.  
  516.  
  517.         ret = drm_mode_create_dirty_info_property(dev);
  518.         if (unlikely(ret != 0))
  519.                 goto err_vblank_cleanup;
  520.  
  521.         for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
  522.                 vmw_sou_init(dev_priv, i);
  523.  
  524.         DRM_INFO("Screen objects system initialized\n");
  525.  
  526.     LEAVE();
  527.         return 0;
  528.  
  529. err_vblank_cleanup:
  530. //   drm_vblank_cleanup(dev);
  531. err_free:
  532.         kfree(dev_priv->sou_priv);
  533.         dev_priv->sou_priv = NULL;
  534. err_no_mem:
  535.         return ret;
  536. }
  537.  
  538. int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
  539. {
  540.         struct drm_device *dev = dev_priv->dev;
  541.  
  542.         if (!dev_priv->sou_priv)
  543.                 return -ENOSYS;
  544.  
  545. //   drm_vblank_cleanup(dev);
  546.  
  547.         kfree(dev_priv->sou_priv);
  548.  
  549.         return 0;
  550. }
  551.  
  552. /**
  553.  * Returns if this unit can be page flipped.
  554.  * Must be called with the mode_config mutex held.
  555.  */
  556. bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv,
  557.                                      struct drm_crtc *crtc)
  558. {
  559.         struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
  560.  
  561.         if (!sou->base.is_implicit)
  562.                 return true;
  563.  
  564.         if (dev_priv->sou_priv->num_implicit != 1)
  565.                 return false;
  566.  
  567.         return true;
  568. }
  569.  
  570. /**
  571.  * Update the implicit fb to the current fb of this crtc.
  572.  * Must be called with the mode_config mutex held.
  573.  */
  574. void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
  575.                                               struct drm_crtc *crtc)
  576. {
  577.         struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
  578.  
  579.         BUG_ON(!sou->base.is_implicit);
  580.  
  581.         dev_priv->sou_priv->implicit_fb =
  582.                 vmw_framebuffer_to_vfb(sou->base.crtc.fb);
  583. }
  584.  
  585. #include "bitmap.h"
  586.  
  587. typedef struct
  588. {
  589.     kobj_t     header;
  590.  
  591.     uint32_t  *data;
  592.     uint32_t   hot_x;
  593.     uint32_t   hot_y;
  594.  
  595.     struct list_head   list;
  596. //    struct drm_i915_gem_object  *cobj;
  597. }cursor_t;
  598.  
  599.  
  600. struct tag_display
  601. {
  602.     int  x;
  603.     int  y;
  604.     int  width;
  605.     int  height;
  606.     int  bpp;
  607.     int  vrefresh;
  608.     int  pitch;
  609.     int  lfb;
  610.  
  611.     int  supported_modes;
  612.     struct drm_device    *ddev;
  613.     struct drm_connector *connector;
  614.     struct drm_crtc      *crtc;
  615.  
  616.     struct list_head   cursors;
  617.  
  618.     cursor_t   *cursor;
  619.     int       (*init_cursor)(cursor_t*);
  620.     cursor_t* (__stdcall *select_cursor)(cursor_t*);
  621.     void      (*show_cursor)(int show);
  622.     void      (__stdcall *move_cursor)(cursor_t *cursor, int x, int y);
  623.     void      (__stdcall *restore_cursor)(int x, int y);
  624.     void      (*disable_mouse)(void);
  625.     u32  mask_seqno;
  626.     u32  check_mouse;
  627.     u32  check_m_pixel;
  628.     u32  dirty;
  629.     void (*update)(void);
  630. };
  631.  
  632. bool set_mode(struct drm_device *dev, struct drm_connector *connector,
  633.               videomode_t *reqmode, bool strict)
  634. {
  635.     struct drm_display_mode  *mode = NULL, *tmpmode;
  636.     struct vmw_private *dev_priv = vmw_priv(dev);
  637.     struct vmw_screen_object_unit *sou;
  638.     display_t *os_display;
  639.  
  640.     bool ret = false;
  641.  
  642.     ENTER();
  643.  
  644. //    dbgprintf("width %d height %d vrefresh %d\n",
  645. //               reqmode->width, reqmode->height, reqmode->freq);
  646.  
  647.     list_for_each_entry(tmpmode, &connector->modes, head)
  648.     {
  649.         if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
  650.             (drm_mode_height(tmpmode)   == reqmode->height) &&
  651.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  652.         {
  653.             mode = tmpmode;
  654.             goto do_set;
  655.         }
  656.     };
  657.  
  658.     if( (mode == NULL) && (strict == false) )
  659.     {
  660.         list_for_each_entry(tmpmode, &connector->modes, head)
  661.         {
  662.             if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
  663.                 (drm_mode_height(tmpmode) == reqmode->height) )
  664.             {
  665.                 mode = tmpmode;
  666.                 goto do_set;
  667.             }
  668.         };
  669.     };
  670.  
  671. do_set:
  672.  
  673.     if( mode != NULL )
  674.     {
  675.         struct drm_framebuffer   *fb;
  676.         struct drm_encoder       *encoder;
  677.         struct drm_crtc          *crtc;
  678.  
  679. //        char  con_edid[128];
  680.         const char *con_name;
  681.         const char *enc_name;
  682.  
  683.         encoder = connector->encoder;
  684.         crtc = encoder->crtc;
  685.  
  686.  
  687. //        fb = list_first_entry(&dev->mode_config.fb_kernel_list,
  688. //                              struct drm_framebuffer, filp_head);
  689.  
  690. //        memcpy(con_edid, connector->edid_blob_ptr->data, 128);
  691.  
  692. //        dbgprintf("Manufacturer: %s Model %x Serial Number %u\n",
  693. //        manufacturer_name(con_edid + 0x08),
  694. //        (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
  695. //        (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
  696. //            + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
  697.  
  698.         con_name = drm_get_connector_name(connector);
  699.         enc_name = drm_get_encoder_name(encoder);
  700.  
  701.         dbgprintf("set mode %d %d connector %s encoder %s\n",
  702.                    mode->hdisplay, mode->vdisplay, con_name, enc_name);
  703.  
  704.         os_display = GetDisplay();
  705.  
  706. #if 0
  707.         sou = vmw_crtc_to_sou(crtc);
  708.         sou->defined = true;
  709.  
  710.         ret = vmw_sou_fifo_destroy(dev_priv, sou);
  711.         if (unlikely(ret != 0))
  712.             return ret;
  713.  
  714.         ret = vmw_sou_fifo_create(dev_priv, sou, 0, 0, mode);
  715.  
  716. #else   /*   sledgehammer  */
  717.  
  718.         vmw_write(dev_priv,SVGA_REG_WIDTH,  mode->hdisplay);
  719.         vmw_write(dev_priv,SVGA_REG_HEIGHT, mode->vdisplay);
  720.         vmw_write(dev_priv,SVGA_REG_BITS_PER_PIXEL, 32);
  721.         ret = 0;
  722. #endif
  723.         if (ret == 0)
  724.         {
  725.             os_display->width    = mode->hdisplay;
  726.             os_display->height   = mode->vdisplay;
  727.             os_display->pitch    = mode->hdisplay*4;
  728.             os_display->vrefresh = drm_mode_vrefresh(mode);
  729.  
  730.             sysSetScreen(os_display->width, os_display->height, os_display->pitch);
  731.  
  732.             dbgprintf("new mode %d x %d pitch %d\n",
  733.                        os_display->width, os_display->height, os_display->pitch);
  734.         }
  735.         else
  736.             DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  737.                        os_display->width, os_display->height, crtc);
  738.     }
  739.  
  740.     LEAVE();
  741.     return ret;
  742. };
  743.