// SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * * Copyright (c) 2011-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 <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_sou(x) … #define vmw_encoder_to_sou(x) … #define vmw_connector_to_sou(x) … /** * struct vmw_kms_sou_surface_dirty - Closure structure for * blit surface to screen command. * @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. * @dst_x: Difference between source clip rects and framebuffer coordinates. * @dst_y: Difference between source clip rects and framebuffer coordinates. * @sid: Surface id of surface to copy from. */ struct vmw_kms_sou_surface_dirty { … }; /* * SVGA commands that are used by this code. Please see the device headers * for explanation. */ struct vmw_kms_sou_readback_blit { … }; struct vmw_kms_sou_bo_blit { … }; struct vmw_kms_sou_dirty_cmd { … }; struct vmw_kms_sou_define_gmrfb { … }; /* * Display unit using screen objects. */ struct vmw_screen_object_unit { … }; static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) { … } /* * Screen Object Display Unit CRTC functions */ static void vmw_sou_crtc_destroy(struct drm_crtc *crtc) { … } /* * Send the fifo command to create a screen. */ static int vmw_sou_fifo_create(struct vmw_private *dev_priv, struct vmw_screen_object_unit *sou, int x, int y, struct drm_display_mode *mode) { … } /* * Send the fifo command to destroy a screen. */ static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv, struct vmw_screen_object_unit *sou) { … } /** * vmw_sou_crtc_mode_set_nofb - Create new screen * * @crtc: CRTC associated with the new screen * * This function creates/destroys a screen. This function cannot fail, so if * somehow we run into a failure, just do the best we can to get out. */ static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc) { … } /** * vmw_sou_crtc_helper_prepare - Noop * * @crtc: CRTC associated with the new screen * * Prepares the CRTC for a mode set, but we don't need to do anything here. */ static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc) { … } /** * vmw_sou_crtc_atomic_disable - Turns off CRTC * * @crtc: CRTC to be turned off * @state: Unused */ static void vmw_sou_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) { … } static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = …; /* * Screen Object Display Unit encoder functions */ static void vmw_sou_encoder_destroy(struct drm_encoder *encoder) { … } static const struct drm_encoder_funcs vmw_screen_object_encoder_funcs = …; /* * Screen Object Display Unit connector functions */ static void vmw_sou_connector_destroy(struct drm_connector *connector) { … } static const struct drm_connector_funcs vmw_sou_connector_funcs = …; static const struct drm_connector_helper_funcs vmw_sou_connector_helper_funcs = …; /* * Screen Object Display Plane Functions */ /** * vmw_sou_primary_plane_cleanup_fb - Frees sou backing buffer * * @plane: display plane * @old_state: Contains the FB to clean up * * Unpins the display surface * * Returns 0 on success */ static void vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { … } /** * vmw_sou_primary_plane_prepare_fb - allocate backing buffer * * @plane: display plane * @new_state: info on the new plane state, including the FB * * The SOU backing buffer is our equivalent of the display plane. * * Returns 0 on success */ static int vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { … } static uint32_t vmw_sou_bo_fifo_size(struct vmw_du_update_plane *update, uint32_t num_hits) { … } static uint32_t vmw_sou_bo_define_gmrfb(struct vmw_du_update_plane *update, void *cmd) { … } static uint32_t vmw_sou_bo_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_stud_bo_post_clip(struct vmw_du_update_plane *update, void *cmd, struct drm_rect *bb) { … } /** * vmw_sou_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_sou_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_sou_surface_fifo_size(struct vmw_du_update_plane *update, uint32_t num_hits) { … } static uint32_t vmw_sou_surface_post_prepare(struct vmw_du_update_plane *update, void *cmd) { … } static uint32_t vmw_sou_surface_pre_clip(struct vmw_du_update_plane *update, void *cmd, uint32_t num_hits) { … } static uint32_t vmw_sou_surface_clip_rect(struct vmw_du_update_plane *update, void *cmd, struct drm_rect *clip, uint32_t src_x, uint32_t src_y) { … } static uint32_t vmw_sou_surface_post_clip(struct vmw_du_update_plane *update, void *cmd, struct drm_rect *bb) { … } /** * vmw_sou_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_sou_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) { … } static void vmw_sou_primary_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) { … } static const struct drm_plane_funcs vmw_sou_plane_funcs = …; static const struct drm_plane_funcs vmw_sou_cursor_funcs = …; /* * Atomic Helpers */ static const struct drm_plane_helper_funcs vmw_sou_cursor_plane_helper_funcs = …; static const struct drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = …; static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = …; static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) { … } int vmw_kms_sou_init_display(struct vmw_private *dev_priv) { … } static int do_bo_define_gmrfb(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer) { … } /** * vmw_sou_surface_fifo_commit - Callback to fill in and submit a * blit surface to screen command. * * @dirty: The closure structure. * * Fills in the missing fields in the command, and translates the cliprects * to match the destination bounding box encoded. */ static void vmw_sou_surface_fifo_commit(struct vmw_kms_dirty *dirty) { … } /** * vmw_sou_surface_clip - Callback to encode a blit surface to screen cliprect. * * @dirty: The closure structure * * Encodes a SVGASignedRect cliprect and updates the bounding box of the * BLIT_SURFACE_TO_SCREEN command. */ static void vmw_sou_surface_clip(struct vmw_kms_dirty *dirty) { … } /** * vmw_kms_sou_do_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_sou_do_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) { … } /** * vmw_sou_bo_fifo_commit - Callback to submit a set of readback clips. * * @dirty: The closure structure. * * Commits a previously built command buffer of readback clips. */ static void vmw_sou_bo_fifo_commit(struct vmw_kms_dirty *dirty) { … } /** * vmw_sou_bo_clip - Callback to encode a readback cliprect. * * @dirty: The closure structure * * Encodes a BLIT_GMRFB_TO_SCREEN cliprect. */ static void vmw_sou_bo_clip(struct vmw_kms_dirty *dirty) { … } /** * vmw_kms_sou_do_bo_dirty - Dirty part of a buffer-object backed framebuffer * * @dev_priv: Pointer to the device private structure. * @framebuffer: Pointer to the buffer-object backed framebuffer. * @clips: Array of clip rects. * @vclips: Alternate array of clip rects. Either @clips or @vclips must * be NULL. * @num_clips: Number of clip rects in @clips. * @increment: Increment to use when looping over @clips. * @interruptible: Whether to perform waits interruptible if possible. * @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 bo dirty on that crtc only. * * Returns 0 on success, negative error code on failure. -ERESTARTSYS if * interrupted. */ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, struct drm_clip_rect *clips, struct drm_vmw_rect *vclips, unsigned num_clips, int increment, bool interruptible, struct vmw_fence_obj **out_fence, struct drm_crtc *crtc) { … } /** * vmw_sou_readback_fifo_commit - Callback to submit a set of readback clips. * * @dirty: The closure structure. * * Commits a previously built command buffer of readback clips. */ static void vmw_sou_readback_fifo_commit(struct vmw_kms_dirty *dirty) { … } /** * vmw_sou_readback_clip - Callback to encode a readback cliprect. * * @dirty: The closure structure * * Encodes a BLIT_SCREEN_TO_GMRFB cliprect. */ static void vmw_sou_readback_clip(struct vmw_kms_dirty *dirty) { … } /** * vmw_kms_sou_readback - Perform a readback from the screen object system to * a buffer-object backed framebuffer. * * @dev_priv: Pointer to the device private structure. * @file_priv: Pointer to a struct drm_file identifying the caller. * Must be set to NULL if @user_fence_rep is NULL. * @vfb: Pointer to the buffer-object backed framebuffer. * @user_fence_rep: User-space provided structure for fence information. * Must be set to non-NULL if @file_priv is non-NULL. * @vclips: Array of clip rects. * @num_clips: Number of clip rects in @vclips. * @crtc: If crtc is passed, readback on that crtc only. * * Returns 0 on success, negative error code on failure. -ERESTARTSYS if * interrupted. */ int vmw_kms_sou_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_vmw_rect *vclips, uint32_t num_clips, struct drm_crtc *crtc) { … }