aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/mgag200/mgag200_mode.c
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2022-05-16 15:43:43 +0200
committerThomas Zimmermann <tzimmermann@suse.de>2022-05-17 20:24:44 +0200
commit475e2b970cc372f49e9d3e4bbead8b4874299d31 (patch)
tree984559124c46fdeb30732f19895a0cb3f497f9d9 /drivers/gpu/drm/mgag200/mgag200_mode.c
parentdrm/mgag200: Test memory requirements in drm_mode_config_funcs.mode_valid (diff)
downloadlinux-475e2b970cc372f49e9d3e4bbead8b4874299d31.tar.xz
linux-475e2b970cc372f49e9d3e4bbead8b4874299d31.zip
drm/mgag200: Split up connector's mode_valid helper
Split up the connector's mode_valid helper into a simple-pipe and a mode-config helper. The simple-pipe helper tests for display-size limits while the mode-config helper tests for memory-bandwidth limits. Also add the mgag200_ prefix to mga_vga_calculate_mode_bandwidth() and comment on the function's purpose. The memory-bandwidth tests assume that the display uses 4 bytes per pixel. The first models of G200SE-A only had 1.75 MiB of VRAM, which limits these devices to 640x480-32. v2: * note the memory constraints on early G200SE-A Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220516134343.6085-8-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm/mgag200/mgag200_mode.c')
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c146
1 files changed, 69 insertions, 77 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index a718a20b3a20..028c6ba7124c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -705,38 +705,27 @@ static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connecto
return ret;
}
-static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode,
- int bits_per_pixel)
-{
- uint32_t total_area, divisor;
- uint64_t active_area, pixels_per_second, bandwidth;
- uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
-
- divisor = 1024;
-
- if (!mode->htotal || !mode->vtotal || !mode->clock)
- return 0;
-
- active_area = mode->hdisplay * mode->vdisplay;
- total_area = mode->htotal * mode->vtotal;
-
- pixels_per_second = active_area * mode->clock * 1000;
- do_div(pixels_per_second, total_area);
-
- bandwidth = pixels_per_second * bytes_per_pixel * 100;
- do_div(bandwidth, divisor);
+static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
+ .get_modes = mgag200_vga_connector_helper_get_modes,
+};
- return (uint32_t)(bandwidth);
-}
+static const struct drm_connector_funcs mga_vga_connector_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
-#define MODE_BANDWIDTH MODE_BAD
+/*
+ * Simple Display Pipe
+ */
-static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+static enum drm_mode_status
+mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
+ const struct drm_display_mode *mode)
{
- struct drm_device *dev = connector->dev;
- struct mga_device *mdev = to_mga_device(dev);
- int bpp = 32;
+ struct mga_device *mdev = to_mga_device(pipe->crtc.dev);
if (IS_G200_SE(mdev)) {
u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
@@ -746,42 +735,17 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
return MODE_VIRTUAL_X;
if (mode->vdisplay > 1200)
return MODE_VIRTUAL_Y;
- if (mga_vga_calculate_mode_bandwidth(mode, bpp)
- > (24400 * 1024))
- return MODE_BANDWIDTH;
} else if (unique_rev_id == 0x02) {
if (mode->hdisplay > 1920)
return MODE_VIRTUAL_X;
if (mode->vdisplay > 1200)
return MODE_VIRTUAL_Y;
- if (mga_vga_calculate_mode_bandwidth(mode, bpp)
- > (30100 * 1024))
- return MODE_BANDWIDTH;
- } else {
- if (mga_vga_calculate_mode_bandwidth(mode, bpp)
- > (55000 * 1024))
- return MODE_BANDWIDTH;
}
} else if (mdev->type == G200_WB) {
if (mode->hdisplay > 1280)
return MODE_VIRTUAL_X;
if (mode->vdisplay > 1024)
return MODE_VIRTUAL_Y;
- if (mga_vga_calculate_mode_bandwidth(mode, bpp) >
- (31877 * 1024))
- return MODE_BANDWIDTH;
- } else if (mdev->type == G200_EV &&
- (mga_vga_calculate_mode_bandwidth(mode, bpp)
- > (32700 * 1024))) {
- return MODE_BANDWIDTH;
- } else if (mdev->type == G200_EH &&
- (mga_vga_calculate_mode_bandwidth(mode, bpp)
- > (37500 * 1024))) {
- return MODE_BANDWIDTH;
- } else if (mdev->type == G200_ER &&
- (mga_vga_calculate_mode_bandwidth(mode,
- bpp) > (55000 * 1024))) {
- return MODE_BANDWIDTH;
}
if ((mode->hdisplay % 8) != 0 || (mode->hsync_start % 8) != 0 ||
@@ -799,30 +763,6 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
return MODE_OK;
}
-static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
- .get_modes = mgag200_vga_connector_helper_get_modes,
- .mode_valid = mga_vga_mode_valid,
-};
-
-static const struct drm_connector_funcs mga_vga_connector_funcs = {
- .reset = drm_atomic_helper_connector_reset,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-/*
- * Simple Display Pipe
- */
-
-static enum drm_mode_status
-mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
- const struct drm_display_mode *mode)
-{
- return MODE_OK;
-}
-
static void
mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,
struct drm_rect *clip, const struct iosys_map *map)
@@ -1055,6 +995,31 @@ static const uint64_t mgag200_simple_display_pipe_fmtmods[] = {
* Mode config
*/
+/* Calculates a mode's required memory bandwidth (in KiB/sec). */
+static uint32_t mgag200_calculate_mode_bandwidth(const struct drm_display_mode *mode,
+ unsigned int bits_per_pixel)
+{
+ uint32_t total_area, divisor;
+ uint64_t active_area, pixels_per_second, bandwidth;
+ uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
+
+ divisor = 1024;
+
+ if (!mode->htotal || !mode->vtotal || !mode->clock)
+ return 0;
+
+ active_area = mode->hdisplay * mode->vdisplay;
+ total_area = mode->htotal * mode->vtotal;
+
+ pixels_per_second = active_area * mode->clock * 1000;
+ do_div(pixels_per_second, total_area);
+
+ bandwidth = pixels_per_second * bytes_per_pixel * 100;
+ do_div(bandwidth, divisor);
+
+ return (uint32_t)bandwidth;
+}
+
static enum drm_mode_status mgag200_mode_config_mode_valid(struct drm_device *dev,
const struct drm_display_mode *mode)
{
@@ -1070,6 +1035,33 @@ static enum drm_mode_status mgag200_mode_config_mode_valid(struct drm_device *de
if (fbpages > max_fbpages)
return MODE_MEM;
+ if (IS_G200_SE(mdev)) {
+ u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
+
+ if (unique_rev_id == 0x01) {
+ if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (24400 * 1024))
+ return MODE_BAD;
+ } else if (unique_rev_id == 0x02) {
+ if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (30100 * 1024))
+ return MODE_BAD;
+ } else {
+ if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (55000 * 1024))
+ return MODE_BAD;
+ }
+ } else if (mdev->type == G200_WB) {
+ if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (31877 * 1024))
+ return MODE_BAD;
+ } else if (mdev->type == G200_EV) {
+ if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (32700 * 1024))
+ return MODE_BAD;
+ } else if (mdev->type == G200_EH) {
+ if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (37500 * 1024))
+ return MODE_BAD;
+ } else if (mdev->type == G200_ER) {
+ if (mgag200_calculate_mode_bandwidth(mode, max_bpp * 8) > (55000 * 1024))
+ return MODE_BAD;
+ }
+
return MODE_OK;
}