summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-07 13:11:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-07 13:11:40 +0000
commit8b0a8165cdad0f4133837d753649ef4682e42c3b (patch)
tree5c58f869f31ddb1f7bd6e8bdea269b680b36c5b6 /drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
parentReleasing progress-linux version 6.8.12-1~progress7.99u1. (diff)
downloadlinux-8b0a8165cdad0f4133837d753649ef4682e42c3b.tar.xz
linux-8b0a8165cdad0f4133837d753649ef4682e42c3b.zip
Merging upstream version 6.9.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index ba0c0e12cf..dbc44ecbd1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -41,7 +41,14 @@
#define vmw_connector_to_stdu(x) \
container_of(x, struct vmw_screen_target_display_unit, base.connector)
-
+/*
+ * 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 64
enum stdu_content_type {
SAME_AS_DISPLAY = 0,
@@ -53,7 +60,6 @@ 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().
- * @transfer: Transfer direction for DMA command.
* @left: Left side of bounding box.
* @right: Right side of bounding box.
* @top: Top side of bounding box.
@@ -100,7 +106,7 @@ struct vmw_stdu_update_gb_image {
};
/**
- * struct vmw_screen_target_display_unit
+ * 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
@@ -208,6 +214,8 @@ static int vmw_stdu_define_st(struct vmw_private *dev_priv,
* @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,
@@ -314,6 +322,9 @@ static int vmw_stdu_update_st(struct vmw_private *dev_priv,
*
* @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)
@@ -536,7 +547,8 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty)
* 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
+ *
+ * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
* interrupted.
*/
int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
@@ -703,7 +715,7 @@ static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty)
* 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
+ * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
* interrupted.
*/
int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
@@ -825,12 +837,46 @@ static void vmw_stdu_connector_destroy(struct drm_connector *connector)
vmw_stdu_destroy(vmw_connector_to_stdu(connector));
}
+static enum drm_mode_status
+vmw_stdu_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ enum drm_mode_status ret;
+ struct drm_device *dev = connector->dev;
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ u64 assumed_cpp = dev_priv->assume_16bpp ? 2 : 4;
+ /* Align width and height to account for GPU tile over-alignment */
+ u64 required_mem = ALIGN(mode->hdisplay, GPU_TILE_SIZE) *
+ ALIGN(mode->vdisplay, GPU_TILE_SIZE) *
+ assumed_cpp;
+ required_mem = ALIGN(required_mem, PAGE_SIZE);
+
+ ret = drm_mode_validate_size(mode, dev_priv->stdu_max_width,
+ dev_priv->stdu_max_height);
+ if (ret != MODE_OK)
+ return ret;
+ ret = drm_mode_validate_size(mode, dev_priv->texture_max_width,
+ dev_priv->texture_max_height);
+ if (ret != MODE_OK)
+ return ret;
+
+ if (required_mem > dev_priv->max_primary_mem)
+ return MODE_MEM;
+
+ if (required_mem > dev_priv->max_mob_pages * PAGE_SIZE)
+ return MODE_MEM;
+
+ if (required_mem > dev_priv->max_mob_size)
+ return MODE_MEM;
+
+ return MODE_OK;
+}
static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
.dpms = vmw_du_connector_dpms,
.detect = vmw_du_connector_detect,
- .fill_modes = vmw_du_connector_fill_modes,
+ .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = vmw_stdu_connector_destroy,
.reset = vmw_du_connector_reset,
.atomic_duplicate_state = vmw_du_connector_duplicate_state,
@@ -840,6 +886,8 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
static const struct
drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
+ .get_modes = vmw_connector_get_modes,
+ .mode_valid = vmw_stdu_connector_mode_valid
};
@@ -887,7 +935,7 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
* backed by a buffer object. The display surface is pinned here, and it'll
* be unpinned in .cleanup_fb()
*
- * Returns 0 on success
+ * Returns: %0 on success
*/
static int
vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
@@ -1465,6 +1513,8 @@ static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
* 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)
{