Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * COPYRIGHT © 2014-2015 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. #include "device_include/svga3d_surfacedefs.h"
  30. #include <drm/drm_plane_helper.h>
  31.  
  32. #define vmw_crtc_to_stdu(x) \
  33.         container_of(x, struct vmw_screen_target_display_unit, base.crtc)
  34. #define vmw_encoder_to_stdu(x) \
  35.         container_of(x, struct vmw_screen_target_display_unit, base.encoder)
  36. #define vmw_connector_to_stdu(x) \
  37.         container_of(x, struct vmw_screen_target_display_unit, base.connector)
  38.  
  39.  
  40.  
  41. enum stdu_content_type {
  42.         SAME_AS_DISPLAY = 0,
  43.         SEPARATE_SURFACE,
  44.         SEPARATE_DMA
  45. };
  46.  
  47. /**
  48.  * struct vmw_stdu_dirty - closure structure for the update functions
  49.  *
  50.  * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
  51.  * @transfer: Transfer direction for DMA command.
  52.  * @left: Left side of bounding box.
  53.  * @right: Right side of bounding box.
  54.  * @top: Top side of bounding box.
  55.  * @bottom: Bottom side of bounding box.
  56.  * @buf: DMA buffer when DMA-ing between buffer and screen targets.
  57.  * @sid: Surface ID when copying between surface and screen targets.
  58.  */
  59. struct vmw_stdu_dirty {
  60.         struct vmw_kms_dirty base;
  61.         SVGA3dTransferType  transfer;
  62.         s32 left, right, top, bottom;
  63.         u32 pitch;
  64.         union {
  65.                 struct vmw_dma_buffer *buf;
  66.                 u32 sid;
  67.         };
  68. };
  69.  
  70. /*
  71.  * SVGA commands that are used by this code. Please see the device headers
  72.  * for explanation.
  73.  */
  74. struct vmw_stdu_update {
  75.         SVGA3dCmdHeader header;
  76.         SVGA3dCmdUpdateGBScreenTarget body;
  77. };
  78.  
  79. struct vmw_stdu_dma {
  80.         SVGA3dCmdHeader     header;
  81.         SVGA3dCmdSurfaceDMA body;
  82. };
  83.  
  84. struct vmw_stdu_surface_copy {
  85.         SVGA3dCmdHeader      header;
  86.         SVGA3dCmdSurfaceCopy body;
  87. };
  88.  
  89.  
  90. /**
  91.  * struct vmw_screen_target_display_unit
  92.  *
  93.  * @base: VMW specific DU structure
  94.  * @display_srf: surface to be displayed.  The dimension of this will always
  95.  *               match the display mode.  If the display mode matches
  96.  *               content_vfbs dimensions, then this is a pointer into the
  97.  *               corresponding field in content_vfbs.  If not, then this
  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
  101.  * @defined:  true if the current display unit has been initialized
  102.  */
  103. struct vmw_screen_target_display_unit {
  104.         struct vmw_display_unit base;
  105.  
  106.         struct vmw_surface     *display_srf;
  107.         struct drm_framebuffer *content_fb;
  108.  
  109.         enum stdu_content_type content_fb_type;
  110.  
  111.         bool defined;
  112. };
  113.  
  114.  
  115.  
  116. static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu);
  117.  
  118.  
  119.  
  120. /******************************************************************************
  121.  * Screen Target Display Unit helper Functions
  122.  *****************************************************************************/
  123.  
  124. /**
  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.  */
  133. static 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
  142.  *
  143.  * @stdu: contains the display surface
  144.  *
  145.  * If the display surface was privatedly allocated by
  146.  * vmw_surface_gb_priv_define() and not registered as a framebuffer, then it
  147.  * won't be automatically cleaned up when all the framebuffers are freed.  As
  148.  * such, we have to explicitly call vmw_resource_unreference() to get it freed.
  149.  */
  150. static void vmw_stdu_unpin_display(struct vmw_screen_target_display_unit *stdu)
  151. {
  152.         if (stdu->display_srf) {
  153.                 struct vmw_resource *res = &stdu->display_srf->res;
  154.  
  155.                 vmw_resource_unpin(res);
  156.  
  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.         }
  164. }
  165.  
  166.  
  167.  
  168. /******************************************************************************
  169.  * Screen Target Display Unit CRTC Functions
  170.  *****************************************************************************/
  171.  
  172.  
  173. /**
  174.  * vmw_stdu_crtc_destroy - cleans up the STDU
  175.  *
  176.  * @crtc: used to get a reference to the containing STDU
  177.  */
  178. static void vmw_stdu_crtc_destroy(struct drm_crtc *crtc)
  179. {
  180.         vmw_stdu_destroy(vmw_crtc_to_stdu(crtc));
  181. }
  182.  
  183. /**
  184.  * vmw_stdu_define_st - Defines a Screen Target
  185.  *
  186.  * @dev_priv:  VMW DRM device
  187.  * @stdu: display unit to create a Screen Target for
  188.  *
  189.  * Creates a STDU that we can used later.  This function is called whenever the
  190.  * framebuffer size changes.
  191.  *
  192.  * RETURNs:
  193.  * 0 on success, error code on failure
  194.  */
  195. static int vmw_stdu_define_st(struct vmw_private *dev_priv,
  196.                               struct vmw_screen_target_display_unit *stdu)
  197. {
  198.         struct {
  199.                 SVGA3dCmdHeader header;
  200.                 SVGA3dCmdDefineGBScreenTarget body;
  201.         } *cmd;
  202.  
  203.         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
  204.  
  205.         if (unlikely(cmd == NULL)) {
  206.                 DRM_ERROR("Out of FIFO space defining Screen Target\n");
  207.                 return -ENOMEM;
  208.         }
  209.  
  210.         cmd->header.id   = SVGA_3D_CMD_DEFINE_GB_SCREENTARGET;
  211.         cmd->header.size = sizeof(cmd->body);
  212.  
  213.         cmd->body.stid   = stdu->base.unit;
  214.         cmd->body.width  = stdu->display_srf->base_size.width;
  215.         cmd->body.height = stdu->display_srf->base_size.height;
  216.         cmd->body.flags  = (0 == cmd->body.stid) ? SVGA_STFLAG_PRIMARY : 0;
  217.         cmd->body.dpi    = 0;
  218.         cmd->body.xRoot  = stdu->base.crtc.x;
  219.         cmd->body.yRoot  = stdu->base.crtc.y;
  220.  
  221.         if (!stdu->base.is_implicit) {
  222.                 cmd->body.xRoot  = stdu->base.gui_x;
  223.                 cmd->body.yRoot  = stdu->base.gui_y;
  224.         }
  225.  
  226.         vmw_fifo_commit(dev_priv, sizeof(*cmd));
  227.  
  228.         stdu->defined = true;
  229.  
  230.         return 0;
  231. }
  232.  
  233.  
  234.  
  235. /**
  236.  * vmw_stdu_bind_st - Binds a surface to a Screen Target
  237.  *
  238.  * @dev_priv: VMW DRM device
  239.  * @stdu: display unit affected
  240.  * @res: Buffer to bind to the screen target.  Set to NULL to blank screen.
  241.  *
  242.  * Binding a surface to a Screen Target the same as flipping
  243.  */
  244. static int vmw_stdu_bind_st(struct vmw_private *dev_priv,
  245.                             struct vmw_screen_target_display_unit *stdu,
  246.                             struct vmw_resource *res)
  247. {
  248.         SVGA3dSurfaceImageId image;
  249.  
  250.         struct {
  251.                 SVGA3dCmdHeader header;
  252.                 SVGA3dCmdBindGBScreenTarget body;
  253.         } *cmd;
  254.  
  255.  
  256.         if (!stdu->defined) {
  257.                 DRM_ERROR("No screen target defined\n");
  258.                 return -EINVAL;
  259.         }
  260.  
  261.         /* Set up image using information in vfb */
  262.         memset(&image, 0, sizeof(image));
  263.         image.sid = res ? res->id : SVGA3D_INVALID_ID;
  264.  
  265.         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
  266.  
  267.         if (unlikely(cmd == NULL)) {
  268.                 DRM_ERROR("Out of FIFO space binding a screen target\n");
  269.                 return -ENOMEM;
  270.         }
  271.  
  272.         cmd->header.id   = SVGA_3D_CMD_BIND_GB_SCREENTARGET;
  273.         cmd->header.size = sizeof(cmd->body);
  274.  
  275.         cmd->body.stid   = stdu->base.unit;
  276.         cmd->body.image  = image;
  277.  
  278.         vmw_fifo_commit(dev_priv, sizeof(*cmd));
  279.  
  280.         return 0;
  281. }
  282.  
  283. /**
  284.  * vmw_stdu_populate_update - populate an UPDATE_GB_SCREENTARGET command with a
  285.  * bounding box.
  286.  *
  287.  * @cmd: Pointer to command stream.
  288.  * @unit: Screen target unit.
  289.  * @left: Left side of bounding box.
  290.  * @right: Right side of bounding box.
  291.  * @top: Top side of bounding box.
  292.  * @bottom: Bottom side of bounding box.
  293.  */
  294. static void vmw_stdu_populate_update(void *cmd, int unit,
  295.                                      s32 left, s32 right, s32 top, s32 bottom)
  296. {
  297.         struct vmw_stdu_update *update = cmd;
  298.  
  299.         update->header.id   = SVGA_3D_CMD_UPDATE_GB_SCREENTARGET;
  300.         update->header.size = sizeof(update->body);
  301.  
  302.         update->body.stid   = unit;
  303.         update->body.rect.x = left;
  304.         update->body.rect.y = top;
  305.         update->body.rect.w = right - left;
  306.         update->body.rect.h = bottom - top;
  307. }
  308.  
  309. /**
  310.  * vmw_stdu_update_st - Full update of a Screen Target
  311.  *
  312.  * @dev_priv: VMW DRM device
  313.  * @stdu: display unit affected
  314.  *
  315.  * This function needs to be called whenever the content of a screen
  316.  * target has changed completely. Typically as a result of a backing
  317.  * surface change.
  318.  *
  319.  * RETURNS:
  320.  * 0 on success, error code on failure
  321.  */
  322. static int vmw_stdu_update_st(struct vmw_private *dev_priv,
  323.                               struct vmw_screen_target_display_unit *stdu)
  324. {
  325.         struct vmw_stdu_update *cmd;
  326.         struct drm_crtc *crtc = &stdu->base.crtc;
  327.  
  328.         if (!stdu->defined) {
  329.                 DRM_ERROR("No screen target defined");
  330.                 return -EINVAL;
  331.         }
  332.  
  333.         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
  334.  
  335.         if (unlikely(cmd == NULL)) {
  336.                 DRM_ERROR("Out of FIFO space updating a Screen Target\n");
  337.                 return -ENOMEM;
  338.         }
  339.  
  340.         vmw_stdu_populate_update(cmd, stdu->base.unit, 0, crtc->mode.hdisplay,
  341.                                  0, crtc->mode.vdisplay);
  342.  
  343.         vmw_fifo_commit(dev_priv, sizeof(*cmd));
  344.  
  345.         return 0;
  346. }
  347.  
  348.  
  349.  
  350. /**
  351.  * vmw_stdu_destroy_st - Destroy a Screen Target
  352.  *
  353.  * @dev_priv:  VMW DRM device
  354.  * @stdu: display unit to destroy
  355.  */
  356. static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
  357.                                struct vmw_screen_target_display_unit *stdu)
  358. {
  359.         int    ret;
  360.  
  361.         struct {
  362.                 SVGA3dCmdHeader header;
  363.                 SVGA3dCmdDestroyGBScreenTarget body;
  364.         } *cmd;
  365.  
  366.  
  367.         /* Nothing to do if not successfully defined */
  368.         if (unlikely(!stdu->defined))
  369.                 return 0;
  370.  
  371.         cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
  372.  
  373.         if (unlikely(cmd == NULL)) {
  374.                 DRM_ERROR("Out of FIFO space, screen target not destroyed\n");
  375.                 return -ENOMEM;
  376.         }
  377.  
  378.         cmd->header.id   = SVGA_3D_CMD_DESTROY_GB_SCREENTARGET;
  379.         cmd->header.size = sizeof(cmd->body);
  380.  
  381.         cmd->body.stid   = stdu->base.unit;
  382.  
  383.         vmw_fifo_commit(dev_priv, sizeof(*cmd));
  384.  
  385.         /* Force sync */
  386.         ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
  387.         if (unlikely(ret != 0))
  388.                 DRM_ERROR("Failed to sync with HW");
  389.  
  390.         stdu->defined = false;
  391.  
  392.         return ret;
  393. }
  394.  
  395.  
  396.  
  397. /**
  398.  * vmw_stdu_crtc_set_config - Sets a mode
  399.  *
  400.  * @set:  mode parameters
  401.  *
  402.  * This function is the device-specific portion of the DRM CRTC mode set.
  403.  * For the SVGA device, we do this by defining a Screen Target, binding a
  404.  * GB Surface to that target, and finally update the screen target.
  405.  *
  406.  * RETURNS:
  407.  * 0 on success, error code otherwise
  408.  */
  409. static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
  410. {
  411.         struct vmw_private *dev_priv;
  412.         struct vmw_screen_target_display_unit *stdu;
  413.         struct vmw_framebuffer *vfb;
  414.         struct vmw_framebuffer_surface *new_vfbs;
  415.         struct drm_display_mode *mode;
  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.  
  497.         stdu->content_fb = new_fb;
  498.         vfb = vmw_framebuffer_to_vfb(stdu->content_fb);
  499.  
  500.         if (vfb->dmabuf)
  501.                 stdu->content_fb_type = SEPARATE_DMA;
  502.  
  503.         /*
  504.          * If the requested mode is different than the width and height
  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;
  512.                 struct drm_vmw_size display_base_size = {0};
  513.                 struct vmw_surface *display_srf;
  514.  
  515.  
  516.                 display_base_size.width  = mode->hdisplay;
  517.                 display_base_size.height = mode->vdisplay;
  518.                 display_base_size.depth  = 1;
  519.  
  520.                 /*
  521.                  * If content buffer is a DMA buf, then we have to construct
  522.                  * surface info
  523.                  */
  524.                 if (stdu->content_fb_type == SEPARATE_DMA) {
  525.  
  526.                         switch (new_fb->bits_per_pixel) {
  527.                         case 32:
  528.                                 content_srf.format = SVGA3D_X8R8G8B8;
  529.                                 break;
  530.  
  531.                         case 16:
  532.                                 content_srf.format = SVGA3D_R5G6B5;
  533.                                 break;
  534.  
  535.                         case 8:
  536.                                 content_srf.format = SVGA3D_P8;
  537.                                 break;
  538.  
  539.                         default:
  540.                                 DRM_ERROR("Invalid format\n");
  541.                                 ret = -EINVAL;
  542.                                 goto err_unref_content;
  543.                         }
  544.  
  545.                         content_srf.flags             = 0;
  546.                         content_srf.mip_levels[0]     = 1;
  547.                         content_srf.multisample_count = 0;
  548.                 } else {
  549.  
  550.                         stdu->content_fb_type = SEPARATE_SURFACE;
  551.  
  552.                         new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
  553.                         content_srf = *new_vfbs->surface;
  554.                 }
  555.  
  556.  
  557.                 ret = vmw_surface_gb_priv_define(crtc->dev,
  558.                                 0, /* because kernel visible only */
  559.                                 content_srf.flags,
  560.                                 content_srf.format,
  561.                                 true, /* a scanout buffer */
  562.                                 content_srf.mip_levels[0],
  563.                                 content_srf.multisample_count,
  564.                                 0,
  565.                                 display_base_size,
  566.                                 &display_srf);
  567.                 if (unlikely(ret != 0)) {
  568.                         DRM_ERROR("Cannot allocate a display FB.\n");
  569.                         goto err_unref_content;
  570.                 }
  571.  
  572.                 stdu->display_srf = display_srf;
  573.         } else {
  574.                 new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
  575.                 stdu->display_srf = new_vfbs->surface;
  576.         }
  577.  
  578.  
  579.         ret = vmw_stdu_pin_display(stdu);
  580.         if (unlikely(ret != 0)) {
  581.                 stdu->display_srf = NULL;
  582.                 goto err_unref_content;
  583.         }
  584.  
  585.         vmw_svga_enable(dev_priv);
  586.  
  587.         /*
  588.          * Steps to displaying a surface, assume surface is already
  589.          * bound:
  590.          *   1.  define a screen target
  591.          *   2.  bind a fb to the screen target
  592.          *   3.  update that screen target (this is done later by
  593.          *       vmw_kms_stdu_do_surface_dirty_or_present)
  594.          */
  595.         ret = vmw_stdu_define_st(dev_priv, stdu);
  596.         if (unlikely(ret != 0))
  597.                 goto err_unpin_display_and_content;
  598.  
  599.         ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
  600.         if (unlikely(ret != 0))
  601.                 goto err_unpin_destroy_st;
  602.  
  603.  
  604.         connector->encoder = encoder;
  605.         encoder->crtc      = crtc;
  606.  
  607.         crtc->mode    = *mode;
  608.         crtc->primary->fb = new_fb;
  609.         crtc->enabled = true;
  610.  
  611.         return ret;
  612.  
  613. err_unpin_destroy_st:
  614.         vmw_stdu_destroy_st(dev_priv, stdu);
  615. err_unpin_display_and_content:
  616.         vmw_stdu_unpin_display(stdu);
  617. err_unref_content:
  618.         stdu->content_fb = NULL;
  619.         return ret;
  620. }
  621.  
  622.  
  623.  
  624. /**
  625.  * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
  626.  *
  627.  * @crtc: CRTC to attach FB to
  628.  * @fb: FB to attach
  629.  * @event: Event to be posted. This event should've been alloced
  630.  *         using k[mz]alloc, and should've been completely initialized.
  631.  * @page_flip_flags: Input flags.
  632.  *
  633.  * If the STDU uses the same display and content buffers, i.e. a true flip,
  634.  * this function will replace the existing display buffer with the new content
  635.  * buffer.
  636.  *
  637.  * If the STDU uses different display and content buffers, i.e. a blit, then
  638.  * only the content buffer will be updated.
  639.  *
  640.  * RETURNS:
  641.  * 0 on success, error code on failure
  642.  */
  643. static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
  644.                                    struct drm_framebuffer *new_fb,
  645.                                    struct drm_pending_vblank_event *event,
  646.                                    uint32_t flags)
  647.  
  648. {
  649.         struct vmw_private *dev_priv = vmw_priv(crtc->dev);
  650.         struct vmw_screen_target_display_unit *stdu;
  651.         int ret;
  652.  
  653.         if (crtc == NULL)
  654.                 return -EINVAL;
  655.  
  656.         dev_priv          = vmw_priv(crtc->dev);
  657.         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.  
  686.  
  687.         if (stdu->content_fb_type == SAME_AS_DISPLAY) {
  688.                 stdu->display_srf = vmw_framebuffer_to_vfbs(new_fb)->surface;
  689.                 ret = vmw_stdu_pin_display(stdu);
  690.                 if (ret) {
  691.                         stdu->display_srf = NULL;
  692.                         goto err_out;
  693.                 }
  694.  
  695.                 /* Bind display surface */
  696.                 ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
  697.                 if (unlikely(ret != 0))
  698.                         goto err_unpin_display_and_content;
  699.         }
  700.  
  701.         /* Update display surface: after this point everything is bound */
  702.         ret = vmw_stdu_update_st(dev_priv, stdu);
  703.         if (unlikely(ret != 0))
  704.                 return ret;
  705.  
  706.         if (event) {
  707.                 struct vmw_fence_obj *fence = NULL;
  708.                 struct drm_file *file_priv = event->base.file_priv;
  709.  
  710.                 vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
  711.                 if (!fence)
  712.                         return -ENOMEM;
  713.  
  714.                 ret = vmw_event_fence_action_queue(file_priv, fence,
  715.                                                    &event->base,
  716.                                                    &event->event.tv_sec,
  717.                                                    &event->event.tv_usec,
  718.                                                    true);
  719.                 vmw_fence_obj_unreference(&fence);
  720.         } else {
  721.                 vmw_fifo_flush(dev_priv, false);
  722.         }
  723.  
  724.         return ret;
  725.  
  726. err_unpin_display_and_content:
  727.         vmw_stdu_unpin_display(stdu);
  728. err_out:
  729.         crtc->primary->fb = NULL;
  730.         stdu->content_fb = NULL;
  731.         return ret;
  732. }
  733.  
  734.  
  735. /**
  736.  * vmw_stdu_dmabuf_clip - Callback to encode a suface DMA command cliprect
  737.  *
  738.  * @dirty: The closure structure.
  739.  *
  740.  * Encodes a surface DMA command cliprect and updates the bounding box
  741.  * for the DMA.
  742.  */
  743. static void vmw_stdu_dmabuf_clip(struct vmw_kms_dirty *dirty)
  744. {
  745.         struct vmw_stdu_dirty *ddirty =
  746.                 container_of(dirty, struct vmw_stdu_dirty, base);
  747.         struct vmw_stdu_dma *cmd = dirty->cmd;
  748.         struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  749.  
  750.         blit += dirty->num_hits;
  751.         blit->srcx = dirty->fb_x;
  752.         blit->srcy = dirty->fb_y;
  753.         blit->x = dirty->unit_x1;
  754.         blit->y = dirty->unit_y1;
  755.         blit->d = 1;
  756.         blit->w = dirty->unit_x2 - dirty->unit_x1;
  757.         blit->h = dirty->unit_y2 - dirty->unit_y1;
  758.         dirty->num_hits++;
  759.  
  760.         if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM)
  761.                 return;
  762.  
  763.         /* Destination bounding box */
  764.         ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
  765.         ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
  766.         ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
  767.         ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
  768. }
  769.  
  770. /**
  771.  * vmw_stdu_dmabuf_fifo_commit - Callback to fill in and submit a DMA command.
  772.  *
  773.  * @dirty: The closure structure.
  774.  *
  775.  * Fills in the missing fields in a DMA command, and optionally encodes
  776.  * a screen target update command, depending on transfer direction.
  777.  */
  778. static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
  779. {
  780.         struct vmw_stdu_dirty *ddirty =
  781.                 container_of(dirty, struct vmw_stdu_dirty, base);
  782.         struct vmw_screen_target_display_unit *stdu =
  783.                 container_of(dirty->unit, typeof(*stdu), base);
  784.         struct vmw_stdu_dma *cmd = dirty->cmd;
  785.         struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  786.         SVGA3dCmdSurfaceDMASuffix *suffix =
  787.                 (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits];
  788.         size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix);
  789.  
  790.         if (!dirty->num_hits) {
  791.                 vmw_fifo_commit(dirty->dev_priv, 0);
  792.                 return;
  793.         }
  794.  
  795.         cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
  796.         cmd->header.size = sizeof(cmd->body) + blit_size;
  797.         vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr);
  798.         cmd->body.guest.pitch = ddirty->pitch;
  799.         cmd->body.host.sid = stdu->display_srf->res.id;
  800.         cmd->body.host.face = 0;
  801.         cmd->body.host.mipmap = 0;
  802.         cmd->body.transfer = ddirty->transfer;
  803.         suffix->suffixSize = sizeof(*suffix);
  804.         suffix->maximumOffset = ddirty->buf->base.num_pages * PAGE_SIZE;
  805.  
  806.         if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) {
  807.                 blit_size += sizeof(struct vmw_stdu_update);
  808.  
  809.                 vmw_stdu_populate_update(&suffix[1], stdu->base.unit,
  810.                                          ddirty->left, ddirty->right,
  811.                                          ddirty->top, ddirty->bottom);
  812.         }
  813.  
  814.         vmw_fifo_commit(dirty->dev_priv, sizeof(*cmd) + blit_size);
  815.  
  816.         ddirty->left = ddirty->top = S32_MAX;
  817.         ddirty->right = ddirty->bottom = S32_MIN;
  818. }
  819.  
  820. /**
  821.  * vmw_kms_stdu_dma - Perform a DMA transfer between a dma-buffer backed
  822.  * framebuffer and the screen target system.
  823.  *
  824.  * @dev_priv: Pointer to the device private structure.
  825.  * @file_priv: Pointer to a struct drm-file identifying the caller. May be
  826.  * set to NULL, but then @user_fence_rep must also be set to NULL.
  827.  * @vfb: Pointer to the dma-buffer backed framebuffer.
  828.  * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
  829.  * @vclips: Alternate array of clip rects. Either @clips or @vclips must
  830.  * be NULL.
  831.  * @num_clips: Number of clip rects in @clips or @vclips.
  832.  * @increment: Increment to use when looping over @clips or @vclips.
  833.  * @to_surface: Whether to DMA to the screen target system as opposed to
  834.  * from the screen target system.
  835.  * @interruptible: Whether to perform waits interruptible if possible.
  836.  *
  837.  * If DMA-ing till the screen target system, the function will also notify
  838.  * the screen target system that a bounding box of the cliprects has been
  839.  * updated.
  840.  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  841.  * interrupted.
  842.  */
  843. int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
  844.                      struct drm_file *file_priv,
  845.                      struct vmw_framebuffer *vfb,
  846.                      struct drm_vmw_fence_rep __user *user_fence_rep,
  847.                      struct drm_clip_rect *clips,
  848.                      struct drm_vmw_rect *vclips,
  849.                      uint32_t num_clips,
  850.                      int increment,
  851.                      bool to_surface,
  852.                      bool interruptible)
  853. {
  854.         struct vmw_dma_buffer *buf =
  855.                 container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer;
  856.         struct vmw_stdu_dirty ddirty;
  857.         int ret;
  858.  
  859.         ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible,
  860.                                             false);
  861.         if (ret)
  862.                 return ret;
  863.  
  864.         ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM :
  865.                 SVGA3D_READ_HOST_VRAM;
  866.         ddirty.left = ddirty.top = S32_MAX;
  867.         ddirty.right = ddirty.bottom = S32_MIN;
  868.         ddirty.pitch = vfb->base.pitches[0];
  869.         ddirty.buf = buf;
  870.         ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit;
  871.         ddirty.base.clip = vmw_stdu_dmabuf_clip;
  872.         ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) +
  873.                 num_clips * sizeof(SVGA3dCopyBox) +
  874.                 sizeof(SVGA3dCmdSurfaceDMASuffix);
  875.         if (to_surface)
  876.                 ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update);
  877.  
  878.         ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips,
  879.                                    0, 0, num_clips, increment, &ddirty.base);
  880.         vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL,
  881.                                      user_fence_rep);
  882.  
  883.         return ret;
  884. }
  885.  
  886. /**
  887.  * vmw_stdu_surface_clip - Callback to encode a surface copy command cliprect
  888.  *
  889.  * @dirty: The closure structure.
  890.  *
  891.  * Encodes a surface copy command cliprect and updates the bounding box
  892.  * for the copy.
  893.  */
  894. static void vmw_kms_stdu_surface_clip(struct vmw_kms_dirty *dirty)
  895. {
  896.         struct vmw_stdu_dirty *sdirty =
  897.                 container_of(dirty, struct vmw_stdu_dirty, base);
  898.         struct vmw_stdu_surface_copy *cmd = dirty->cmd;
  899.         struct vmw_screen_target_display_unit *stdu =
  900.                 container_of(dirty->unit, typeof(*stdu), base);
  901.  
  902.         if (sdirty->sid != stdu->display_srf->res.id) {
  903.                 struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  904.  
  905.                 blit += dirty->num_hits;
  906.                 blit->srcx = dirty->fb_x;
  907.                 blit->srcy = dirty->fb_y;
  908.                 blit->x = dirty->unit_x1;
  909.                 blit->y = dirty->unit_y1;
  910.                 blit->d = 1;
  911.                 blit->w = dirty->unit_x2 - dirty->unit_x1;
  912.                 blit->h = dirty->unit_y2 - dirty->unit_y1;
  913.         }
  914.  
  915.         dirty->num_hits++;
  916.  
  917.         /* Destination bounding box */
  918.         sdirty->left = min_t(s32, sdirty->left, dirty->unit_x1);
  919.         sdirty->top = min_t(s32, sdirty->top, dirty->unit_y1);
  920.         sdirty->right = max_t(s32, sdirty->right, dirty->unit_x2);
  921.         sdirty->bottom = max_t(s32, sdirty->bottom, dirty->unit_y2);
  922. }
  923.  
  924. /**
  925.  * vmw_stdu_surface_fifo_commit - Callback to fill in and submit a surface
  926.  * copy command.
  927.  *
  928.  * @dirty: The closure structure.
  929.  *
  930.  * Fills in the missing fields in a surface copy command, and encodes a screen
  931.  * target update command.
  932.  */
  933. static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty)
  934. {
  935.         struct vmw_stdu_dirty *sdirty =
  936.                 container_of(dirty, struct vmw_stdu_dirty, base);
  937.         struct vmw_screen_target_display_unit *stdu =
  938.                 container_of(dirty->unit, typeof(*stdu), base);
  939.         struct vmw_stdu_surface_copy *cmd = dirty->cmd;
  940.         struct vmw_stdu_update *update;
  941.         size_t blit_size = sizeof(SVGA3dCopyBox) * dirty->num_hits;
  942.         size_t commit_size;
  943.  
  944.         if (!dirty->num_hits) {
  945.                 vmw_fifo_commit(dirty->dev_priv, 0);
  946.                 return;
  947.         }
  948.  
  949.         if (sdirty->sid != stdu->display_srf->res.id) {
  950.                 struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  951.  
  952.                 cmd->header.id = SVGA_3D_CMD_SURFACE_COPY;
  953.                 cmd->header.size = sizeof(cmd->body) + blit_size;
  954.                 cmd->body.src.sid = sdirty->sid;
  955.                 cmd->body.dest.sid = stdu->display_srf->res.id;
  956.                 update = (struct vmw_stdu_update *) &blit[dirty->num_hits];
  957.                 commit_size = sizeof(*cmd) + blit_size + sizeof(*update);
  958.         } else {
  959.                 update = dirty->cmd;
  960.                 commit_size = sizeof(*update);
  961.         }
  962.  
  963.         vmw_stdu_populate_update(update, stdu->base.unit, sdirty->left,
  964.                                  sdirty->right, sdirty->top, sdirty->bottom);
  965.  
  966.         vmw_fifo_commit(dirty->dev_priv, commit_size);
  967.  
  968.         sdirty->left = sdirty->top = S32_MAX;
  969.         sdirty->right = sdirty->bottom = S32_MIN;
  970. }
  971.  
  972. /**
  973.  * vmw_kms_stdu_surface_dirty - Dirty part of a surface backed framebuffer
  974.  *
  975.  * @dev_priv: Pointer to the device private structure.
  976.  * @framebuffer: Pointer to the surface-buffer backed framebuffer.
  977.  * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
  978.  * @vclips: Alternate array of clip rects. Either @clips or @vclips must
  979.  * be NULL.
  980.  * @srf: Pointer to surface to blit from. If NULL, the surface attached
  981.  * to @framebuffer will be used.
  982.  * @dest_x: X coordinate offset to align @srf with framebuffer coordinates.
  983.  * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates.
  984.  * @num_clips: Number of clip rects in @clips.
  985.  * @inc: Increment to use when looping over @clips.
  986.  * @out_fence: If non-NULL, will return a ref-counted pointer to a
  987.  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
  988.  * case the device has already synchronized.
  989.  *
  990.  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  991.  * interrupted.
  992.  */
  993. int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
  994.                                struct vmw_framebuffer *framebuffer,
  995.                                struct drm_clip_rect *clips,
  996.                                struct drm_vmw_rect *vclips,
  997.                                struct vmw_resource *srf,
  998.                                s32 dest_x,
  999.                                s32 dest_y,
  1000.                                unsigned num_clips, int inc,
  1001.                                struct vmw_fence_obj **out_fence)
  1002. {
  1003.         struct vmw_framebuffer_surface *vfbs =
  1004.                 container_of(framebuffer, typeof(*vfbs), base);
  1005.         struct vmw_stdu_dirty sdirty;
  1006.         int ret;
  1007.  
  1008.         if (!srf)
  1009.                 srf = &vfbs->surface->res;
  1010.  
  1011.         ret = vmw_kms_helper_resource_prepare(srf, true);
  1012.         if (ret)
  1013.                 return ret;
  1014.  
  1015.         if (vfbs->is_dmabuf_proxy) {
  1016.                 ret = vmw_kms_update_proxy(srf, clips, num_clips, inc);
  1017.                 if (ret)
  1018.                         goto out_finish;
  1019.         }
  1020.  
  1021.         sdirty.base.fifo_commit = vmw_kms_stdu_surface_fifo_commit;
  1022.         sdirty.base.clip = vmw_kms_stdu_surface_clip;
  1023.         sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) +
  1024.                 sizeof(SVGA3dCopyBox) * num_clips +
  1025.                 sizeof(struct vmw_stdu_update);
  1026.         sdirty.sid = srf->id;
  1027.         sdirty.left = sdirty.top = S32_MAX;
  1028.         sdirty.right = sdirty.bottom = S32_MIN;
  1029.  
  1030.         ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
  1031.                                    dest_x, dest_y, num_clips, inc,
  1032.                                    &sdirty.base);
  1033. out_finish:
  1034.         vmw_kms_helper_resource_finish(srf, out_fence);
  1035.  
  1036.         return ret;
  1037. }
  1038.  
  1039.  
  1040. /*
  1041.  *  Screen Target CRTC dispatch table
  1042.  */
  1043. static struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
  1044.         .save = vmw_du_crtc_save,
  1045.         .restore = vmw_du_crtc_restore,
  1046. //   .cursor_set2 = vmw_du_crtc_cursor_set2,
  1047. //   .cursor_move = vmw_du_crtc_cursor_move,
  1048.         .gamma_set = vmw_du_crtc_gamma_set,
  1049.         .destroy = vmw_stdu_crtc_destroy,
  1050.         .set_config = vmw_stdu_crtc_set_config,
  1051.         .page_flip = vmw_stdu_crtc_page_flip,
  1052. };
  1053.  
  1054.  
  1055.  
  1056. /******************************************************************************
  1057.  * Screen Target Display Unit Encoder Functions
  1058.  *****************************************************************************/
  1059.  
  1060. /**
  1061.  * vmw_stdu_encoder_destroy - cleans up the STDU
  1062.  *
  1063.  * @encoder: used the get the containing STDU
  1064.  *
  1065.  * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
  1066.  * this can be a no-op.  Nevertheless, it doesn't hurt of have this in case
  1067.  * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
  1068.  * get called.
  1069.  */
  1070. static void vmw_stdu_encoder_destroy(struct drm_encoder *encoder)
  1071. {
  1072.         vmw_stdu_destroy(vmw_encoder_to_stdu(encoder));
  1073. }
  1074.  
  1075. static struct drm_encoder_funcs vmw_stdu_encoder_funcs = {
  1076.         .destroy = vmw_stdu_encoder_destroy,
  1077. };
  1078.  
  1079.  
  1080.  
  1081. /******************************************************************************
  1082.  * Screen Target Display Unit Connector Functions
  1083.  *****************************************************************************/
  1084.  
  1085. /**
  1086.  * vmw_stdu_connector_destroy - cleans up the STDU
  1087.  *
  1088.  * @connector: used to get the containing STDU
  1089.  *
  1090.  * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
  1091.  * this can be a no-op.  Nevertheless, it doesn't hurt of have this in case
  1092.  * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
  1093.  * get called.
  1094.  */
  1095. static void vmw_stdu_connector_destroy(struct drm_connector *connector)
  1096. {
  1097.         vmw_stdu_destroy(vmw_connector_to_stdu(connector));
  1098. }
  1099.  
  1100.  
  1101.  
  1102. static struct drm_connector_funcs vmw_stdu_connector_funcs = {
  1103.         .dpms = vmw_du_connector_dpms,
  1104.         .save = vmw_du_connector_save,
  1105.         .restore = vmw_du_connector_restore,
  1106.         .detect = vmw_du_connector_detect,
  1107.         .fill_modes = vmw_du_connector_fill_modes,
  1108.         .set_property = vmw_du_connector_set_property,
  1109.         .destroy = vmw_stdu_connector_destroy,
  1110. };
  1111.  
  1112.  
  1113.  
  1114. /**
  1115.  * vmw_stdu_init - Sets up a Screen Target Display Unit
  1116.  *
  1117.  * @dev_priv: VMW DRM device
  1118.  * @unit: unit number range from 0 to VMWGFX_NUM_DISPLAY_UNITS
  1119.  *
  1120.  * This function is called once per CRTC, and allocates one Screen Target
  1121.  * display unit to represent that CRTC.  Since the SVGA device does not separate
  1122.  * out encoder and connector, they are represented as part of the STDU as well.
  1123.  */
  1124. static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
  1125. {
  1126.         struct vmw_screen_target_display_unit *stdu;
  1127.         struct drm_device *dev = dev_priv->dev;
  1128.         struct drm_connector *connector;
  1129.         struct drm_encoder *encoder;
  1130.         struct drm_crtc *crtc;
  1131.  
  1132.  
  1133.         stdu = kzalloc(sizeof(*stdu), GFP_KERNEL);
  1134.         if (!stdu)
  1135.                 return -ENOMEM;
  1136.  
  1137.         stdu->base.unit = unit;
  1138.         crtc = &stdu->base.crtc;
  1139.         encoder = &stdu->base.encoder;
  1140.         connector = &stdu->base.connector;
  1141.  
  1142.         stdu->base.pref_active = (unit == 0);
  1143.         stdu->base.pref_width  = dev_priv->initial_width;
  1144.         stdu->base.pref_height = dev_priv->initial_height;
  1145.         stdu->base.is_implicit = true;
  1146.  
  1147.         drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
  1148.                            DRM_MODE_CONNECTOR_VIRTUAL);
  1149.         connector->status = vmw_du_connector_detect(connector, false);
  1150.  
  1151.         drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
  1152.                          DRM_MODE_ENCODER_VIRTUAL);
  1153.         drm_mode_connector_attach_encoder(connector, encoder);
  1154.         encoder->possible_crtcs = (1 << unit);
  1155.         encoder->possible_clones = 0;
  1156.  
  1157.         (void) drm_connector_register(connector);
  1158.  
  1159.         drm_crtc_init(dev, crtc, &vmw_stdu_crtc_funcs);
  1160.  
  1161.         drm_mode_crtc_set_gamma_size(crtc, 256);
  1162.  
  1163.         drm_object_attach_property(&connector->base,
  1164.                                    dev->mode_config.dirty_info_property,
  1165.                                    1);
  1166.  
  1167.         return 0;
  1168. }
  1169.  
  1170.  
  1171.  
  1172. /**
  1173.  *  vmw_stdu_destroy - Cleans up a vmw_screen_target_display_unit
  1174.  *
  1175.  *  @stdu:  Screen Target Display Unit to be destroyed
  1176.  *
  1177.  *  Clean up after vmw_stdu_init
  1178.  */
  1179. static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu)
  1180. {
  1181.         vmw_stdu_unpin_display(stdu);
  1182.  
  1183.         vmw_du_cleanup(&stdu->base);
  1184.         kfree(stdu);
  1185. }
  1186.  
  1187.  
  1188.  
  1189. /******************************************************************************
  1190.  * Screen Target Display KMS Functions
  1191.  *
  1192.  * These functions are called by the common KMS code in vmwgfx_kms.c
  1193.  *****************************************************************************/
  1194.  
  1195. /**
  1196.  * vmw_kms_stdu_init_display - Initializes a Screen Target based display
  1197.  *
  1198.  * @dev_priv: VMW DRM device
  1199.  *
  1200.  * This function initialize a Screen Target based display device.  It checks
  1201.  * the capability bits to make sure the underlying hardware can support
  1202.  * screen targets, and then creates the maximum number of CRTCs, a.k.a Display
  1203.  * Units, as supported by the display hardware.
  1204.  *
  1205.  * RETURNS:
  1206.  * 0 on success, error code otherwise
  1207.  */
  1208. int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
  1209. {
  1210.         struct drm_device *dev = dev_priv->dev;
  1211.         int i, ret;
  1212.  
  1213.  
  1214.         /* Do nothing if Screen Target support is turned off */
  1215.         if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE)
  1216.                 return -ENOSYS;
  1217.  
  1218.         if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
  1219.                 return -ENOSYS;
  1220.  
  1221.         ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
  1222.         if (unlikely(ret != 0))
  1223.                 return ret;
  1224.  
  1225.         ret = drm_mode_create_dirty_info_property(dev);
  1226.         if (unlikely(ret != 0))
  1227.                 goto err_vblank_cleanup;
  1228.  
  1229.         dev_priv->active_display_unit = vmw_du_screen_target;
  1230.  
  1231.         for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) {
  1232.                 ret = vmw_stdu_init(dev_priv, i);
  1233.  
  1234.                 if (unlikely(ret != 0)) {
  1235.                         DRM_ERROR("Failed to initialize STDU %d", i);
  1236.                         goto err_vblank_cleanup;
  1237.                 }
  1238.         }
  1239.  
  1240.         DRM_INFO("Screen Target Display device initialized\n");
  1241.  
  1242.         return 0;
  1243.  
  1244. err_vblank_cleanup:
  1245.         drm_vblank_cleanup(dev);
  1246.         return ret;
  1247. }
  1248.  
  1249.  
  1250.  
  1251. /**
  1252.  * vmw_kms_stdu_close_display - Cleans up after vmw_kms_stdu_init_display
  1253.  *
  1254.  * @dev_priv: VMW DRM device
  1255.  *
  1256.  * Frees up any resources allocated by vmw_kms_stdu_init_display
  1257.  *
  1258.  * RETURNS:
  1259.  * 0 on success
  1260.  */
  1261. int vmw_kms_stdu_close_display(struct vmw_private *dev_priv)
  1262. {
  1263.         struct drm_device *dev = dev_priv->dev;
  1264.  
  1265.         drm_vblank_cleanup(dev);
  1266.  
  1267.         return 0;
  1268. }
  1269.