Commit 80f7c3f7 authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/vram: Add helpers to validate a display mode's memory requirements

Devices with low amount of dedicated video memory may not be able
to use all possible display modes, as the framebuffers may not fit
into VRAM. The new helper function drm_vram_helper_mode_valid()
implements a simple test to sort out all display modes that can
not be used in any case. Drivers should call this function from
struct drm_mode_config_funcs.mode_valid.

The functionality was originally implemented by the ast driver, which
is being converted as well.

v2:
	* WARN_ON if VRAM memory manager has not been initialized
	* documentation fixes
	* unexported drm_vram_helper_mode_valid_internal()
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20200203155258.9346-2-tzimmermann@suse.de
parent fda15721
...@@ -388,31 +388,9 @@ static int ast_get_dram_info(struct drm_device *dev) ...@@ -388,31 +388,9 @@ static int ast_get_dram_info(struct drm_device *dev)
return 0; return 0;
} }
enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev,
const struct drm_display_mode *mode)
{
static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGBA8888 */
struct ast_private *ast = dev->dev_private;
unsigned long fbsize, fbpages, max_fbpages;
/* To support double buffering, a framebuffer may not
* consume more than half of the available VRAM.
*/
max_fbpages = (ast->vram_size / 2) >> PAGE_SHIFT;
fbsize = mode->hdisplay * mode->vdisplay * max_bpp;
fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
if (fbpages > max_fbpages)
return MODE_MEM;
return MODE_OK;
}
static const struct drm_mode_config_funcs ast_mode_funcs = { static const struct drm_mode_config_funcs ast_mode_funcs = {
.fb_create = drm_gem_fb_create, .fb_create = drm_gem_fb_create,
.mode_valid = ast_mode_config_mode_valid, .mode_valid = drm_vram_helper_mode_valid,
.atomic_check = drm_atomic_helper_check, .atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
}; };
......
...@@ -1141,3 +1141,64 @@ void drm_vram_helper_release_mm(struct drm_device *dev) ...@@ -1141,3 +1141,64 @@ void drm_vram_helper_release_mm(struct drm_device *dev)
dev->vram_mm = NULL; dev->vram_mm = NULL;
} }
EXPORT_SYMBOL(drm_vram_helper_release_mm); EXPORT_SYMBOL(drm_vram_helper_release_mm);
/*
* Mode-config helpers
*/
static enum drm_mode_status
drm_vram_helper_mode_valid_internal(struct drm_device *dev,
const struct drm_display_mode *mode,
unsigned long max_bpp)
{
struct drm_vram_mm *vmm = dev->vram_mm;
unsigned long fbsize, fbpages, max_fbpages;
if (WARN_ON(!dev->vram_mm))
return MODE_BAD;
max_fbpages = (vmm->vram_size / 2) >> PAGE_SHIFT;
fbsize = mode->hdisplay * mode->vdisplay * max_bpp;
fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
if (fbpages > max_fbpages)
return MODE_MEM;
return MODE_OK;
}
/**
* drm_vram_helper_mode_valid - Tests if a display mode's
* framebuffer fits into the available video memory.
* @dev: the DRM device
* @mode: the mode to test
*
* This function tests if enough video memory is available for using the
* specified display mode. Atomic modesetting requires importing the
* designated framebuffer into video memory before evicting the active
* one. Hence, any framebuffer may consume at most half of the available
* VRAM. Display modes that require a larger framebuffer can not be used,
* even if the CRTC does support them. Each framebuffer is assumed to
* have 32-bit color depth.
*
* Note:
* The function can only test if the display mode is supported in
* general. If there are too many framebuffers pinned to video memory,
* a display mode may still not be usable in practice. The color depth of
* 32-bit fits all current use case. A more flexible test can be added
* when necessary.
*
* Returns:
* MODE_OK if the display mode is supported, or an error code of type
* enum drm_mode_status otherwise.
*/
enum drm_mode_status
drm_vram_helper_mode_valid(struct drm_device *dev,
const struct drm_display_mode *mode)
{
static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
return drm_vram_helper_mode_valid_internal(dev, mode, max_bpp);
}
EXPORT_SYMBOL(drm_vram_helper_mode_valid);
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <drm/drm_file.h> #include <drm/drm_file.h>
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_ioctl.h> #include <drm/drm_ioctl.h>
#include <drm/drm_modes.h>
#include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_api.h>
#include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_bo_driver.h>
#include <drm/ttm/ttm_placement.h> #include <drm/ttm/ttm_placement.h>
...@@ -205,4 +206,12 @@ struct drm_vram_mm *drm_vram_helper_alloc_mm( ...@@ -205,4 +206,12 @@ struct drm_vram_mm *drm_vram_helper_alloc_mm(
struct drm_device *dev, uint64_t vram_base, size_t vram_size); struct drm_device *dev, uint64_t vram_base, size_t vram_size);
void drm_vram_helper_release_mm(struct drm_device *dev); void drm_vram_helper_release_mm(struct drm_device *dev);
/*
* Mode-config helpers
*/
enum drm_mode_status
drm_vram_helper_mode_valid(struct drm_device *dev,
const struct drm_display_mode *mode);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment