linux/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c

// SPDX-License-Identifier: GPL-2.0 OR MIT
/******************************************************************************
 *
 * Copyright (c) 2014-2024 Broadcom. All Rights Reserved. The term
 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 ******************************************************************************/

#include "vmwgfx_bo.h"
#include "vmwgfx_kms.h"
#include "vmwgfx_vkms.h"
#include "vmw_surface_cache.h"
#include <linux/fsnotify.h>

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>

#define vmw_crtc_to_stdu(x)
#define vmw_encoder_to_stdu(x)
#define vmw_connector_to_stdu(x)

/*
 * Some renderers such as llvmpipe will align the width and height of their
 * buffers to match their tile size. We need to keep this in mind when exposing
 * modes to userspace so that this possible over-allocation will not exceed
 * graphics memory. 64x64 pixels seems to be a reasonable upper bound for the
 * tile size of current renderers.
 */
#define GPU_TILE_SIZE

enum stdu_content_type {};

/**
 * struct vmw_stdu_dirty - closure structure for the update functions
 *
 * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
 * @left: Left side of bounding box.
 * @right: Right side of bounding box.
 * @top: Top side of bounding box.
 * @bottom: Bottom side of bounding box.
 * @fb_left: Left side of the framebuffer/content bounding box
 * @fb_top: Top of the framebuffer/content bounding box
 * @pitch: framebuffer pitch (stride)
 * @buf: buffer object when DMA-ing between buffer and screen targets.
 * @sid: Surface ID when copying between surface and screen targets.
 */
struct vmw_stdu_dirty {};

/*
 * SVGA commands that are used by this code. Please see the device headers
 * for explanation.
 */
struct vmw_stdu_update {};

struct vmw_stdu_surface_copy {};

struct vmw_stdu_update_gb_image {};

/**
 * struct vmw_screen_target_display_unit - conglomerated STDU structure
 *
 * @base: VMW specific DU structure
 * @display_srf: surface to be displayed.  The dimension of this will always
 *               match the display mode.  If the display mode matches
 *               content_vfbs dimensions, then this is a pointer into the
 *               corresponding field in content_vfbs.  If not, then this
 *               is a separate buffer to which content_vfbs will blit to.
 * @content_fb_type: content_fb type
 * @display_width:  display width
 * @display_height: display height
 * @defined:     true if the current display unit has been initialized
 * @cpp:         Bytes per pixel
 */
struct vmw_screen_target_display_unit {};



static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu);



/******************************************************************************
 * Screen Target Display Unit CRTC Functions
 *****************************************************************************/

/**
 * vmw_stdu_crtc_destroy - cleans up the STDU
 *
 * @crtc: used to get a reference to the containing STDU
 */
static void vmw_stdu_crtc_destroy(struct drm_crtc *crtc)
{}

/**
 * vmw_stdu_define_st - Defines a Screen Target
 *
 * @dev_priv:  VMW DRM device
 * @stdu: display unit to create a Screen Target for
 * @mode: The mode to set.
 * @crtc_x: X coordinate of screen target relative to framebuffer origin.
 * @crtc_y: Y coordinate of screen target relative to framebuffer origin.
 *
 * Creates a STDU that we can used later.  This function is called whenever the
 * framebuffer size changes.
 *
 * RETURNs:
 * 0 on success, error code on failure
 */
static int vmw_stdu_define_st(struct vmw_private *dev_priv,
			      struct vmw_screen_target_display_unit *stdu,
			      struct drm_display_mode *mode,
			      int crtc_x, int crtc_y)
{}



/**
 * vmw_stdu_bind_st - Binds a surface to a Screen Target
 *
 * @dev_priv: VMW DRM device
 * @stdu: display unit affected
 * @res: Buffer to bind to the screen target.  Set to NULL to blank screen.
 *
 * Binding a surface to a Screen Target the same as flipping
 *
 * Returns: %0 on success or -errno code on failure
 */
static int vmw_stdu_bind_st(struct vmw_private *dev_priv,
			    struct vmw_screen_target_display_unit *stdu,
			    const struct vmw_resource *res)
{}

