cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vmwgfx_stdu.c (55202B)


      1// SPDX-License-Identifier: GPL-2.0 OR MIT
      2/******************************************************************************
      3 *
      4 * COPYRIGHT (C) 2014-2022 VMware, Inc., Palo Alto, CA., USA
      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 <drm/drm_atomic.h>
     29#include <drm/drm_atomic_helper.h>
     30#include <drm/drm_damage_helper.h>
     31#include <drm/drm_fourcc.h>
     32#include <drm/drm_plane_helper.h>
     33#include <drm/drm_vblank.h>
     34
     35#include "vmwgfx_kms.h"
     36#include "vmw_surface_cache.h"
     37
     38#define vmw_crtc_to_stdu(x) \
     39	container_of(x, struct vmw_screen_target_display_unit, base.crtc)
     40#define vmw_encoder_to_stdu(x) \
     41	container_of(x, struct vmw_screen_target_display_unit, base.encoder)
     42#define vmw_connector_to_stdu(x) \
     43	container_of(x, struct vmw_screen_target_display_unit, base.connector)
     44
     45
     46
     47enum stdu_content_type {
     48	SAME_AS_DISPLAY = 0,
     49	SEPARATE_SURFACE,
     50	SEPARATE_BO
     51};
     52
     53/**
     54 * struct vmw_stdu_dirty - closure structure for the update functions
     55 *
     56 * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
     57 * @transfer: Transfer direction for DMA command.
     58 * @left: Left side of bounding box.
     59 * @right: Right side of bounding box.
     60 * @top: Top side of bounding box.
     61 * @bottom: Bottom side of bounding box.
     62 * @fb_left: Left side of the framebuffer/content bounding box
     63 * @fb_top: Top of the framebuffer/content bounding box
     64 * @pitch: framebuffer pitch (stride)
     65 * @buf: buffer object when DMA-ing between buffer and screen targets.
     66 * @sid: Surface ID when copying between surface and screen targets.
     67 */
     68struct vmw_stdu_dirty {
     69	struct vmw_kms_dirty base;
     70	SVGA3dTransferType  transfer;
     71	s32 left, right, top, bottom;
     72	s32 fb_left, fb_top;
     73	u32 pitch;
     74	union {
     75		struct vmw_buffer_object *buf;
     76		u32 sid;
     77	};
     78};
     79
     80/*
     81 * SVGA commands that are used by this code. Please see the device headers
     82 * for explanation.
     83 */
     84struct vmw_stdu_update {
     85	SVGA3dCmdHeader header;
     86	SVGA3dCmdUpdateGBScreenTarget body;
     87};
     88
     89struct vmw_stdu_dma {
     90	SVGA3dCmdHeader     header;
     91	SVGA3dCmdSurfaceDMA body;
     92};
     93
     94struct vmw_stdu_surface_copy {
     95	SVGA3dCmdHeader      header;
     96	SVGA3dCmdSurfaceCopy body;
     97};
     98
     99struct vmw_stdu_update_gb_image {
    100	SVGA3dCmdHeader header;
    101	SVGA3dCmdUpdateGBImage body;
    102};
    103
    104/**
    105 * struct vmw_screen_target_display_unit
    106 *
    107 * @base: VMW specific DU structure
    108 * @display_srf: surface to be displayed.  The dimension of this will always
    109 *               match the display mode.  If the display mode matches
    110 *               content_vfbs dimensions, then this is a pointer into the
    111 *               corresponding field in content_vfbs.  If not, then this
    112 *               is a separate buffer to which content_vfbs will blit to.
    113 * @content_fb_type: content_fb type
    114 * @display_width:  display width
    115 * @display_height: display height
    116 * @defined:     true if the current display unit has been initialized
    117 * @cpp:         Bytes per pixel
    118 */
    119struct vmw_screen_target_display_unit {
    120	struct vmw_display_unit base;
    121	struct vmw_surface *display_srf;
    122	enum stdu_content_type content_fb_type;
    123	s32 display_width, display_height;
    124
    125	bool defined;
    126
    127	/* For CPU Blit */
    128	unsigned int cpp;
    129};
    130
    131
    132
    133static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu);
    134
    135
    136
    137/******************************************************************************
    138 * Screen Target Display Unit CRTC Functions
    139 *****************************************************************************/
    140
    141static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw)
    142{
    143	return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024);
    144}
    145
    146
    147/**
    148 * vmw_stdu_crtc_destroy - cleans up the STDU
    149 *
    150 * @crtc: used to get a reference to the containing STDU
    151 */
    152static void vmw_stdu_crtc_destroy(struct drm_crtc *crtc)
    153{
    154	vmw_stdu_destroy(vmw_crtc_to_stdu(crtc));
    155}
    156
    157/**
    158 * vmw_stdu_define_st - Defines a Screen Target
    159 *
    160 * @dev_priv:  VMW DRM device
    161 * @stdu: display unit to create a Screen Target for
    162 * @mode: The mode to set.
    163 * @crtc_x: X coordinate of screen target relative to framebuffer origin.
    164 * @crtc_y: Y coordinate of screen target relative to framebuffer origin.
    165 *
    166 * Creates a STDU that we can used later.  This function is called whenever the
    167 * framebuffer size changes.
    168 *
    169 * RETURNs:
    170 * 0 on success, error code on failure
    171 */
    172static int vmw_stdu_define_st(struct vmw_private *dev_priv,
    173			      struct vmw_screen_target_display_unit *stdu,
    174			      struct drm_display_mode *mode,
    175			      int crtc_x, int crtc_y)
    176{
    177	struct {
    178		SVGA3dCmdHeader header;
    179		SVGA3dCmdDefineGBScreenTarget body;
    180	} *cmd;
    181
    182	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
    183	if (unlikely(cmd == NULL))
    184		return -ENOMEM;
    185
    186	cmd->header.id   = SVGA_3D_CMD_DEFINE_GB_SCREENTARGET;
    187	cmd->header.size = sizeof(cmd->body);
    188
    189	cmd->body.stid   = stdu->base.unit;
    190	cmd->body.width  = mode->hdisplay;
    191	cmd->body.height = mode->vdisplay;
    192	cmd->body.flags  = (0 == cmd->body.stid) ? SVGA_STFLAG_PRIMARY : 0;
    193	cmd->body.dpi    = 0;
    194	cmd->body.xRoot  = crtc_x;
    195	cmd->body.yRoot  = crtc_y;
    196
    197	stdu->base.set_gui_x = cmd->body.xRoot;
    198	stdu->base.set_gui_y = cmd->body.yRoot;
    199
    200	vmw_cmd_commit(dev_priv, sizeof(*cmd));
    201
    202	stdu->defined = true;
    203	stdu->display_width  = mode->hdisplay;
    204	stdu->display_height = mode->vdisplay;
    205
    206	return 0;
    207}
    208
    209
    210
    211/**
    212 * vmw_stdu_bind_st - Binds a surface to a Screen Target
    213 *
    214 * @dev_priv: VMW DRM device
    215 * @stdu: display unit affected
    216 * @res: Buffer to bind to the screen target.  Set to NULL to blank screen.
    217 *
    218 * Binding a surface to a Screen Target the same as flipping
    219 */
    220static int vmw_stdu_bind_st(struct vmw_private *dev_priv,
    221			    struct vmw_screen_target_display_unit *stdu,
    222			    const struct vmw_resource *res)
    223{
    224	SVGA3dSurfaceImageId image;
    225
    226	struct {
    227		SVGA3dCmdHeader header;
    228		SVGA3dCmdBindGBScreenTarget body;
    229	} *cmd;
    230
    231
    232	if (!stdu->defined) {
    233		DRM_ERROR("No screen target defined\n");
    234		return -EINVAL;
    235	}
    236
    237	/* Set up image using information in vfb */
    238	memset(&image, 0, sizeof(image));
    239	image.sid = res ? res->id : SVGA3D_INVALID_ID;
    240
    241	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
    242	if (unlikely(cmd == NULL))
    243		return -ENOMEM;
    244
    245	cmd->header.id   = SVGA_3D_CMD_BIND_GB_SCREENTARGET;
    246	cmd->header.size = sizeof(cmd->body);
    247
    248	cmd->body.stid   = stdu->base.unit;
    249	cmd->body.image  = image;
    250
    251	vmw_cmd_commit(dev_priv, sizeof(*cmd));
    252
    253	return 0;
    254}
    255
    256/**
    257 * vmw_stdu_populate_update - populate an UPDATE_GB_SCREENTARGET command with a
    258 * bounding box.
    259 *
    260 * @cmd: Pointer to command stream.
    261 * @unit: Screen target unit.
    262 * @left: Left side of bounding box.
    263 * @right: Right side of bounding box.
    264 * @top: Top side of bounding box.
    265 * @bottom: Bottom side of bounding box.
    266 */
    267static void vmw_stdu_populate_update(void *cmd, int unit,
    268				     s32 left, s32 right, s32 top, s32 bottom)
    269{
    270	struct vmw_stdu_update *update = cmd;
    271
    272	update->header.id   = SVGA_3D_CMD_UPDATE_GB_SCREENTARGET;
    273	update->header.size = sizeof(update->body);
    274
    275	update->body.stid   = unit;
    276	update->body.rect.x = left;
    277	update->body.rect.y = top;
    278	update->body.rect.w = right - left;
    279	update->body.rect.h = bottom - top;
    280}
    281
    282/**
    283 * vmw_stdu_update_st - Full update of a Screen Target
    284 *
    285 * @dev_priv: VMW DRM device
    286 * @stdu: display unit affected
    287 *
    288 * This function needs to be called whenever the content of a screen
    289 * target has changed completely. Typically as a result of a backing
    290 * surface change.
    291 *
    292 * RETURNS:
    293 * 0 on success, error code on failure
    294 */
    295static int vmw_stdu_update_st(struct vmw_private *dev_priv,
    296			      struct vmw_screen_target_display_unit *stdu)
    297{
    298	struct vmw_stdu_update *cmd;
    299
    300	if (!stdu->defined) {
    301		DRM_ERROR("No screen target defined");
    302		return -EINVAL;
    303	}
    304
    305	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
    306	if (unlikely(cmd == NULL))
    307		return -ENOMEM;
    308
    309	vmw_stdu_populate_update(cmd, stdu->base.unit,
    310				 0, stdu->display_width,
    311				 0, stdu->display_height);
    312
    313	vmw_cmd_commit(dev_priv, sizeof(*cmd));
    314
    315	return 0;
    316}
    317
    318
    319
    320/**
    321 * vmw_stdu_destroy_st - Destroy a Screen Target
    322 *
    323 * @dev_priv:  VMW DRM device
    324 * @stdu: display unit to destroy
    325 */
    326static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
    327			       struct vmw_screen_target_display_unit *stdu)
    328{
    329	int    ret;
    330
    331	struct {
    332		SVGA3dCmdHeader header;
    333		SVGA3dCmdDestroyGBScreenTarget body;
    334	} *cmd;
    335
    336
    337	/* Nothing to do if not successfully defined */
    338	if (unlikely(!stdu->defined))
    339		return 0;
    340
    341	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
    342	if (unlikely(cmd == NULL))
    343		return -ENOMEM;
    344
    345	cmd->header.id   = SVGA_3D_CMD_DESTROY_GB_SCREENTARGET;
    346	cmd->header.size = sizeof(cmd->body);
    347
    348	cmd->body.stid   = stdu->base.unit;
    349
    350	vmw_cmd_commit(dev_priv, sizeof(*cmd));
    351
    352	/* Force sync */
    353	ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
    354	if (unlikely(ret != 0))
    355		DRM_ERROR("Failed to sync with HW");
    356
    357	stdu->defined = false;
    358	stdu->display_width  = 0;
    359	stdu->display_height = 0;
    360
    361	return ret;
    362}
    363
    364
    365/**
    366 * vmw_stdu_crtc_mode_set_nofb - Updates screen target size
    367 *
    368 * @crtc: CRTC associated with the screen target
    369 *
    370 * This function defines/destroys a screen target
    371 *
    372 */
    373static void vmw_stdu_crtc_mode_set_nofb(struct drm_crtc *crtc)
    374{
    375	struct vmw_private *dev_priv;
    376	struct vmw_screen_target_display_unit *stdu;
    377	struct drm_connector_state *conn_state;
    378	struct vmw_connector_state *vmw_conn_state;
    379	int x, y, ret;
    380
    381	stdu = vmw_crtc_to_stdu(crtc);
    382	dev_priv = vmw_priv(crtc->dev);
    383	conn_state = stdu->base.connector.state;
    384	vmw_conn_state = vmw_connector_state_to_vcs(conn_state);
    385
    386	if (stdu->defined) {
    387		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
    388		if (ret)
    389			DRM_ERROR("Failed to blank CRTC\n");
    390
    391		(void) vmw_stdu_update_st(dev_priv, stdu);
    392
    393		ret = vmw_stdu_destroy_st(dev_priv, stdu);
    394		if (ret)
    395			DRM_ERROR("Failed to destroy Screen Target\n");
    396
    397		stdu->content_fb_type = SAME_AS_DISPLAY;
    398	}
    399
    400	if (!crtc->state->enable)
    401		return;
    402
    403	x = vmw_conn_state->gui_x;
    404	y = vmw_conn_state->gui_y;
    405
    406	vmw_svga_enable(dev_priv);
    407	ret = vmw_stdu_define_st(dev_priv, stdu, &crtc->mode, x, y);
    408
    409	if (ret)
    410		DRM_ERROR("Failed to define Screen Target of size %dx%d\n",
    411			  crtc->x, crtc->y);
    412}
    413
    414
    415static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc)
    416{
    417}
    418
    419static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc,
    420					struct drm_atomic_state *state)
    421{
    422}
    423
    424static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
    425					 struct drm_atomic_state *state)
    426{
    427	struct vmw_private *dev_priv;
    428	struct vmw_screen_target_display_unit *stdu;
    429	int ret;
    430
    431
    432	if (!crtc) {
    433		DRM_ERROR("CRTC is NULL\n");
    434		return;
    435	}
    436
    437	stdu     = vmw_crtc_to_stdu(crtc);
    438	dev_priv = vmw_priv(crtc->dev);
    439
    440	if (stdu->defined) {
    441		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
    442		if (ret)
    443			DRM_ERROR("Failed to blank CRTC\n");
    444
    445		(void) vmw_stdu_update_st(dev_priv, stdu);
    446
    447		ret = vmw_stdu_destroy_st(dev_priv, stdu);
    448		if (ret)
    449			DRM_ERROR("Failed to destroy Screen Target\n");
    450
    451		stdu->content_fb_type = SAME_AS_DISPLAY;
    452	}
    453}
    454
    455/**
    456 * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect
    457 *
    458 * @dirty: The closure structure.
    459 *
    460 * Encodes a surface DMA command cliprect and updates the bounding box
    461 * for the DMA.
    462 */
    463static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty)
    464{
    465	struct vmw_stdu_dirty *ddirty =
    466		container_of(dirty, struct vmw_stdu_dirty, base);
    467	struct vmw_stdu_dma *cmd = dirty->cmd;
    468	struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
    469
    470	blit += dirty->num_hits;
    471	blit->srcx = dirty->fb_x;
    472	blit->srcy = dirty->fb_y;
    473	blit->x = dirty->unit_x1;
    474	blit->y = dirty->unit_y1;
    475	blit->d = 1;
    476	blit->w = dirty->unit_x2 - dirty->unit_x1;
    477	blit->h = dirty->unit_y2 - dirty->unit_y1;
    478	dirty->num_hits++;
    479
    480	if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM)
    481		return;
    482
    483	/* Destination bounding box */
    484	ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
    485	ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
    486	ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
    487	ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
    488}
    489
    490/**
    491 * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command.
    492 *
    493 * @dirty: The closure structure.
    494 *
    495 * Fills in the missing fields in a DMA command, and optionally encodes
    496 * a screen target update command, depending on transfer direction.
    497 */
    498static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty)
    499{
    500	struct vmw_stdu_dirty *ddirty =
    501		container_of(dirty, struct vmw_stdu_dirty, base);
    502	struct vmw_screen_target_display_unit *stdu =
    503		container_of(dirty->unit, typeof(*stdu), base);
    504	struct vmw_stdu_dma *cmd = dirty->cmd;
    505	struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
    506	SVGA3dCmdSurfaceDMASuffix *suffix =
    507		(SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits];
    508	size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix);
    509
    510	if (!dirty->num_hits) {
    511		vmw_cmd_commit(dirty->dev_priv, 0);
    512		return;
    513	}
    514
    515	cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
    516	cmd->header.size = sizeof(cmd->body) + blit_size;
    517	vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr);
    518	cmd->body.guest.pitch = ddirty->pitch;
    519	cmd->body.host.sid = stdu->display_srf->res.id;
    520	cmd->body.host.face = 0;
    521	cmd->body.host.mipmap = 0;
    522	cmd->body.transfer = ddirty->transfer;
    523	suffix->suffixSize = sizeof(*suffix);
    524	suffix->maximumOffset = ddirty->buf->base.base.size;
    525
    526	if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) {
    527		blit_size += sizeof(struct vmw_stdu_update);
    528
    529		vmw_stdu_populate_update(&suffix[1], stdu->base.unit,
    530					 ddirty->left, ddirty->right,
    531					 ddirty->top, ddirty->bottom);
    532	}
    533
    534	vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size);
    535
    536	stdu->display_srf->res.res_dirty = true;
    537	ddirty->left = ddirty->top = S32_MAX;
    538	ddirty->right = ddirty->bottom = S32_MIN;
    539}
    540
    541
    542/**
    543 * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit
    544 *
    545 * @dirty: The closure structure.
    546 *
    547 * This function calculates the bounding box for all the incoming clips.
    548 */
    549static void vmw_stdu_bo_cpu_clip(struct vmw_kms_dirty *dirty)
    550{
    551	struct vmw_stdu_dirty *ddirty =
    552		container_of(dirty, struct vmw_stdu_dirty, base);
    553
    554	dirty->num_hits = 1;
    555
    556	/* Calculate destination bounding box */
    557	ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
    558	ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
    559	ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
    560	ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
    561
    562	/*
    563	 * Calculate content bounding box.  We only need the top-left
    564	 * coordinate because width and height will be the same as the
    565	 * destination bounding box above
    566	 */
    567	ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x);
    568	ddirty->fb_top  = min_t(s32, ddirty->fb_top, dirty->fb_y);
    569}
    570
    571
    572/**
    573 * vmw_stdu_bo_cpu_commit - Callback to do a CPU blit from buffer object
    574 *
    575 * @dirty: The closure structure.
    576 *
    577 * For the special case when we cannot create a proxy surface in a
    578 * 2D VM, we have to do a CPU blit ourselves.
    579 */
    580static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty)
    581{
    582	struct vmw_stdu_dirty *ddirty =
    583		container_of(dirty, struct vmw_stdu_dirty, base);
    584	struct vmw_screen_target_display_unit *stdu =
    585		container_of(dirty->unit, typeof(*stdu), base);
    586	s32 width, height;
    587	s32 src_pitch, dst_pitch;
    588	struct ttm_buffer_object *src_bo, *dst_bo;
    589	u32 src_offset, dst_offset;
    590	struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(stdu->cpp);
    591
    592	if (!dirty->num_hits)
    593		return;
    594
    595	width = ddirty->right - ddirty->left;
    596	height = ddirty->bottom - ddirty->top;
    597
    598	if (width == 0 || height == 0)
    599		return;
    600
    601	/* Assume we are blitting from Guest (bo) to Host (display_srf) */
    602	dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
    603	dst_bo = &stdu->display_srf->res.backup->base;
    604	dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp;
    605
    606	src_pitch = ddirty->pitch;
    607	src_bo = &ddirty->buf->base;
    608	src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp;
    609
    610	/* Swap src and dst if the assumption was wrong. */
    611	if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) {
    612		swap(dst_pitch, src_pitch);
    613		swap(dst_bo, src_bo);
    614		swap(src_offset, dst_offset);
    615	}
    616
    617	(void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch,
    618			       src_bo, src_offset, src_pitch,
    619			       width * stdu->cpp, height, &diff);
    620
    621	if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM &&
    622	    drm_rect_visible(&diff.rect)) {
    623		struct vmw_private *dev_priv;
    624		struct vmw_stdu_update *cmd;
    625		struct drm_clip_rect region;
    626		int ret;
    627
    628		/* We are updating the actual surface, not a proxy */
    629		region.x1 = diff.rect.x1;
    630		region.x2 = diff.rect.x2;
    631		region.y1 = diff.rect.y1;
    632		region.y2 = diff.rect.y2;
    633		ret = vmw_kms_update_proxy(&stdu->display_srf->res, &region,
    634					   1, 1);
    635		if (ret)
    636			goto out_cleanup;
    637
    638
    639		dev_priv = vmw_priv(stdu->base.crtc.dev);
    640		cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
    641		if (!cmd)
    642			goto out_cleanup;
    643
    644		vmw_stdu_populate_update(cmd, stdu->base.unit,
    645					 region.x1, region.x2,
    646					 region.y1, region.y2);
    647
    648		vmw_cmd_commit(dev_priv, sizeof(*cmd));
    649	}
    650
    651out_cleanup:
    652	ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
    653	ddirty->right = ddirty->bottom = S32_MIN;
    654}
    655
    656/**
    657 * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed
    658 * framebuffer and the screen target system.
    659 *
    660 * @dev_priv: Pointer to the device private structure.
    661 * @file_priv: Pointer to a struct drm-file identifying the caller. May be
    662 * set to NULL, but then @user_fence_rep must also be set to NULL.
    663 * @vfb: Pointer to the buffer-object backed framebuffer.
    664 * @user_fence_rep: User-space provided structure for fence information.
    665 * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
    666 * @vclips: Alternate array of clip rects. Either @clips or @vclips must
    667 * be NULL.
    668 * @num_clips: Number of clip rects in @clips or @vclips.
    669 * @increment: Increment to use when looping over @clips or @vclips.
    670 * @to_surface: Whether to DMA to the screen target system as opposed to
    671 * from the screen target system.
    672 * @interruptible: Whether to perform waits interruptible if possible.
    673 * @crtc: If crtc is passed, perform stdu dma on that crtc only.
    674 *
    675 * If DMA-ing till the screen target system, the function will also notify
    676 * the screen target system that a bounding box of the cliprects has been
    677 * updated.
    678 * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
    679 * interrupted.
    680 */
    681int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
    682		     struct drm_file *file_priv,
    683		     struct vmw_framebuffer *vfb,
    684		     struct drm_vmw_fence_rep __user *user_fence_rep,
    685		     struct drm_clip_rect *clips,
    686		     struct drm_vmw_rect *vclips,
    687		     uint32_t num_clips,
    688		     int increment,
    689		     bool to_surface,
    690		     bool interruptible,
    691		     struct drm_crtc *crtc)
    692{
    693	struct vmw_buffer_object *buf =
    694		container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;
    695	struct vmw_stdu_dirty ddirty;
    696	int ret;
    697	bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv);
    698	DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
    699
    700	/*
    701	 * VMs without 3D support don't have the surface DMA command and
    702	 * we'll be using a CPU blit, and the framebuffer should be moved out
    703	 * of VRAM.
    704	 */
    705	ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit);
    706	if (ret)
    707		return ret;
    708
    709	ret = vmw_validation_prepare(&val_ctx, NULL, interruptible);
    710	if (ret)
    711		goto out_unref;
    712
    713	ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM :
    714		SVGA3D_READ_HOST_VRAM;
    715	ddirty.left = ddirty.top = S32_MAX;
    716	ddirty.right = ddirty.bottom = S32_MIN;
    717	ddirty.fb_left = ddirty.fb_top = S32_MAX;
    718	ddirty.pitch = vfb->base.pitches[0];
    719	ddirty.buf = buf;
    720	ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit;
    721	ddirty.base.clip = vmw_stdu_bo_clip;
    722	ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) +
    723		num_clips * sizeof(SVGA3dCopyBox) +
    724		sizeof(SVGA3dCmdSurfaceDMASuffix);
    725	if (to_surface)
    726		ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update);
    727
    728
    729	if (cpu_blit) {
    730		ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit;
    731		ddirty.base.clip = vmw_stdu_bo_cpu_clip;
    732		ddirty.base.fifo_reserve_size = 0;
    733	}
    734
    735	ddirty.base.crtc = crtc;
    736
    737	ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips,
    738				   0, 0, num_clips, increment, &ddirty.base);
    739
    740	vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL,
    741					 user_fence_rep);
    742	return ret;
    743
    744out_unref:
    745	vmw_validation_unref_lists(&val_ctx);
    746	return ret;
    747}
    748
    749/**
    750 * vmw_kms_stdu_surface_clip - Callback to encode a surface copy command cliprect
    751 *
    752 * @dirty: The closure structure.
    753 *
    754 * Encodes a surface copy command cliprect and updates the bounding box
    755 * for the copy.
    756 */
    757static void vmw_kms_stdu_surface_clip(struct vmw_kms_dirty *dirty)
    758{
    759	struct vmw_stdu_dirty *sdirty =
    760		container_of(dirty, struct vmw_stdu_dirty, base);
    761	struct vmw_stdu_surface_copy *cmd = dirty->cmd;
    762	struct vmw_screen_target_display_unit *stdu =
    763		container_of(dirty->unit, typeof(*stdu), base);
    764
    765	if (sdirty->sid != stdu->display_srf->res.id) {
    766		struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
    767
    768		blit += dirty->num_hits;
    769		blit->srcx = dirty->fb_x;
    770		blit->srcy = dirty->fb_y;
    771		blit->x = dirty->unit_x1;
    772		blit->y = dirty->unit_y1;
    773		blit->d = 1;
    774		blit->w = dirty->unit_x2 - dirty->unit_x1;
    775		blit->h = dirty->unit_y2 - dirty->unit_y1;
    776	}
    777
    778	dirty->num_hits++;
    779
    780	/* Destination bounding box */
    781	sdirty->left = min_t(s32, sdirty->left, dirty->unit_x1);
    782	sdirty->top = min_t(s32, sdirty->top, dirty->unit_y1);
    783	sdirty->right = max_t(s32, sdirty->right, dirty->unit_x2);
    784	sdirty->bottom = max_t(s32, sdirty->bottom, dirty->unit_y2);
    785}
    786
    787/**
    788 * vmw_kms_stdu_surface_fifo_commit - Callback to fill in and submit a surface
    789 * copy command.
    790 *
    791 * @dirty: The closure structure.
    792 *
    793 * Fills in the missing fields in a surface copy command, and encodes a screen
    794 * target update command.
    795 */
    796static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty)
    797{
    798	struct vmw_stdu_dirty *sdirty =
    799		container_of(dirty, struct vmw_stdu_dirty, base);
    800	struct vmw_screen_target_display_unit *stdu =
    801		container_of(dirty->unit, typeof(*stdu), base);
    802	struct vmw_stdu_surface_copy *cmd = dirty->cmd;
    803	struct vmw_stdu_update *update;
    804	size_t blit_size = sizeof(SVGA3dCopyBox) * dirty->num_hits;
    805	size_t commit_size;
    806
    807	if (!dirty->num_hits) {
    808		vmw_cmd_commit(dirty->dev_priv, 0);
    809		return;
    810	}
    811
    812	if (sdirty->sid != stdu->display_srf->res.id) {
    813		struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
    814
    815		cmd->header.id = SVGA_3D_CMD_SURFACE_COPY;
    816		cmd->header.size = sizeof(cmd->body) + blit_size;
    817		cmd->body.src.sid = sdirty->sid;
    818		cmd->body.dest.sid = stdu->display_srf->res.id;
    819		update = (struct vmw_stdu_update *) &blit[dirty->num_hits];
    820		commit_size = sizeof(*cmd) + blit_size + sizeof(*update);
    821		stdu->display_srf->res.res_dirty = true;
    822	} else {
    823		update = dirty->cmd;
    824		commit_size = sizeof(*update);
    825	}
    826
    827	vmw_stdu_populate_update(update, stdu->base.unit, sdirty->left,
    828				 sdirty->right, sdirty->top, sdirty->bottom);
    829
    830	vmw_cmd_commit(dirty->dev_priv, commit_size);
    831
    832	sdirty->left = sdirty->top = S32_MAX;
    833	sdirty->right = sdirty->bottom = S32_MIN;
    834}
    835
    836/**
    837 * vmw_kms_stdu_surface_dirty - Dirty part of a surface backed framebuffer
    838 *
    839 * @dev_priv: Pointer to the device private structure.
    840 * @framebuffer: Pointer to the surface-buffer backed framebuffer.
    841 * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
    842 * @vclips: Alternate array of clip rects. Either @clips or @vclips must
    843 * be NULL.
    844 * @srf: Pointer to surface to blit from. If NULL, the surface attached
    845 * to @framebuffer will be used.
    846 * @dest_x: X coordinate offset to align @srf with framebuffer coordinates.
    847 * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates.
    848 * @num_clips: Number of clip rects in @clips.
    849 * @inc: Increment to use when looping over @clips.
    850 * @out_fence: If non-NULL, will return a ref-counted pointer to a
    851 * struct vmw_fence_obj. The returned fence pointer may be NULL in which
    852 * case the device has already synchronized.
    853 * @crtc: If crtc is passed, perform surface dirty on that crtc only.
    854 *
    855 * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
    856 * interrupted.
    857 */
    858int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
    859			       struct vmw_framebuffer *framebuffer,
    860			       struct drm_clip_rect *clips,
    861			       struct drm_vmw_rect *vclips,
    862			       struct vmw_resource *srf,
    863			       s32 dest_x,
    864			       s32 dest_y,
    865			       unsigned num_clips, int inc,
    866			       struct vmw_fence_obj **out_fence,
    867			       struct drm_crtc *crtc)
    868{
    869	struct vmw_framebuffer_surface *vfbs =
    870		container_of(framebuffer, typeof(*vfbs), base);
    871	struct vmw_stdu_dirty sdirty;
    872	DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
    873	int ret;
    874
    875	if (!srf)
    876		srf = &vfbs->surface->res;
    877
    878	ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE,
    879					  NULL, NULL);
    880	if (ret)
    881		return ret;
    882
    883	ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true);
    884	if (ret)
    885		goto out_unref;
    886
    887	if (vfbs->is_bo_proxy) {
    888		ret = vmw_kms_update_proxy(srf, clips, num_clips, inc);
    889		if (ret)
    890			goto out_finish;
    891	}
    892
    893	sdirty.base.fifo_commit = vmw_kms_stdu_surface_fifo_commit;
    894	sdirty.base.clip = vmw_kms_stdu_surface_clip;
    895	sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) +
    896		sizeof(SVGA3dCopyBox) * num_clips +
    897		sizeof(struct vmw_stdu_update);
    898	sdirty.base.crtc = crtc;
    899	sdirty.sid = srf->id;
    900	sdirty.left = sdirty.top = S32_MAX;
    901	sdirty.right = sdirty.bottom = S32_MIN;
    902
    903	ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
    904				   dest_x, dest_y, num_clips, inc,
    905				   &sdirty.base);
    906out_finish:
    907	vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
    908					 NULL);
    909
    910	return ret;
    911
    912out_unref:
    913	vmw_validation_unref_lists(&val_ctx);
    914	return ret;
    915}
    916
    917
    918/*
    919 *  Screen Target CRTC dispatch table
    920 */
    921static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
    922	.gamma_set = vmw_du_crtc_gamma_set,
    923	.destroy = vmw_stdu_crtc_destroy,
    924	.reset = vmw_du_crtc_reset,
    925	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
    926	.atomic_destroy_state = vmw_du_crtc_destroy_state,
    927	.set_config = drm_atomic_helper_set_config,
    928	.page_flip = drm_atomic_helper_page_flip,
    929	.get_vblank_counter = vmw_get_vblank_counter,
    930	.enable_vblank = vmw_enable_vblank,
    931	.disable_vblank = vmw_disable_vblank,
    932};
    933
    934
    935
    936/******************************************************************************
    937 * Screen Target Display Unit Encoder Functions
    938 *****************************************************************************/
    939
    940/**
    941 * vmw_stdu_encoder_destroy - cleans up the STDU
    942 *
    943 * @encoder: used the get the containing STDU
    944 *
    945 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
    946 * this can be a no-op.  Nevertheless, it doesn't hurt of have this in case
    947 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
    948 * get called.
    949 */
    950static void vmw_stdu_encoder_destroy(struct drm_encoder *encoder)
    951{
    952	vmw_stdu_destroy(vmw_encoder_to_stdu(encoder));
    953}
    954
    955static const struct drm_encoder_funcs vmw_stdu_encoder_funcs = {
    956	.destroy = vmw_stdu_encoder_destroy,
    957};
    958
    959
    960
    961/******************************************************************************
    962 * Screen Target Display Unit Connector Functions
    963 *****************************************************************************/
    964
    965/**
    966 * vmw_stdu_connector_destroy - cleans up the STDU
    967 *
    968 * @connector: used to get the containing STDU
    969 *
    970 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
    971 * this can be a no-op.  Nevertheless, it doesn't hurt of have this in case
    972 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
    973 * get called.
    974 */
    975static void vmw_stdu_connector_destroy(struct drm_connector *connector)
    976{
    977	vmw_stdu_destroy(vmw_connector_to_stdu(connector));
    978}
    979
    980
    981
    982static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
    983	.dpms = vmw_du_connector_dpms,
    984	.detect = vmw_du_connector_detect,
    985	.fill_modes = vmw_du_connector_fill_modes,
    986	.destroy = vmw_stdu_connector_destroy,
    987	.reset = vmw_du_connector_reset,
    988	.atomic_duplicate_state = vmw_du_connector_duplicate_state,
    989	.atomic_destroy_state = vmw_du_connector_destroy_state,
    990};
    991
    992
    993static const struct
    994drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
    995};
    996
    997
    998
    999/******************************************************************************
   1000 * Screen Target Display Plane Functions
   1001 *****************************************************************************/
   1002
   1003
   1004
   1005/**
   1006 * vmw_stdu_primary_plane_cleanup_fb - Unpins the display surface
   1007 *
   1008 * @plane:  display plane
   1009 * @old_state: Contains the FB to clean up
   1010 *
   1011 * Unpins the display surface
   1012 *
   1013 * Returns 0 on success
   1014 */
   1015static void
   1016vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
   1017				  struct drm_plane_state *old_state)
   1018{
   1019	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
   1020
   1021	if (vps->surf)
   1022		WARN_ON(!vps->pinned);
   1023
   1024	vmw_du_plane_cleanup_fb(plane, old_state);
   1025
   1026	vps->content_fb_type = SAME_AS_DISPLAY;
   1027	vps->cpp = 0;
   1028}
   1029
   1030
   1031
   1032/**
   1033 * vmw_stdu_primary_plane_prepare_fb - Readies the display surface
   1034 *
   1035 * @plane:  display plane
   1036 * @new_state: info on the new plane state, including the FB
   1037 *
   1038 * This function allocates a new display surface if the content is
   1039 * backed by a buffer object.  The display surface is pinned here, and it'll
   1040 * be unpinned in .cleanup_fb()
   1041 *
   1042 * Returns 0 on success
   1043 */
   1044static int
   1045vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
   1046				  struct drm_plane_state *new_state)
   1047{
   1048	struct vmw_private *dev_priv = vmw_priv(plane->dev);
   1049	struct drm_framebuffer *new_fb = new_state->fb;
   1050	struct vmw_framebuffer *vfb;
   1051	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
   1052	enum stdu_content_type new_content_type;
   1053	struct vmw_framebuffer_surface *new_vfbs;
   1054	uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h;
   1055	int ret;
   1056
   1057	/* No FB to prepare */
   1058	if (!new_fb) {
   1059		if (vps->surf) {
   1060			WARN_ON(vps->pinned != 0);
   1061			vmw_surface_unreference(&vps->surf);
   1062		}
   1063
   1064		return 0;
   1065	}
   1066
   1067	vfb = vmw_framebuffer_to_vfb(new_fb);
   1068	new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
   1069
   1070	if (new_vfbs &&
   1071	    new_vfbs->surface->metadata.base_size.width == hdisplay &&
   1072	    new_vfbs->surface->metadata.base_size.height == vdisplay)
   1073		new_content_type = SAME_AS_DISPLAY;
   1074	else if (vfb->bo)
   1075		new_content_type = SEPARATE_BO;
   1076	else
   1077		new_content_type = SEPARATE_SURFACE;
   1078
   1079	if (new_content_type != SAME_AS_DISPLAY) {
   1080		struct vmw_surface_metadata metadata = {0};
   1081
   1082		/*
   1083		 * If content buffer is a buffer object, then we have to
   1084		 * construct surface info
   1085		 */
   1086		if (new_content_type == SEPARATE_BO) {
   1087
   1088			switch (new_fb->format->cpp[0]*8) {
   1089			case 32:
   1090				metadata.format = SVGA3D_X8R8G8B8;
   1091				break;
   1092
   1093			case 16:
   1094				metadata.format = SVGA3D_R5G6B5;
   1095				break;
   1096
   1097			case 8:
   1098				metadata.format = SVGA3D_P8;
   1099				break;
   1100
   1101			default:
   1102				DRM_ERROR("Invalid format\n");
   1103				return -EINVAL;
   1104			}
   1105
   1106			metadata.mip_levels[0] = 1;
   1107			metadata.num_sizes = 1;
   1108			metadata.scanout = true;
   1109		} else {
   1110			metadata = new_vfbs->surface->metadata;
   1111		}
   1112
   1113		metadata.base_size.width = hdisplay;
   1114		metadata.base_size.height = vdisplay;
   1115		metadata.base_size.depth = 1;
   1116
   1117		if (vps->surf) {
   1118			struct drm_vmw_size cur_base_size =
   1119				vps->surf->metadata.base_size;
   1120
   1121			if (cur_base_size.width != metadata.base_size.width ||
   1122			    cur_base_size.height != metadata.base_size.height ||
   1123			    vps->surf->metadata.format != metadata.format) {
   1124				WARN_ON(vps->pinned != 0);
   1125				vmw_surface_unreference(&vps->surf);
   1126			}
   1127
   1128		}
   1129
   1130		if (!vps->surf) {
   1131			ret = vmw_gb_surface_define(dev_priv, &metadata,
   1132						    &vps->surf);
   1133			if (ret != 0) {
   1134				DRM_ERROR("Couldn't allocate STDU surface.\n");
   1135				return ret;
   1136			}
   1137		}
   1138	} else {
   1139		/*
   1140		 * prepare_fb and clean_fb should only take care of pinning
   1141		 * and unpinning.  References are tracked by state objects.
   1142		 * The only time we add a reference in prepare_fb is if the
   1143		 * state object doesn't have a reference to begin with
   1144		 */
   1145		if (vps->surf) {
   1146			WARN_ON(vps->pinned != 0);
   1147			vmw_surface_unreference(&vps->surf);
   1148		}
   1149
   1150		vps->surf = vmw_surface_reference(new_vfbs->surface);
   1151	}
   1152
   1153	if (vps->surf) {
   1154
   1155		/* Pin new surface before flipping */
   1156		ret = vmw_resource_pin(&vps->surf->res, false);
   1157		if (ret)
   1158			goto out_srf_unref;
   1159
   1160		vps->pinned++;
   1161	}
   1162
   1163	vps->content_fb_type = new_content_type;
   1164
   1165	/*
   1166	 * This should only happen if the buffer object is too large to create a
   1167	 * proxy surface for.
   1168	 * If we are a 2D VM with a buffer object then we have to use CPU blit
   1169	 * so cache these mappings
   1170	 */
   1171	if (vps->content_fb_type == SEPARATE_BO &&
   1172	    vmw_stdu_use_cpu_blit(dev_priv))
   1173		vps->cpp = new_fb->pitches[0] / new_fb->width;
   1174
   1175	return 0;
   1176
   1177out_srf_unref:
   1178	vmw_surface_unreference(&vps->surf);
   1179	return ret;
   1180}
   1181
   1182static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update,
   1183				      uint32_t num_hits)
   1184{
   1185	return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits +
   1186		sizeof(SVGA3dCmdSurfaceDMASuffix) +
   1187		sizeof(struct vmw_stdu_update);
   1188}
   1189
   1190static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update,
   1191					  uint32_t num_hits)
   1192{
   1193	return sizeof(struct vmw_stdu_update_gb_image) +
   1194		sizeof(struct vmw_stdu_update);
   1195}
   1196
   1197static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane  *update,
   1198					 void *cmd, uint32_t num_hits)
   1199{
   1200	struct vmw_screen_target_display_unit *stdu;
   1201	struct vmw_framebuffer_bo *vfbbo;
   1202	struct vmw_stdu_dma *cmd_dma = cmd;
   1203
   1204	stdu = container_of(update->du, typeof(*stdu), base);
   1205	vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
   1206
   1207	cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA;
   1208	cmd_dma->header.size = sizeof(cmd_dma->body) +
   1209		sizeof(struct SVGA3dCopyBox) * num_hits +
   1210		sizeof(SVGA3dCmdSurfaceDMASuffix);
   1211	vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr);
   1212	cmd_dma->body.guest.pitch = update->vfb->base.pitches[0];
   1213	cmd_dma->body.host.sid = stdu->display_srf->res.id;
   1214	cmd_dma->body.host.face = 0;
   1215	cmd_dma->body.host.mipmap = 0;
   1216	cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM;
   1217
   1218	return sizeof(*cmd_dma);
   1219}
   1220
   1221static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane  *update,
   1222					  void *cmd, struct drm_rect *clip,
   1223					  uint32_t fb_x, uint32_t fb_y)
   1224{
   1225	struct SVGA3dCopyBox *box = cmd;
   1226
   1227	box->srcx = fb_x;
   1228	box->srcy = fb_y;
   1229	box->srcz = 0;
   1230	box->x = clip->x1;
   1231	box->y = clip->y1;
   1232	box->z = 0;
   1233	box->w = drm_rect_width(clip);
   1234	box->h = drm_rect_height(clip);
   1235	box->d = 1;
   1236
   1237	return sizeof(*box);
   1238}
   1239
   1240static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane  *update,
   1241					    void *cmd, struct drm_rect *bb)
   1242{
   1243	struct vmw_screen_target_display_unit *stdu;
   1244	struct vmw_framebuffer_bo *vfbbo;
   1245	SVGA3dCmdSurfaceDMASuffix *suffix = cmd;
   1246
   1247	stdu = container_of(update->du, typeof(*stdu), base);
   1248	vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
   1249
   1250	suffix->suffixSize = sizeof(*suffix);
   1251	suffix->maximumOffset = vfbbo->buffer->base.base.size;
   1252
   1253	vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2,
   1254				 bb->y1, bb->y2);
   1255
   1256	return sizeof(*suffix) + sizeof(struct vmw_stdu_update);
   1257}
   1258
   1259static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane  *update,
   1260					 void *cmd, uint32_t num_hits)
   1261{
   1262	struct vmw_du_update_plane_buffer *bo_update =
   1263		container_of(update, typeof(*bo_update), base);
   1264
   1265	bo_update->fb_left = INT_MAX;
   1266	bo_update->fb_top = INT_MAX;
   1267
   1268	return 0;
   1269}
   1270
   1271static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane  *update,
   1272				     void *cmd, struct drm_rect *clip,
   1273				     uint32_t fb_x, uint32_t fb_y)
   1274{
   1275	struct vmw_du_update_plane_buffer *bo_update =
   1276		container_of(update, typeof(*bo_update), base);
   1277
   1278	bo_update->fb_left = min_t(int, bo_update->fb_left, fb_x);
   1279	bo_update->fb_top = min_t(int, bo_update->fb_top, fb_y);
   1280
   1281	return 0;
   1282}
   1283
   1284static uint32_t
   1285vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
   1286				struct drm_rect *bb)
   1287{
   1288	struct vmw_du_update_plane_buffer *bo_update;
   1289	struct vmw_screen_target_display_unit *stdu;
   1290	struct vmw_framebuffer_bo *vfbbo;
   1291	struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
   1292	struct vmw_stdu_update_gb_image *cmd_img = cmd;
   1293	struct vmw_stdu_update *cmd_update;
   1294	struct ttm_buffer_object *src_bo, *dst_bo;
   1295	u32 src_offset, dst_offset;
   1296	s32 src_pitch, dst_pitch;
   1297	s32 width, height;
   1298
   1299	bo_update = container_of(update, typeof(*bo_update), base);
   1300	stdu = container_of(update->du, typeof(*stdu), base);
   1301	vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
   1302
   1303	width = bb->x2 - bb->x1;
   1304	height = bb->y2 - bb->y1;
   1305
   1306	diff.cpp = stdu->cpp;
   1307
   1308	dst_bo = &stdu->display_srf->res.backup->base;
   1309	dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
   1310	dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp;
   1311
   1312	src_bo = &vfbbo->buffer->base;
   1313	src_pitch = update->vfb->base.pitches[0];
   1314	src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left *
   1315		stdu->cpp;
   1316
   1317	(void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, src_bo,
   1318			       src_offset, src_pitch, width * stdu->cpp, height,
   1319			       &diff);
   1320
   1321	if (drm_rect_visible(&diff.rect)) {
   1322		SVGA3dBox *box = &cmd_img->body.box;
   1323
   1324		cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
   1325		cmd_img->header.size = sizeof(cmd_img->body);
   1326		cmd_img->body.image.sid = stdu->display_srf->res.id;
   1327		cmd_img->body.image.face = 0;
   1328		cmd_img->body.image.mipmap = 0;
   1329
   1330		box->x = diff.rect.x1;
   1331		box->y = diff.rect.y1;
   1332		box->z = 0;
   1333		box->w = drm_rect_width(&diff.rect);
   1334		box->h = drm_rect_height(&diff.rect);
   1335		box->d = 1;
   1336
   1337		cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
   1338		vmw_stdu_populate_update(cmd_update, stdu->base.unit,
   1339					 diff.rect.x1, diff.rect.x2,
   1340					 diff.rect.y1, diff.rect.y2);
   1341
   1342		return sizeof(*cmd_img) + sizeof(*cmd_update);
   1343	}
   1344
   1345	return 0;
   1346}
   1347
   1348/**
   1349 * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
   1350 * @dev_priv: device private.
   1351 * @plane: plane state.
   1352 * @old_state: old plane state.
   1353 * @vfb: framebuffer which is blitted to display unit.
   1354 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
   1355 *             The returned fence pointer may be NULL in which case the device
   1356 *             has already synchronized.
   1357 *
   1358 * Return: 0 on success or a negative error code on failure.
   1359 */
   1360static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv,
   1361				    struct drm_plane *plane,
   1362				    struct drm_plane_state *old_state,
   1363				    struct vmw_framebuffer *vfb,
   1364				    struct vmw_fence_obj **out_fence)
   1365{
   1366	struct vmw_du_update_plane_buffer bo_update;
   1367
   1368	memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
   1369	bo_update.base.plane = plane;
   1370	bo_update.base.old_state = old_state;
   1371	bo_update.base.dev_priv = dev_priv;
   1372	bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
   1373	bo_update.base.vfb = vfb;
   1374	bo_update.base.out_fence = out_fence;
   1375	bo_update.base.mutex = NULL;
   1376	bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv);
   1377	bo_update.base.intr = false;
   1378
   1379	/*
   1380	 * VM without 3D support don't have surface DMA command and framebuffer
   1381	 * should be moved out of VRAM.
   1382	 */
   1383	if (bo_update.base.cpu_blit) {
   1384		bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
   1385		bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
   1386		bo_update.base.clip = vmw_stdu_bo_clip_cpu;
   1387		bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu;
   1388	} else {
   1389		bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size;
   1390		bo_update.base.pre_clip = vmw_stdu_bo_populate_dma;
   1391		bo_update.base.clip = vmw_stdu_bo_populate_clip;
   1392		bo_update.base.post_clip = vmw_stdu_bo_populate_update;
   1393	}
   1394
   1395	return vmw_du_helper_plane_update(&bo_update.base);
   1396}
   1397
   1398static uint32_t
   1399vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update,
   1400					uint32_t num_hits)
   1401{
   1402	struct vmw_framebuffer_surface *vfbs;
   1403	uint32_t size = 0;
   1404
   1405	vfbs = container_of(update->vfb, typeof(*vfbs), base);
   1406
   1407	if (vfbs->is_bo_proxy)
   1408		size += sizeof(struct vmw_stdu_update_gb_image) * num_hits;
   1409
   1410	size += sizeof(struct vmw_stdu_update);
   1411
   1412	return size;
   1413}
   1414
   1415static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update,
   1416					   uint32_t num_hits)
   1417{
   1418	struct vmw_framebuffer_surface *vfbs;
   1419	uint32_t size = 0;
   1420
   1421	vfbs = container_of(update->vfb, typeof(*vfbs), base);
   1422
   1423	if (vfbs->is_bo_proxy)
   1424		size += sizeof(struct vmw_stdu_update_gb_image) * num_hits;
   1425
   1426	size += sizeof(struct vmw_stdu_surface_copy) + sizeof(SVGA3dCopyBox) *
   1427		num_hits + sizeof(struct vmw_stdu_update);
   1428
   1429	return size;
   1430}
   1431
   1432static uint32_t
   1433vmw_stdu_surface_update_proxy(struct vmw_du_update_plane *update, void *cmd)
   1434{
   1435	struct vmw_framebuffer_surface *vfbs;
   1436	struct drm_plane_state *state = update->plane->state;
   1437	struct drm_plane_state *old_state = update->old_state;
   1438	struct vmw_stdu_update_gb_image *cmd_update = cmd;
   1439	struct drm_atomic_helper_damage_iter iter;
   1440	struct drm_rect clip;
   1441	uint32_t copy_size = 0;
   1442
   1443	vfbs = container_of(update->vfb, typeof(*vfbs), base);
   1444
   1445	/*
   1446	 * proxy surface is special where a buffer object type fb is wrapped
   1447	 * in a surface and need an update gb image command to sync with device.
   1448	 */
   1449	drm_atomic_helper_damage_iter_init(&iter, old_state, state);
   1450	drm_atomic_for_each_plane_damage(&iter, &clip) {
   1451		SVGA3dBox *box = &cmd_update->body.box;
   1452
   1453		cmd_update->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
   1454		cmd_update->header.size = sizeof(cmd_update->body);
   1455		cmd_update->body.image.sid = vfbs->surface->res.id;
   1456		cmd_update->body.image.face = 0;
   1457		cmd_update->body.image.mipmap = 0;
   1458
   1459		box->x = clip.x1;
   1460		box->y = clip.y1;
   1461		box->z = 0;
   1462		box->w = drm_rect_width(&clip);
   1463		box->h = drm_rect_height(&clip);
   1464		box->d = 1;
   1465
   1466		copy_size += sizeof(*cmd_update);
   1467		cmd_update++;
   1468	}
   1469
   1470	return copy_size;
   1471}
   1472
   1473static uint32_t
   1474vmw_stdu_surface_populate_copy(struct vmw_du_update_plane  *update, void *cmd,
   1475			       uint32_t num_hits)
   1476{
   1477	struct vmw_screen_target_display_unit *stdu;
   1478	struct vmw_framebuffer_surface *vfbs;
   1479	struct vmw_stdu_surface_copy *cmd_copy = cmd;
   1480
   1481	stdu = container_of(update->du, typeof(*stdu), base);
   1482	vfbs = container_of(update->vfb, typeof(*vfbs), base);
   1483
   1484	cmd_copy->header.id = SVGA_3D_CMD_SURFACE_COPY;
   1485	cmd_copy->header.size = sizeof(cmd_copy->body) + sizeof(SVGA3dCopyBox) *
   1486		num_hits;
   1487	cmd_copy->body.src.sid = vfbs->surface->res.id;
   1488	cmd_copy->body.dest.sid = stdu->display_srf->res.id;
   1489
   1490	return sizeof(*cmd_copy);
   1491}
   1492
   1493static uint32_t
   1494vmw_stdu_surface_populate_clip(struct vmw_du_update_plane  *update, void *cmd,
   1495			       struct drm_rect *clip, uint32_t fb_x,
   1496			       uint32_t fb_y)
   1497{
   1498	struct SVGA3dCopyBox *box = cmd;
   1499
   1500	box->srcx = fb_x;
   1501	box->srcy = fb_y;
   1502	box->srcz = 0;
   1503	box->x = clip->x1;
   1504	box->y = clip->y1;
   1505	box->z = 0;
   1506	box->w = drm_rect_width(clip);
   1507	box->h = drm_rect_height(clip);
   1508	box->d = 1;
   1509
   1510	return sizeof(*box);
   1511}
   1512
   1513static uint32_t
   1514vmw_stdu_surface_populate_update(struct vmw_du_update_plane  *update, void *cmd,
   1515				 struct drm_rect *bb)
   1516{
   1517	vmw_stdu_populate_update(cmd, update->du->unit, bb->x1, bb->x2, bb->y1,
   1518				 bb->y2);
   1519
   1520	return sizeof(struct vmw_stdu_update);
   1521}
   1522
   1523/**
   1524 * vmw_stdu_plane_update_surface - Update display unit for surface backed fb
   1525 * @dev_priv: Device private
   1526 * @plane: Plane state
   1527 * @old_state: Old plane state
   1528 * @vfb: Framebuffer which is blitted to display unit
   1529 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
   1530 *             The returned fence pointer may be NULL in which case the device
   1531 *             has already synchronized.
   1532 *
   1533 * Return: 0 on success or a negative error code on failure.
   1534 */
   1535static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv,
   1536					 struct drm_plane *plane,
   1537					 struct drm_plane_state *old_state,
   1538					 struct vmw_framebuffer *vfb,
   1539					 struct vmw_fence_obj **out_fence)
   1540{
   1541	struct vmw_du_update_plane srf_update;
   1542	struct vmw_screen_target_display_unit *stdu;
   1543	struct vmw_framebuffer_surface *vfbs;
   1544
   1545	stdu = vmw_crtc_to_stdu(plane->state->crtc);
   1546	vfbs = container_of(vfb, typeof(*vfbs), base);
   1547
   1548	memset(&srf_update, 0, sizeof(struct vmw_du_update_plane));
   1549	srf_update.plane = plane;
   1550	srf_update.old_state = old_state;
   1551	srf_update.dev_priv = dev_priv;
   1552	srf_update.du = vmw_crtc_to_du(plane->state->crtc);
   1553	srf_update.vfb = vfb;
   1554	srf_update.out_fence = out_fence;
   1555	srf_update.mutex = &dev_priv->cmdbuf_mutex;
   1556	srf_update.cpu_blit = false;
   1557	srf_update.intr = true;
   1558
   1559	if (vfbs->is_bo_proxy)
   1560		srf_update.post_prepare = vmw_stdu_surface_update_proxy;
   1561
   1562	if (vfbs->surface->res.id != stdu->display_srf->res.id) {
   1563		srf_update.calc_fifo_size = vmw_stdu_surface_fifo_size;
   1564		srf_update.pre_clip = vmw_stdu_surface_populate_copy;
   1565		srf_update.clip = vmw_stdu_surface_populate_clip;
   1566	} else {
   1567		srf_update.calc_fifo_size =
   1568			vmw_stdu_surface_fifo_size_same_display;
   1569	}
   1570
   1571	srf_update.post_clip = vmw_stdu_surface_populate_update;
   1572
   1573	return vmw_du_helper_plane_update(&srf_update);
   1574}
   1575
   1576/**
   1577 * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane
   1578 * @plane: display plane
   1579 * @state: Only used to get crtc info
   1580 *
   1581 * Formally update stdu->display_srf to the new plane, and bind the new
   1582 * plane STDU.  This function is called during the commit phase when
   1583 * all the preparation have been done and all the configurations have
   1584 * been checked.
   1585 */
   1586static void
   1587vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
   1588				     struct drm_atomic_state *state)
   1589{
   1590	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
   1591	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
   1592	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
   1593	struct drm_crtc *crtc = new_state->crtc;
   1594	struct vmw_screen_target_display_unit *stdu;
   1595	struct drm_pending_vblank_event *event;
   1596	struct vmw_fence_obj *fence = NULL;
   1597	struct vmw_private *dev_priv;
   1598	int ret;
   1599
   1600	/* If case of device error, maintain consistent atomic state */
   1601	if (crtc && new_state->fb) {
   1602		struct vmw_framebuffer *vfb =
   1603			vmw_framebuffer_to_vfb(new_state->fb);
   1604		stdu = vmw_crtc_to_stdu(crtc);
   1605		dev_priv = vmw_priv(crtc->dev);
   1606
   1607		stdu->display_srf = vps->surf;
   1608		stdu->content_fb_type = vps->content_fb_type;
   1609		stdu->cpp = vps->cpp;
   1610
   1611		ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
   1612		if (ret)
   1613			DRM_ERROR("Failed to bind surface to STDU.\n");
   1614
   1615		if (vfb->bo)
   1616			ret = vmw_stdu_plane_update_bo(dev_priv, plane,
   1617						       old_state, vfb, &fence);
   1618		else
   1619			ret = vmw_stdu_plane_update_surface(dev_priv, plane,
   1620							    old_state, vfb,
   1621							    &fence);
   1622		if (ret)
   1623			DRM_ERROR("Failed to update STDU.\n");
   1624	} else {
   1625		crtc = old_state->crtc;
   1626		stdu = vmw_crtc_to_stdu(crtc);
   1627		dev_priv = vmw_priv(crtc->dev);
   1628
   1629		/* Blank STDU when fb and crtc are NULL */
   1630		if (!stdu->defined)
   1631			return;
   1632
   1633		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
   1634		if (ret)
   1635			DRM_ERROR("Failed to blank STDU\n");
   1636
   1637		ret = vmw_stdu_update_st(dev_priv, stdu);
   1638		if (ret)
   1639			DRM_ERROR("Failed to update STDU.\n");
   1640
   1641		return;
   1642	}
   1643
   1644	/* In case of error, vblank event is send in vmw_du_crtc_atomic_flush */
   1645	event = crtc->state->event;
   1646	if (event && fence) {
   1647		struct drm_file *file_priv = event->base.file_priv;
   1648
   1649		ret = vmw_event_fence_action_queue(file_priv,
   1650						   fence,
   1651						   &event->base,
   1652						   &event->event.vbl.tv_sec,
   1653						   &event->event.vbl.tv_usec,
   1654						   true);
   1655		if (ret)
   1656			DRM_ERROR("Failed to queue event on fence.\n");
   1657		else
   1658			crtc->state->event = NULL;
   1659	}
   1660
   1661	if (fence)
   1662		vmw_fence_obj_unreference(&fence);
   1663}
   1664
   1665
   1666static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
   1667	.update_plane = drm_atomic_helper_update_plane,
   1668	.disable_plane = drm_atomic_helper_disable_plane,
   1669	.destroy = vmw_du_primary_plane_destroy,
   1670	.reset = vmw_du_plane_reset,
   1671	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
   1672	.atomic_destroy_state = vmw_du_plane_destroy_state,
   1673};
   1674
   1675static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
   1676	.update_plane = drm_atomic_helper_update_plane,
   1677	.disable_plane = drm_atomic_helper_disable_plane,
   1678	.destroy = vmw_du_cursor_plane_destroy,
   1679	.reset = vmw_du_plane_reset,
   1680	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
   1681	.atomic_destroy_state = vmw_du_plane_destroy_state,
   1682};
   1683
   1684
   1685/*
   1686 * Atomic Helpers
   1687 */
   1688static const struct
   1689drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs = {
   1690	.atomic_check = vmw_du_cursor_plane_atomic_check,
   1691	.atomic_update = vmw_du_cursor_plane_atomic_update,
   1692	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
   1693	.cleanup_fb = vmw_du_cursor_plane_cleanup_fb,
   1694};
   1695
   1696static const struct
   1697drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
   1698	.atomic_check = vmw_du_primary_plane_atomic_check,
   1699	.atomic_update = vmw_stdu_primary_plane_atomic_update,
   1700	.prepare_fb = vmw_stdu_primary_plane_prepare_fb,
   1701	.cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
   1702};
   1703
   1704static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
   1705	.prepare = vmw_stdu_crtc_helper_prepare,
   1706	.mode_set_nofb = vmw_stdu_crtc_mode_set_nofb,
   1707	.atomic_check = vmw_du_crtc_atomic_check,
   1708	.atomic_begin = vmw_du_crtc_atomic_begin,
   1709	.atomic_flush = vmw_du_crtc_atomic_flush,
   1710	.atomic_enable = vmw_stdu_crtc_atomic_enable,
   1711	.atomic_disable = vmw_stdu_crtc_atomic_disable,
   1712};
   1713
   1714
   1715/**
   1716 * vmw_stdu_init - Sets up a Screen Target Display Unit
   1717 *
   1718 * @dev_priv: VMW DRM device
   1719 * @unit: unit number range from 0 to VMWGFX_NUM_DISPLAY_UNITS
   1720 *
   1721 * This function is called once per CRTC, and allocates one Screen Target
   1722 * display unit to represent that CRTC.  Since the SVGA device does not separate
   1723 * out encoder and connector, they are represented as part of the STDU as well.
   1724 */
   1725static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
   1726{
   1727	struct vmw_screen_target_display_unit *stdu;
   1728	struct drm_device *dev = &dev_priv->drm;
   1729	struct drm_connector *connector;
   1730	struct drm_encoder *encoder;
   1731	struct drm_plane *primary;
   1732	struct vmw_cursor_plane *cursor;
   1733	struct drm_crtc *crtc;
   1734	int    ret;
   1735
   1736	stdu = kzalloc(sizeof(*stdu), GFP_KERNEL);
   1737	if (!stdu)
   1738		return -ENOMEM;
   1739
   1740	stdu->base.unit = unit;
   1741	crtc = &stdu->base.crtc;
   1742	encoder = &stdu->base.encoder;
   1743	connector = &stdu->base.connector;
   1744	primary = &stdu->base.primary;
   1745	cursor = &stdu->base.cursor;
   1746
   1747	stdu->base.pref_active = (unit == 0);
   1748	stdu->base.pref_width  = dev_priv->initial_width;
   1749	stdu->base.pref_height = dev_priv->initial_height;
   1750	stdu->base.is_implicit = false;
   1751
   1752	/* Initialize primary plane */
   1753	ret = drm_universal_plane_init(dev, primary,
   1754				       0, &vmw_stdu_plane_funcs,
   1755				       vmw_primary_plane_formats,
   1756				       ARRAY_SIZE(vmw_primary_plane_formats),
   1757				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
   1758	if (ret) {
   1759		DRM_ERROR("Failed to initialize primary plane");
   1760		goto err_free;
   1761	}
   1762
   1763	drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs);
   1764	drm_plane_enable_fb_damage_clips(primary);
   1765
   1766	/* Initialize cursor plane */
   1767	ret = drm_universal_plane_init(dev, &cursor->base,
   1768			0, &vmw_stdu_cursor_funcs,
   1769			vmw_cursor_plane_formats,
   1770			ARRAY_SIZE(vmw_cursor_plane_formats),
   1771			NULL, DRM_PLANE_TYPE_CURSOR, NULL);
   1772	if (ret) {
   1773		DRM_ERROR("Failed to initialize cursor plane");
   1774		drm_plane_cleanup(&stdu->base.primary);
   1775		goto err_free;
   1776	}
   1777
   1778	drm_plane_helper_add(&cursor->base, &vmw_stdu_cursor_plane_helper_funcs);
   1779
   1780	ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
   1781				 DRM_MODE_CONNECTOR_VIRTUAL);
   1782	if (ret) {
   1783		DRM_ERROR("Failed to initialize connector\n");
   1784		goto err_free;
   1785	}
   1786
   1787	drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs);
   1788	connector->status = vmw_du_connector_detect(connector, false);
   1789
   1790	ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
   1791			       DRM_MODE_ENCODER_VIRTUAL, NULL);
   1792	if (ret) {
   1793		DRM_ERROR("Failed to initialize encoder\n");
   1794		goto err_free_connector;
   1795	}
   1796
   1797	(void) drm_connector_attach_encoder(connector, encoder);
   1798	encoder->possible_crtcs = (1 << unit);
   1799	encoder->possible_clones = 0;
   1800
   1801	ret = drm_connector_register(connector);
   1802	if (ret) {
   1803		DRM_ERROR("Failed to register connector\n");
   1804		goto err_free_encoder;
   1805	}
   1806
   1807	ret = drm_crtc_init_with_planes(dev, crtc, primary,
   1808					&cursor->base,
   1809					&vmw_stdu_crtc_funcs, NULL);
   1810	if (ret) {
   1811		DRM_ERROR("Failed to initialize CRTC\n");
   1812		goto err_free_unregister;
   1813	}
   1814
   1815	drm_crtc_helper_add(crtc, &vmw_stdu_crtc_helper_funcs);
   1816
   1817	drm_mode_crtc_set_gamma_size(crtc, 256);
   1818
   1819	drm_object_attach_property(&connector->base,
   1820				   dev_priv->hotplug_mode_update_property, 1);
   1821	drm_object_attach_property(&connector->base,
   1822				   dev->mode_config.suggested_x_property, 0);
   1823	drm_object_attach_property(&connector->base,
   1824				   dev->mode_config.suggested_y_property, 0);
   1825	return 0;
   1826
   1827err_free_unregister:
   1828	drm_connector_unregister(connector);
   1829err_free_encoder:
   1830	drm_encoder_cleanup(encoder);
   1831err_free_connector:
   1832	drm_connector_cleanup(connector);
   1833err_free:
   1834	kfree(stdu);
   1835	return ret;
   1836}
   1837
   1838
   1839
   1840/**
   1841 *  vmw_stdu_destroy - Cleans up a vmw_screen_target_display_unit
   1842 *
   1843 *  @stdu:  Screen Target Display Unit to be destroyed
   1844 *
   1845 *  Clean up after vmw_stdu_init
   1846 */
   1847static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu)
   1848{
   1849	vmw_du_cleanup(&stdu->base);
   1850	kfree(stdu);
   1851}
   1852
   1853
   1854
   1855/******************************************************************************
   1856 * Screen Target Display KMS Functions
   1857 *
   1858 * These functions are called by the common KMS code in vmwgfx_kms.c
   1859 *****************************************************************************/
   1860
   1861/**
   1862 * vmw_kms_stdu_init_display - Initializes a Screen Target based display
   1863 *
   1864 * @dev_priv: VMW DRM device
   1865 *
   1866 * This function initialize a Screen Target based display device.  It checks
   1867 * the capability bits to make sure the underlying hardware can support
   1868 * screen targets, and then creates the maximum number of CRTCs, a.k.a Display
   1869 * Units, as supported by the display hardware.
   1870 *
   1871 * RETURNS:
   1872 * 0 on success, error code otherwise
   1873 */
   1874int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
   1875{
   1876	struct drm_device *dev = &dev_priv->drm;
   1877	int i, ret;
   1878
   1879
   1880	/* Do nothing if there's no support for MOBs */
   1881	if (!dev_priv->has_mob)
   1882		return -ENOSYS;
   1883
   1884	if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
   1885		return -ENOSYS;
   1886
   1887	ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
   1888	if (unlikely(ret != 0))
   1889		return ret;
   1890
   1891	dev_priv->active_display_unit = vmw_du_screen_target;
   1892
   1893	for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) {
   1894		ret = vmw_stdu_init(dev_priv, i);
   1895
   1896		if (unlikely(ret != 0)) {
   1897			drm_err(&dev_priv->drm,
   1898				"Failed to initialize STDU %d", i);
   1899			return ret;
   1900		}
   1901	}
   1902
   1903	drm_mode_config_reset(dev);
   1904
   1905	return 0;
   1906}