/**
 * vmw_stdu_populate_update - populate an UPDATE_GB_SCREENTARGET command with a
 * bounding box.
 *
 * @cmd: Pointer to command stream.
 * @unit: Screen target unit.
 * @left: Left side of bounding box.
 * @right: Right side of bounding box.
 * @top: Top side of bounding box.
 * @bottom: Bottom side of bounding box.
 */
static void vmw_stdu_populate_update(void *cmd, int unit,
				     s32 left, s32 right, s32 top, s32 bottom)
{}

/**
 * vmw_stdu_update_st - Full update of a Screen Target
 *
 * @dev_priv: VMW DRM device
 * @stdu: display unit affected
 *
 * This function needs to be called whenever the content of a screen
 * target has changed completely. Typically as a result of a backing
 * surface change.
 *
 * RETURNS:
 * 0 on success, error code on failure
 */
static int vmw_stdu_update_st(struct vmw_private *dev_priv,
			      struct vmw_screen_target_display_unit *stdu)
{}



/**
 * vmw_stdu_destroy_st - Destroy a Screen Target
 *
 * @dev_priv:  VMW DRM device
 * @stdu: display unit to destroy
 *
 * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
 * interrupted.
 */
static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
			       struct vmw_screen_target_display_unit *stdu)
{}


/**
 * vmw_stdu_crtc_mode_set_nofb - Updates screen target size
 *
 * @crtc: CRTC associated with the screen target
 *
 * This function defines/destroys a screen target
 *
 */
static void vmw_stdu_crtc_mode_set_nofb(struct drm_crtc *crtc)
{}

static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
					 struct drm_atomic_state *state)
{}

/**
 * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit
 *
 * @dirty: The closure structure.
 *
 * This function calculates the bounding box for all the incoming clips.
 */
static void vmw_stdu_bo_cpu_clip(struct vmw_kms_dirty *dirty)
{}


/**
 * vmw_stdu_bo_cpu_commit - Callback to do a CPU blit from buffer object
 *
 * @dirty: The closure structure.
 *
 * For the special case when we cannot create a proxy surface in a
 * 2D VM, we have to do a CPU blit ourselves.
 */
static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty)
{}

/**
 * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed
 * framebuffer and the screen target system.
 *
 * @dev_priv: Pointer to the device private structure.
 * @file_priv: Pointer to a struct drm-file identifying the caller. May be
 * set to NULL, but then @user_fence_rep must also be set to NULL.
 * @vfb: Pointer to the buffer-object backed framebuffer.
 * @user_fence_rep: User-space provided structure for fence information.
 * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
 * @vclips: Alternate array of clip rects. Either @clips or @vclips must
 * be NULL.
 * @num_clips: Number of clip rects in @clips or @vclips.
 * @increment: Increment to use when looping over @clips or @vclips.
 * @crtc: If crtc is passed, perform stdu dma on that crtc only.
 *
 * If DMA-ing till the screen target system, the function will also notify
 * the screen target system that a bounding box of the cliprects has been
 * updated.
 *
 * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
 * interrupted.
 */
int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
			  struct drm_file *file_priv,
			  struct vmw_framebuffer *vfb,
			  struct drm_vmw_fence_rep __user *user_fence_rep,
			  struct drm_clip_rect *clips,
			  struct drm_vmw_rect *vclips,
			  uint32_t num_clips,
			  int increment,
			  struct drm_crtc *crtc)
{}

/**
 * vmw_kms_stdu_surface_clip - Callback to encode a surface copy command cliprect
 *
 * @dirty: The closure structure.
 *
 * Encodes a surface copy command cliprect and updates the bounding box
 * for the copy.
 */
static void vmw_kms_stdu_surface_clip(struct vmw_kms_dirty *dirty)
{}

/**
 * vmw_kms_stdu_surface_fifo_commit - Callback to fill in and submit a surface
 * copy command.
 *
 * @dirty: The closure structure.
 *
 * Fills in the missing fields in a surface copy command, and encodes a screen
 * target update command.
 */
static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty)
{}

/**
 * vmw_kms_stdu_surface_dirty - Dirty part of a surface backed framebuffer
 *
 * @dev_priv: Pointer to the device private structure.
 * @framebuffer: Pointer to the surface-buffer backed framebuffer.
 * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
 * @vclips: Alternate array of clip rects. Either @clips or @vclips must
 * be NULL.
 * @srf: Pointer to surface to blit from. If NULL, the surface attached
 * to @framebuffer will be used.
 * @dest_x: X coordinate offset to align @srf with framebuffer coordinates.
 * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates.
 * @num_clips: Number of clip rects in @clips.
 * @inc: Increment to use when looping over @clips.
 * @out_fence: If non-NULL, will return a ref-counted pointer to a
 * struct vmw_fence_obj. The returned fence pointer may be NULL in which
 * case the device has already synchronized.
 * @crtc: If crtc is passed, perform surface dirty on that crtc only.
 *
 * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
 * interrupted.
 */
int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
			       struct vmw_framebuffer *framebuffer,
			       struct drm_clip_rect *clips,
			       struct drm_vmw_rect *vclips,
			       struct vmw_resource *srf,
			       s32 dest_x,
			       s32 dest_y,
			       unsigned num_clips, int inc,
			       struct vmw_fence_obj **out_fence,
			       struct drm_crtc *crtc)
{}

/*
 *  Screen Target CRTC dispatch table
 */
static const struct drm_crtc_funcs vmw_stdu_crtc_funcs =;



/******************************************************************************
 * Screen Target Display Unit Encoder Functions
 *****************************************************************************/

/**
 * vmw_stdu_encoder_destroy - cleans up the STDU
 *
 * @encoder: used the get the containing STDU
 *
 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
 * this can be a no-op.  Nevertheless, it doesn't hurt of have this in case
 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
 * get called.
 */
static void vmw_stdu_encoder_destroy(struct drm_encoder *encoder)
{}

static const struct drm_encoder_funcs vmw_stdu_encoder_funcs =;



/******************************************************************************
 * Screen Target Display Unit Connector Functions
 *****************************************************************************/

/**
 * vmw_stdu_connector_destroy - cleans up the STDU
 *
 * @connector: used to get the containing STDU
 *
 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
 * this can be a no-op.  Nevertheless, it doesn't hurt of have this in case
 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
 * get called.
 */
static void vmw_stdu_connector_destroy(struct drm_connector *connector)
{}

static enum drm_mode_status
vmw_stdu_connector_mode_valid(struct drm_connector *connector,
			      struct drm_display_mode *mode)
{}

/*
 * Trigger a modeset if the X,Y position of the Screen Target changes.
 * This is needed when multi-mon is cycled. The original Screen Target will have
 * the same mode but its relative X,Y position in the topology will change.
 */
static int vmw_stdu_connector_atomic_check(struct drm_connector *conn,
					   struct drm_atomic_state *state)
{}

static const struct drm_connector_funcs vmw_stdu_connector_funcs =;


static const struct
drm_connector_helper_funcs vmw_stdu_connector_helper_funcs =;



/******************************************************************************
 * Screen Target Display Plane Functions
 *****************************************************************************/



/**
 * vmw_stdu_primary_plane_cleanup_fb - Unpins the display surface
 *
 * @plane:  display plane
 * @old_state: Contains the FB to clean up
 *
 * Unpins the display surface
 *
 * Returns 0 on success
 */
static void
vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
				  struct drm_plane_state *old_state)
{}


/**
 * vmw_stdu_primary_plane_prepare_fb - Readies the display surface
 *
 * @plane:  display plane
 * @new_state: info on the new plane state, including the FB
 *
 * This function allocates a new display surface if the content is
 * backed by a buffer object.  The display surface is pinned here, and it'll
 * be unpinned in .cleanup_fb()
 *
 * Returns: %0 on success
 */
static int
vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
				  struct drm_plane_state *new_state)
{}

static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update,
					  uint32_t num_hits)
{}

static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane  *update,
					 void *cmd, uint32_t num_hits)
{}

static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane  *update,
				     void *cmd, struct drm_rect *clip,
				     uint32_t fb_x, uint32_t fb_y)
{}

static uint32_t
vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
				struct drm_rect *bb)
{}

/**
 * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
 * @dev_priv: device private.
 * @plane: plane state.
 * @old_state: old plane state.
 * @vfb: framebuffer which is blitted to display unit.
 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
 *             The returned fence pointer may be NULL in which case the device
 *             has already synchronized.
 *
 * Return: 0 on success or a negative error code on failure.
 */
static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv,
				    struct drm_plane *plane,
				    struct drm_plane_state *old_state,
				    struct vmw_framebuffer *vfb,
				    struct vmw_fence_obj **out_fence)
{}

static uint32_t
vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update,
					uint32_t num_hits)
{}

static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update,
					   uint32_t num_hits)
{}

static uint32_t
vmw_stdu_surface_populate_copy(struct vmw_du_update_plane  *update, void *cmd,
			       uint32_t num_hits)
{}

static uint32_t
vmw_stdu_surface_populate_clip(struct vmw_du_update_plane  *update, void *cmd,
			       struct drm_rect *clip, uint32_t fb_x,
			       uint32_t fb_y)
{}

static uint32_t
vmw_stdu_surface_populate_update(struct vmw_du_update_plane  *update, void *cmd,
				 struct drm_rect *bb)
{}

/**
 * vmw_stdu_plane_update_surface - Update display unit for surface backed fb
 * @dev_priv: Device private
 * @plane: Plane state
 * @old_state: Old plane state
 * @vfb: Framebuffer which is blitted to display unit
 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
 *             The returned fence pointer may be NULL in which case the device
 *             has already synchronized.
 *
 * Return: 0 on success or a negative error code on failure.
 */
static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv,
					 struct drm_plane *plane,
					 struct drm_plane_state *old_state,
					 struct vmw_framebuffer *vfb,
					 struct vmw_fence_obj **out_fence)
{}

/**
 * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane
 * @plane: display plane
 * @state: Only used to get crtc info
 *
 * Formally update stdu->display_srf to the new plane, and bind the new
 * plane STDU.  This function is called during the commit phase when
 * all the preparation have been done and all the configurations have
 * been checked.
 */
static void
vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
				     struct drm_atomic_state *state)
{}

static void
vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc,
			   struct drm_atomic_state *state)
{}

static const struct drm_plane_funcs vmw_stdu_plane_funcs =;

static const struct drm_plane_funcs vmw_stdu_cursor_funcs =;


/*
 * Atomic Helpers
 */
static const struct
drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs =;

static const struct
drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs =;

static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs =;


/**
 * vmw_stdu_init - Sets up a Screen Target Display Unit
 *
 * @dev_priv: VMW DRM device
 * @unit: unit number range from 0 to VMWGFX_NUM_DISPLAY_UNITS
 *
 * This function is called once per CRTC, and allocates one Screen Target
 * display unit to represent that CRTC.  Since the SVGA device does not separate
 * out encoder and connector, they are represented as part of the STDU as well.
 *
 * Returns: %0 on success or -errno code on failure
 */
static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
{}



/**
 *  vmw_stdu_destroy - Cleans up a vmw_screen_target_display_unit
 *
 *  @stdu:  Screen Target Display Unit to be destroyed
 *
 *  Clean up after vmw_stdu_init
 */
static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu)
{}



/******************************************************************************
 * Screen Target Display KMS Functions
 *
 * These functions are called by the common KMS code in vmwgfx_kms.c
 *****************************************************************************/

/**
 * vmw_kms_stdu_init_display - Initializes a Screen Target based display
 *
 * @dev_priv: VMW DRM device
 *
 * This function initialize a Screen Target based display device.  It checks
 * the capability bits to make sure the underlying hardware can support
 * screen targets, and then creates the maximum number of CRTCs, a.k.a Display
 * Units, as supported by the display hardware.
 *
 * RETURNS:
 * 0 on success, error code otherwise
 */
int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
{}