[PATCH i-g-t 1/4] tools/displaytop: Add Display Top - a terminal-based display pipeline monitor

Adith Narein T adith.narein.t at intel.com
Thu May 29 14:23:40 UTC 2025


This patch introduces `displaytop`, a terminal-based tool designed for
monitoring and debugging the display pipeline in real time.
The initial feature focuses on providing detailed display configuration
information, including:

     - CRTCs
     - Connectors
     - Encoders
     - Planes
     - Framebuffers

These components are presented in an organized format using a terminal UI
built with `ncurses`, giving developers and validation engineers a fast and
accessible way to inspect the current state of the display system.

Signed-off-by: Adith Narein T <adith.narein.t at intel.com>
---
 tools/displaytop/README.md                    |  77 ++
 tools/displaytop/include/data.h               |  37 +
 tools/displaytop/include/display.h            |  46 +
 tools/displaytop/include/log.h                |  45 +
 tools/displaytop/include/node.h               | 126 +++
 tools/displaytop/include/populate.h           |  37 +
 tools/displaytop/include/utils.h              | 115 +++
 tools/displaytop/meson.build                  | 100 ++
 tools/displaytop/src/data.c                   |  29 +
 tools/displaytop/src/display.c                | 480 ++++++++++
 tools/displaytop/src/display_configuration.c  | 877 ++++++++++++++++++
 tools/displaytop/src/display_dump.c           | 215 +++++
 tools/displaytop/src/display_search_bar.c     | 281 ++++++
 tools/displaytop/src/display_summary.c        | 308 ++++++
 tools/displaytop/src/log.c                    |  84 ++
 tools/displaytop/src/main.c                   |  63 ++
 tools/displaytop/src/node.c                   | 140 +++
 tools/displaytop/src/populate.c               |  32 +
 .../displaytop/src/populate_display_config.c  | 295 ++++++
 tools/displaytop/src/utils.c                  | 102 ++
 tools/displaytop/src/utils_cli.c              |  70 ++
 tools/displaytop/src/utils_display.c          | 195 ++++
 tools/displaytop/src/utils_driver.c           | 189 ++++
 tools/displaytop/src/utils_drm.c              | 585 ++++++++++++
 tools/displaytop/src/utils_search.c           |  49 +
 tools/meson.build                             |   1 +
 26 files changed, 4578 insertions(+)
 create mode 100644 tools/displaytop/README.md
 create mode 100644 tools/displaytop/include/data.h
 create mode 100644 tools/displaytop/include/display.h
 create mode 100644 tools/displaytop/include/log.h
 create mode 100644 tools/displaytop/include/node.h
 create mode 100644 tools/displaytop/include/populate.h
 create mode 100644 tools/displaytop/include/utils.h
 create mode 100644 tools/displaytop/meson.build
 create mode 100644 tools/displaytop/src/data.c
 create mode 100644 tools/displaytop/src/display.c
 create mode 100644 tools/displaytop/src/display_configuration.c
 create mode 100644 tools/displaytop/src/display_dump.c
 create mode 100644 tools/displaytop/src/display_search_bar.c
 create mode 100644 tools/displaytop/src/display_summary.c
 create mode 100644 tools/displaytop/src/log.c
 create mode 100644 tools/displaytop/src/main.c
 create mode 100644 tools/displaytop/src/node.c
 create mode 100644 tools/displaytop/src/populate.c
 create mode 100644 tools/displaytop/src/populate_display_config.c
 create mode 100644 tools/displaytop/src/utils.c
 create mode 100644 tools/displaytop/src/utils_cli.c
 create mode 100644 tools/displaytop/src/utils_display.c
 create mode 100644 tools/displaytop/src/utils_driver.c
 create mode 100644 tools/displaytop/src/utils_drm.c
 create mode 100644 tools/displaytop/src/utils_search.c

diff --git a/tools/displaytop/README.md b/tools/displaytop/README.md
new file mode 100644
index 000000000..7349f0760
--- /dev/null
+++ b/tools/displaytop/README.md
@@ -0,0 +1,77 @@
+# **DisplayTop**
+
+A terminal-based tool for monitoring and debugging the display pipeline.
+
+## **Features**
+
+- Terminal UI using `ncurses`
+- Dump feature for all the menus
+- Real-time display Configuration
+
+---
+
+## **Quick Start**
+
+To run DisplayTop as part of the IGT GPU Tools:
+
+1. Build IGT as usual.
+2. Navigate to the build directory:
+
+   ```bash
+   cd build/tools/displaytop
+   ```
+3. Run the tool with root privileges:
+
+   ```bash
+   sudo ./displaytop
+   ```
+
+> **Note:** Running without `sudo` will disable certain features due to insufficient permissions.
+
+---
+
+## **Building as a Standalone Project**
+
+DisplayTop can also be built independently of the full IGT suite.
+
+### Steps:
+
+1. In the displaytop directory, open `meson.build` and **uncomment** the following block at the top:
+
+   ```meson
+   # This block must be UNCOMMENTED when building DisplayTop as a standalone project
+   project('displaytop', 'c',
+     version: '1.0',
+     default_options: ['warning_level=2', 'c_std=c11']
+   )
+   cc = meson.get_compiler('c')
+   ```
+
+2. Build the project:
+
+   ```bash
+   meson build
+   ninja -C build
+   ```
+
+3. Run the tool:
+
+   ```bash
+   sudo ./build/displaytop
+   ```
+
+> **Important:** If you're building DisplayTop **as part of IGT**, **comment out** the block above in `meson.build`.
+
+---
+
+Build igt-gpu-tools as normal and then go to `build/tools/displaytop` and run sudo `./displaytop`.
+Note: Running the tool without sudo will result in loss of some features being disabled.
+
+---
+
+## Logs & Dumps
+
+The log for the display top tool and the dumps initiated by the user are
+stored in the `/tmp` folder as `displaytop.log` and `/displaytop_dump` respectively.
+
+---
\ No newline at end of file
diff --git a/tools/displaytop/include/data.h b/tools/displaytop/include/data.h
new file mode 100644
index 000000000..0bc1b51d4
--- /dev/null
+++ b/tools/displaytop/include/data.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef DATA_H
+#define DATA_H
+
+#include "node.h"
+
+extern Node *root; /* shared throughout the program */
+
+#define DUMP_DIR "/tmp/displaytop_dump"
+
+#define DRM_DIR "/dev/dri/"
+#define DRM_PRIMARY_PREFIX "card"
+#define DRM_RENDER_PREFIX "renderD"
+
+#endif
\ No newline at end of file
diff --git a/tools/displaytop/include/display.h b/tools/displaytop/include/display.h
new file mode 100644
index 000000000..db77ef785
--- /dev/null
+++ b/tools/displaytop/include/display.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+#include "log.h"
+#include "node.h"
+#include "utils.h"
+
+void display_win(WINDOW *win, Node *node);
+
+Node *display_search_bar(Node *head);
+void display_dump_menu(Node *head);
+
+void display_crtc(WINDOW *pad, Node *node, int *content_line);
+void display_plane(WINDOW *pad, Node *node, int *content_line);
+void display_encoder(WINDOW *pad, Node *node, int *content_line);
+void display_formats(WINDOW *pad, Node *node, int *content_line);
+void display_connector(WINDOW *pad, Node *node, int *content_line);
+void display_informats(WINDOW *pad, Node *node, int *content_line);
+void display_framebuffer(WINDOW *pad, Node *node, int *content_line);
+
+void display_summary(WINDOW *pad, Node *node, int *content_line);
+
+#endif
\ No newline at end of file
diff --git a/tools/displaytop/include/log.h b/tools/displaytop/include/log.h
new file mode 100644
index 000000000..bfc37e543
--- /dev/null
+++ b/tools/displaytop/include/log.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef LOG_H
+#define LOG_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#define LOG_FILE "/tmp/displaytop.log"
+
+typedef enum
+{
+    LOG_INFO,
+    LOG_WARNING,
+    LOG_ERROR
+} LogLevel;
+
+void init_log_system(void);
+void close_log_system(void);
+
+void log_message(int level, const char *format, ...) __attribute__((format(gnu_printf, 2, 3)));
+
+#endif
diff --git a/tools/displaytop/include/node.h b/tools/displaytop/include/node.h
new file mode 100644
index 000000000..e0ab2c5cd
--- /dev/null
+++ b/tools/displaytop/include/node.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef NODE_H
+#define NODE_H
+
+#include <string.h>
+#include <stdlib.h>
+#include <ncurses.h>
+
+/**
+ * @struct Node
+ * @brief Represents a node in a tree structure.
+ *
+ * This structure is used to represent a node in a tree, where each node can have a name,
+ * a display function, a parent node, and an array of child nodes.
+ *
+ * @var Node::name
+ * A character array to store the name of the node. The name can be up to 49 characters long,
+ * with the 50th character reserved for the null terminator.
+ *
+ * @var Node::display_function
+ * A pointer to a function that takes a WINDOW pointer and a variable number of arguments,
+ * and returns an integer. This function is used to display the node.
+ *
+ * @var Node::parent
+ * A pointer to the parent node. If the node is the root, this will be NULL.
+ *
+ * @var Node::children
+ * A pointer to an array of child nodes. If the node has no children, this will be NULL.
+ *
+ * @var Node::children_size
+ * An integer representing the number of children the node has.
+ */
+typedef struct Node
+{
+    char name[50];
+    void (*display_function)(WINDOW *, struct Node *, int *);
+    struct Node *parent;
+    struct Node *children;
+    int children_size;
+} Node;
+
+/**
+ * @brief Creates a new node with the given name, display function, and parent.
+ *
+ * This function allocates memory for a new node, initializes its name, display function,
+ * parent, and sets its children to NULL and children_size to 0.
+ *
+ * @param name The name of the node.
+ * @param display_function A pointer to the display function associated with the node.
+ * @param parent A pointer to the parent node.
+ * @return A pointer to the newly created node.
+ */
+Node *create_node(const char *name, void (*display_function)(WINDOW *, Node *, int *), Node *parent);
+
+/**
+ * @brief Adds a child node to the specified parent node.
+ *
+ * This function reallocates memory for the parent's children array to accommodate the new child,
+ * assigns the child to the next available position in the array, and increments the children_size.
+ *
+ * @param parent A pointer to the parent node.
+ * @param child A pointer to the child node to be added.
+ */
+void add_child(Node *parent, Node *child);
+
+/**
+ * @brief Frees the memory allocated for the tree recursively.
+ *
+ * This function recursively frees the memory allocated for the children of the given root node,
+ * then frees the memory allocated for the children array and the root node itself.
+ *
+ * @param root A pointer to the root node of the tree.
+ */
+void free_tree(Node *root);
+
+/**
+ * @brief Prints the path from the given node.
+ *
+ * This function takes a pointer to a Node structure and prints the path
+ * associated with that node. The exact format and details of the path
+ * are dependent on the implementation of the Node structure and the
+ * printPath function.
+ *
+ * @param node A pointer to the Node whose path is to be printed.
+ */
+void print_path(Node *node);
+
+/**
+ * @brief Gets the path from the given node.
+ *
+ * This function takes a pointer to a Node structure and returns the path
+ * associated with that node. The exact format and details of the path
+ * are dependent on the implementation of the Node structure and the
+ * getPath function.
+ *
+ * @param node A pointer to the Node whose path is to be returned.
+ * @return A string representing the path of the node.
+ */
+char *get_path(Node *node);
+
+void count_nodes(Node *node, int *count);
+
+
+#endif
diff --git a/tools/displaytop/include/populate.h b/tools/displaytop/include/populate.h
new file mode 100644
index 000000000..5a5241355
--- /dev/null
+++ b/tools/displaytop/include/populate.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef POPULATE_H
+#define POPULATE_H
+
+#include "node.h"
+#include "data.h"
+#include "utils.h"
+#include "utils.h"
+#include "display.h"
+
+void populate_data(void);
+
+void initialize_display_config(void);
+
+#endif
\ No newline at end of file
diff --git a/tools/displaytop/include/utils.h b/tools/displaytop/include/utils.h
new file mode 100644
index 000000000..eef5df5f3
--- /dev/null
+++ b/tools/displaytop/include/utils.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+#include <time.h>
+#include <math.h>
+#include <string.h>
+
+#include <error.h>
+#include <errno.h>
+
+#include <fcntl.h>
+#include <ctype.h>
+#include <limits.h>
+#include <libgen.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <dirent.h>
+#include <unistd.h>
+#include <ncurses.h>
+#include <sys/wait.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <xf86drm.h>
+#include <drm/drm.h>
+#include <xf86drmMode.h>
+#include <drm/drm_mode.h>
+#include <drm/i915_drm.h>
+#include <drm/drm_fourcc.h>
+
+#include "log.h"
+#include "node.h"
+#include "data.h"
+#include "display.h"
+
+extern int drm_fd;
+
+/* utils_cli.c */
+void handle_cli_args(int argc, char *argv[]);
+
+/* utils_driver.c*/
+void check_and_load_driver(void);
+
+/* utils_display.c */
+void set_string(char *dest, const char *src, size_t size);
+int check_size_change(WINDOW *win, int *height, int *width);
+
+void single_file_dump(Node *node, const char *filePath, bool single);
+void search_nodes(Node *root, const char *searchInput, Node *results);
+
+void print_bold_text(WINDOW *win, int line, int col, const char *text, ...)
+    __attribute__((format(printf, 4, 5)));
+
+void print_dim_text(WINDOW *win, int line, int col, const char *text, ...)
+    __attribute__((format(printf, 4, 5)));
+
+void print_red_text(WINDOW *win, int line, int col, const char *text, ...)
+    __attribute__((format(printf, 4, 5)));
+
+void print_green_text(WINDOW *win, int line, int col, const char *text, ...)
+    __attribute__((format(printf, 4, 5)));
+
+void draw_header(WINDOW *win, int winWidth, const char *title, const char *helper);
+void render_progress_bar(WINDOW *win, int current, int total);
+
+void print_wrapped_text(WINDOW *pad, int *line, int start, int size, const char *text, bool enclose_with_pipe);
+
+/* utils.c*/
+void ensure_dump_directory(void);
+void strip_whitespace(char *str);
+char *read_file(const char *filename);
+
+char *get_file_path(const char *filename);
+
+/* utils_drm.c */
+char *find_drm_device(bool primary);
+void open_primary_drm_device(void);
+void close_primary_drm_device(void);
+
+const char *get_drm_object_type_name(uint32_t object_type);
+const char *get_format_str(uint32_t format);
+const char *get_basic_modifier_str(uint64_t modifier);
+const char *get_connector_type_name(uint32_t connector_type);
+const char *get_encoder_type_name(uint32_t encoder_type);
+
+#endif
\ No newline at end of file
diff --git a/tools/displaytop/meson.build b/tools/displaytop/meson.build
new file mode 100644
index 000000000..2d8c9d418
--- /dev/null
+++ b/tools/displaytop/meson.build
@@ -0,0 +1,100 @@
+# Meson build definition for DisplayTop tool
+
+# This block of code must be UNCOMMENTED when building displaytop as a standalone project
+# project('displaytop', 'c',
+#   version: '1.0',
+#   default_options: ['warning_level=2', 'c_std=c11']
+# )
+# cc = meson.get_compiler('c')
+
+# Compiler flags
+cflags = [
+  '-Wall', '-Wextra',
+  '-Iinclude', '-I/usr/include/libdrm', '-I/usr/local/include',
+  '-DMESON_SOURCE_ROOT="' + meson.source_root() + '"'
+]
+
+# Include directories
+inc_dirs = include_directories(
+  'include',
+  '/usr/include/libdrm',
+  '/usr/local/include'
+)
+
+libdrm_dep = dependency('libdrm', required: true)
+ncurses_dep = dependency('ncurses', required: false)
+menu_dep    = dependency('menu', required: false)
+form_dep    = dependency('form', required: false)
+panel_dep   = dependency('panel', required: false)
+
+have_displaytop = ncurses_dep.found() and menu_dep.found() and form_dep.found() and panel_dep.found()
+
+if have_displaytop
+  message('All dependencies found. Building displaytop.')
+
+  deps = [
+    libdrm_dep,
+    ncurses_dep,
+    menu_dep,
+    form_dep,
+    panel_dep,
+  ]
+  # Source files
+  source = files(
+    'src/data.c',
+    'src/display.c',
+    'src/display_configuration.c',
+    'src/display_dump.c',
+    'src/display_search_bar.c',
+    'src/display_summary.c',
+    'src/log.c',
+    'src/main.c',
+    'src/node.c',
+    'src/populate.c',
+    'src/populate_display_config.c',
+    'src/utils.c',
+    'src/utils_cli.c',
+    'src/utils_display.c',
+    'src/utils_driver.c',
+    'src/utils_drm.c',
+    'src/utils_search.c',
+  )
+
+  if meson.is_subproject()
+    # SUBPROJECT MODE
+    # This block is used when the project is included as a subproject
+    # inside a larger Meson-based project (via subproject('displaytop'))
+
+    # Define a static library
+    displaytop_lib = static_library(
+      'displaytop', source,
+      c_args: cflags,
+      include_directories: inc_dirs,
+      dependencies: deps,
+    )
+
+    # Declare the dependency so parent projects can link to this
+    displaytop_dep = declare_dependency(
+      link_with: displaytop_lib,
+      include_directories: inc_dirs,
+      dependencies: deps,
+    )
+
+  else
+    # STANDALONE MODE
+    # This block builds and installs the executable when run independently.
+    # If you’re including this as a subproject in another Meson build,
+    # COMMENT OUT the `project()` line at the top and this `else` block.
+
+    executable(
+      'displaytop', source,
+      install: true,
+      c_args: cflags,
+      include_directories: inc_dirs,
+      dependencies: deps,
+    )
+  endif
+
+else
+  message('Skipping displaytop: missing required optional dependencies.')
+endif
\ No newline at end of file
diff --git a/tools/displaytop/src/data.c b/tools/displaytop/src/data.c
new file mode 100644
index 000000000..3aed6292b
--- /dev/null
+++ b/tools/displaytop/src/data.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "data.h"
+#include "display.h"
+
+/* This file holds all the global variables that are being used in the tool */
+
+Node *root;
\ No newline at end of file
diff --git a/tools/displaytop/src/display.c b/tools/displaytop/src/display.c
new file mode 100644
index 000000000..e826f6611
--- /dev/null
+++ b/tools/displaytop/src/display.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "display.h"
+#include "data.h"
+#include "utils.h"
+
+static int display_exit_menu(void)
+{
+    int height = 8, width = 40;
+    int starty = (LINES - height) / 2;
+    int startx = (COLS - width) / 2;
+    int ch;
+    const char *message = "Are you sure you want to quit?";
+
+    WINDOW *overlay = newwin(LINES, COLS, 0, 0);
+    WINDOW *confirm_win = newwin(height, width, starty, startx);
+
+    wbkgd(overlay, COLOR_PAIR(0));
+    wclear(overlay);
+    wrefresh(overlay);
+
+    wbkgd(confirm_win, COLOR_PAIR(2));
+    box(confirm_win, 0, 0);
+
+    mvwprintw(confirm_win, 2, (width - strlen(message)) / 2, "%s", message);
+
+    wattron(confirm_win, A_REVERSE);
+    mvwprintw(confirm_win, 4, width / 2 - 5, "[Y]es");
+    mvwprintw(confirm_win, 4, width / 2 + 2, "[N]o");
+    wattroff(confirm_win, A_REVERSE);
+
+    wrefresh(confirm_win);
+
+    while ((ch = wgetch(confirm_win)))
+    {
+        if (ch == 'y' || ch == 'Y')
+        {
+            delwin(confirm_win);
+            delwin(overlay);
+            return 1;
+        }
+        else if (ch == 'n' || ch == 'N' || ch == 27)
+        {
+            delwin(confirm_win);
+            delwin(overlay);
+            return 0;
+        }
+    }
+
+    delwin(confirm_win);
+    delwin(overlay);
+    return 0;
+}
+
+static void display_help_menu(void)
+{
+    int row = 2;
+    const char *title = " Help ";
+    WINDOW *help_win = newwin(LINES, COLS, 0, 0);
+    wbkgd(help_win, COLOR_PAIR(6));
+    wclear(help_win);
+    box(help_win, 0, 0);
+
+    mvwprintw(help_win, 0, (COLS - strlen(title)) / 2, "%s", title);
+
+    print_bold_text(help_win, row++, 4, "Key Bindings:");
+    row++;
+    print_bold_text(help_win, row, 6, "[Q]");
+    mvwprintw(help_win, row++, 18, "- Quit the application with a confirmation prompt.");
+    print_bold_text(help_win, row, 6, "[H]");
+    mvwprintw(help_win, row++, 18, "- Open the help menu to view key bindings and descriptions.");
+    print_bold_text(help_win, row, 6, "[UP/DOWN]");
+    mvwprintw(help_win, row++, 18, "- Navigate through menu items or scroll content.");
+    print_bold_text(help_win, row, 6, "[TAB]");
+    mvwprintw(help_win, row++, 18, "- Toggle focus between the menu and display content.");
+    print_bold_text(help_win, row, 6, "[ENTER]");
+    mvwprintw(help_win, row++, 18, "- Select a menu item or confirm an action.");
+    print_bold_text(help_win, row, 6, "[ESC]");
+    mvwprintw(help_win, row++, 18, "- Go back, cancel an action, or exit the application.");
+    print_bold_text(help_win, row, 6, "[S]");
+    mvwprintw(help_win, row++, 18, "- Search for specific items in the menu.");
+    print_bold_text(help_win, row, 6, "[P]");
+    mvwprintw(help_win, row++, 18, "- Save the current page's content to a file.");
+    print_bold_text(help_win, row, 6, "[D]");
+    mvwprintw(help_win, row++, 18, "- Save all nested content starting from the current menu.");
+    print_bold_text(help_win, row, 6, "[R]");
+    mvwprintw(help_win, row++, 18, "- Refresh the display to show recent updates.");
+
+    row++;
+    mvwprintw(help_win, row++, 4, "Press any key to return...");
+
+    wrefresh(help_win);
+    wgetch(help_win);
+
+    delwin(help_win);
+}
+
+void display_win(WINDOW *win, Node *node)
+{
+    Node *head = node;
+
+    int is_running;
+    int highlighted_index = 0;
+
+    bool focus_on_menu = true;
+    bool refresh = true;
+
+    int win_height, win_width;
+
+    int content_height;
+    int content_y_start;
+
+    int mpx;
+    int menu_pad_pos;
+    int menu_pad_width;
+    int menu_pad_height;
+    WINDOW *menu_pad = NULL;
+
+    int dpx;
+    int display_pad_pos;
+    int display_pad_width;
+    int display_pad_height;
+    WINDOW *display_pad = NULL;
+
+    const char *path = get_path(head);
+    const char *status_text = "[TAB] Switch Focus [S] Search [ESC] Back [R] Refresh [H] Help";
+
+    int count;
+
+    int ch;
+
+    while (1)
+    {
+        wclear(win);
+        box(win, 0, 0);
+        wbkgd(win, COLOR_PAIR(2));
+        getmaxyx(win, win_height, win_width);
+
+        if (head->display_function == NULL && head->children_size == 0)
+        {
+            mvwprintw(win, 4, 2, "It's so Empty at %s :(", head->name);
+            mvwprintw(win, 8, 2, "Press 'e' to go back.");
+            wrefresh(win);
+        }
+
+        is_running = 1;
+
+        log_message(LOG_INFO, "Displaying %s", head->name);
+
+        while (is_running)
+        {
+            if (check_size_change(win, &win_height, &win_width) == 1 || refresh)
+            {
+                log_message(LOG_INFO, "Window size changed. Refreshing display.");
+                refresh = false;
+
+                content_height = win_height - 6;
+                content_y_start = 4;
+
+                mpx = 1;
+                menu_pad_pos = 0;
+                menu_pad_height = head->children_size > content_height ? head->children_size + 5 : content_height;
+                menu_pad_width = (int)((win_width - 3) * 0.3);
+
+                dpx = menu_pad_width + 2;
+                display_pad_pos = 0;
+                display_pad_height = 1000;
+                display_pad_width = win_width - 3 - menu_pad_width;
+
+                if (menu_pad != NULL)
+                {
+                    delwin(menu_pad);
+                    menu_pad = NULL;
+                }
+
+                menu_pad = newpad(menu_pad_height, menu_pad_width);
+                prefresh(menu_pad, menu_pad_pos, 0, content_y_start, 1, content_height + content_y_start - 1, menu_pad_width + 1);
+
+                if (head->display_function != NULL)
+                {
+                    if (display_pad != NULL)
+                    {
+                        delwin(display_pad);
+                        display_pad = NULL;
+                    }
+
+                    count = display_pad_height;
+                    display_pad = newpad(display_pad_height, display_pad_width);
+
+                    head->display_function(display_pad, head, &count);
+
+                    if (count == 0)
+                    {
+                        log_message(LOG_INFO, "Exiting %s", head->name);
+                        if (head != NULL && head->parent != NULL)
+                        {
+                            head = head->parent;
+                            focus_on_menu = true;
+                            highlighted_index = 0;
+                            display_pad_pos = 0;
+                            is_running = 0;
+                        }
+                        else
+                        {
+                            return;
+                        }
+                        continue;
+                    }
+
+                    if (count < display_pad_height)
+                        display_pad_height = count + 5;
+
+                    prefresh(display_pad, display_pad_pos, 0, content_y_start, dpx, content_height + content_y_start - 1, 2 + menu_pad_width + display_pad_width);
+                }
+
+                wclear(win);
+                box(win, 0, 0);
+
+                path = get_path(head);
+
+                draw_header(win, win_width, path, status_text);
+
+                mvwvline(win, 3, menu_pad_width + 1, ACS_VLINE, win_height - 4);
+                wrefresh(win);
+            }
+
+            if (head->display_function != NULL)
+            {
+                if (display_pad_pos > 0)
+                    print_bold_text(win, 3, menu_pad_width + 2, "...");
+                else
+                    mvwprintw(win, 3, menu_pad_width + 2, "   ");
+
+                if (display_pad_pos < display_pad_height - content_height)
+                    print_bold_text(win, content_height + content_y_start, menu_pad_width + 2, "...");
+                else
+                    mvwprintw(win, content_height + content_y_start, menu_pad_width + 2, "   ");
+
+                print_dim_text(win, 3, win_width - 15, "%d lines", display_pad_height);
+                prefresh(display_pad, display_pad_pos, 0, content_y_start, dpx, content_height + content_y_start - 1, 2 + menu_pad_width + display_pad_width);
+            }
+
+            if (focus_on_menu)
+            {
+                print_bold_text(win, 3, win_width - 5, "   ");
+                wattron(win, A_REVERSE);
+                print_bold_text(win, 3, menu_pad_width - 3, "***");
+                wattroff(win, A_REVERSE);
+            }
+            else
+            {
+                print_bold_text(win, 3, menu_pad_width - 3, "   ");
+                wattron(win, A_REVERSE);
+                print_bold_text(win, 3, win_width - 5, "***");
+                wattroff(win, A_REVERSE);
+            }
+
+            if (head->children_size > 0)
+            {
+                if (head->display_function == NULL)
+                    focus_on_menu = true;
+                print_dim_text(win, 3, menu_pad_width - 15, "%d Menus", head->children_size);
+                for (int i = 0; i < head->children_size; ++i)
+                {
+                    if (highlighted_index == i && focus_on_menu)
+                        wattron(menu_pad, A_REVERSE);
+                    mvwprintw(menu_pad, i, 1, "%d. %s", i + 1, head->children[i].name);
+                    wattroff(menu_pad, A_REVERSE);
+                }
+            }
+
+            if (highlighted_index == head->children_size && focus_on_menu)
+                wattron(menu_pad, A_REVERSE);
+
+            if (head->parent != NULL)
+                print_dim_text(menu_pad, head->children_size, 1, "Go Back");
+            else
+                print_dim_text(menu_pad, head->children_size, 1, "Exit");
+
+            wattroff(menu_pad, A_REVERSE);
+
+            prefresh(menu_pad, menu_pad_pos, 0, content_y_start, mpx, content_height + content_y_start - 1, menu_pad_width + 1);
+
+            ch = wgetch(win);
+            switch (ch)
+            {
+            case KEY_UP:
+                if (!focus_on_menu && display_pad_pos > 0)
+                    display_pad_pos--;
+
+                else if (focus_on_menu)
+                {
+                    if (highlighted_index == 0)
+                    {
+                        highlighted_index = head->children_size;
+                        menu_pad_pos = menu_pad_height - content_height;
+                    }
+                    else
+                    {
+                        highlighted_index--;
+
+                        if (highlighted_index > menu_pad_height - content_height)
+                        {
+                            menu_pad_pos = menu_pad_height - content_height;
+                        }
+                        else
+                        {
+                            menu_pad_pos--;
+                        }
+                    }
+                }
+                break;
+
+            case KEY_DOWN:
+                if (!focus_on_menu && display_pad_pos < display_pad_height - content_height)
+                    display_pad_pos++;
+
+                else if (focus_on_menu)
+                {
+                    if (highlighted_index == head->children_size)
+                    {
+                        highlighted_index = 0;
+                        menu_pad_pos = 0;
+                    }
+                    else
+                    {
+                        highlighted_index++;
+
+                        if (highlighted_index > menu_pad_height - content_height)
+                        {
+                            menu_pad_pos = menu_pad_height - content_height;
+                        }
+                        else
+                        {
+                            menu_pad_pos++;
+                        }
+                    }
+                }
+                break;
+
+            case 's':
+            case 'S':
+                log_message(LOG_INFO, "Searching %s", head->name);
+                head = display_search_bar(head);
+                refresh = true;
+                break;
+
+            case 'p':
+            case 'P':
+                single_file_dump(head, DUMP_DIR, true);
+                refresh = true;
+                break;
+
+            case 'd':
+            case 'D':
+                display_dump_menu(head);
+                refresh = true;
+                break;
+
+            case 'h':
+            case 'H':
+                display_help_menu();
+                refresh = true;
+                break;
+
+            case 'q':
+            case 'Q':
+                if (display_exit_menu())
+                {
+                    log_message(LOG_INFO, "Exiting DisplayTop");
+                    return;
+                }
+                else
+                {
+                    refresh = true;
+                }
+                break;
+
+            case 27:
+                log_message(LOG_INFO, "Exiting %s", head->name);
+                if (head != NULL && head->parent != NULL)
+                {
+                    head = head->parent;
+                    focus_on_menu = true;
+                    highlighted_index = 0;
+                    display_pad_pos = 0;
+                    is_running = 0;
+                }
+                else if (display_exit_menu())
+                {
+                    log_message(LOG_INFO, "Exiting DisplayTop");
+                    return;
+                }
+                else
+                {
+                    refresh = true;
+                }
+                break;
+
+            case 'r':
+            case 'R':
+                log_message(LOG_INFO, "Refreshing %s", head->name);
+                refresh = true;
+                break;
+
+            case '\n':
+                if (focus_on_menu && head != NULL)
+                {
+                    if (highlighted_index >= 0 && highlighted_index < head->children_size)
+                    {
+                        head = &head->children[highlighted_index];
+                        highlighted_index = 0;
+                        display_pad_pos = 0;
+                        is_running = 0;
+                        refresh = true;
+                    }
+                    else if (highlighted_index == head->children_size)
+                    {
+                        if (head != NULL && head->parent != NULL)
+                        {
+                            head = head->parent;
+                            focus_on_menu = true;
+                            highlighted_index = 0;
+                            display_pad_pos = 0;
+                            is_running = 0;
+                        }
+                        else if (display_exit_menu())
+                        {
+                            log_message(LOG_INFO, "Exiting DisplayTop");
+                            return;
+                        }
+                        else
+                        {
+                            refresh = true;
+                        }
+                    }
+                }
+                break;
+
+            case '\t':
+                focus_on_menu = !focus_on_menu;
+                break;
+            }
+        }
+
+        refresh = true;
+
+        if (display_pad != NULL)
+        {
+            delwin(display_pad);
+            display_pad = NULL;
+        }
+        if (menu_pad != NULL)
+        {
+            delwin(menu_pad);
+            menu_pad = NULL;
+        }
+    }
+}
diff --git a/tools/displaytop/src/display_configuration.c b/tools/displaytop/src/display_configuration.c
new file mode 100644
index 000000000..8f366d7df
--- /dev/null
+++ b/tools/displaytop/src/display_configuration.c
@@ -0,0 +1,877 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "display.h"
+#include "utils.h"
+
+void display_crtc(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    drmModeRes *resources = NULL;
+    drmModeObjectProperties *props = NULL;
+    drmModePlaneRes *plane_resources = NULL;
+    drmModeCrtc *crtc = NULL;
+    int crtc_index = -1;
+    char *endptr;
+
+    if (drm_fd < 0)
+    {
+        print_red_text(pad, line++, 1, "Failed to open DRM Device!\n");
+        goto err;
+    }
+
+    resources = drmModeGetResources(drm_fd);
+    if (!resources)
+    {
+        print_red_text(pad, line++, 1, "Failed to get DRM resources\n");
+        goto err;
+    }
+
+    crtc_index = strtol(node->name + 4, &endptr, 10);
+    if (*endptr != '\0' || crtc_index < 0 || crtc_index >= resources->count_crtcs)
+    {
+        print_red_text(pad, line++, 1, "Invalid CRTC name: %s\n", node->name);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    crtc = drmModeGetCrtc(drm_fd, resources->crtcs[crtc_index]);
+    if (!crtc)
+    {
+        print_red_text(pad, line++, 1, "Failed to get CRTC %d\n", crtc_index);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "CRTC ID: %d", crtc->crtc_id);
+    mvwprintw(pad, line++, 1, "Framebuffer ID: %d", crtc->buffer_id);
+    mvwprintw(pad, line++, 1, "Position(X, Y): (%d, %d)", crtc->x, crtc->y);
+    mvwprintw(pad, line++, 1, "Mode: ");
+    if (crtc->mode_valid)
+        print_green_text(pad, -1, -1, "VALID");
+    else
+        print_red_text(pad, -1, -1, "INVALID");
+
+    if (crtc->mode_valid)
+    {
+        drmModeModeInfo *mode = &crtc->mode;
+        mvwprintw(pad, line++, 3, "Name: %s", mode->name);
+        mvwprintw(pad, line++, 3, "Resolution: %dx%d", mode->hdisplay, mode->vdisplay);
+        mvwprintw(pad, line++, 3, "Refresh Rate: %.2f Hz", mode->clock / (float)(mode->htotal * mode->vtotal));
+        mvwprintw(pad, line++, 3, "Type: 0x%x", mode->type);
+        mvwprintw(pad, line++, 3, "Flags: 0x%x", mode->flags);
+    }
+
+    mvwprintw(pad, line++, 1, "Gamma size: %u", crtc->gamma_size);
+
+    props = drmModeObjectGetProperties(drm_fd, crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
+    if (!props)
+    {
+        print_red_text(pad, line++, 1, "Failed to get properties for CRTC %u\n", crtc->crtc_id);
+        drmModeFreeCrtc(crtc);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    plane_resources = drmModeGetPlaneResources(drm_fd);
+    if (!plane_resources)
+    {
+        print_red_text(pad, line++, 3, "Failed to get plane resources");
+        return;
+    }
+
+    line++;
+    mvwprintw(pad, line++, 1, "Possible Planes for CRTC %d:", crtc->crtc_id);
+    line++;
+
+    wattron(pad, A_DIM);
+    for (size_t i = 0; i < plane_resources->count_planes; i++)
+    {
+        drmModePlane *plane = drmModeGetPlane(drm_fd, plane_resources->planes[i]);
+        if (plane)
+        {
+            if (plane->possible_crtcs & (1 << crtc_index))
+            {
+                mvwprintw(pad, line++, 3, "Plane %ld: ID %d, %s",
+                          i, plane->plane_id, plane->crtc_id ? "Active" : "Inactive");
+            }
+            drmModeFreePlane(plane);
+        }
+        else
+        {
+            print_red_text(pad, line++, 3, "Plane %ld: Failed to get plane", i);
+        }
+    }
+    wattroff(pad, A_DIM);
+    drmModeFreePlaneResources(plane_resources);
+
+    line++;
+    mvwprintw(pad, line++, 1, "Properties for CRTC %u:", crtc->crtc_id);
+    line++;
+
+    wattron(pad, A_DIM);
+    for (uint32_t i = 0; i < props->count_props; i++)
+    {
+        drmModePropertyPtr prop = drmModeGetProperty(drm_fd, props->props[i]);
+        if (prop)
+        {
+            uint64_t value = props->prop_values[i];
+            int remaining_width = getmaxx(pad) - getcurx(pad);
+            char value_str[256] = {0};
+
+            const char *immutability = (prop->flags & DRM_MODE_PROP_IMMUTABLE) ? " immutable" : "";
+            const char *atomicity = (prop->flags & DRM_MODE_PROP_ATOMIC) ? " atomic" : " ";
+
+            if (prop->flags & DRM_MODE_PROP_BLOB)
+            {
+                snprintf(value_str, sizeof(value_str), "blob = %lu", value);
+            }
+            else if (prop->flags & DRM_MODE_PROP_ENUM)
+            {
+                snprintf(value_str, sizeof(value_str), "enum (");
+                for (int j = 0; j < prop->count_enums; j++)
+                {
+                    if (j > 0)
+                    {
+                        snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), ", ");
+                    }
+                    snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), "%s", prop->enums[j].name);
+                }
+                snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), ") = %s", prop->enums[value].name);
+            }
+            else if (prop->flags & DRM_MODE_PROP_RANGE)
+            {
+                snprintf(value_str, sizeof(value_str), "range [%lu, %lu] = %lu",
+                         prop->values[0], prop->values[1], value);
+            }
+            else if (prop->flags & DRM_MODE_PROP_OBJECT)
+            {
+                snprintf(value_str, sizeof(value_str), "object %s = %lu",
+                         get_drm_object_type_name(prop->values[0]), value);
+            }
+            else
+            {
+                snprintf(value_str, sizeof(value_str), "%lu", value);
+            }
+
+            wattroff(pad, A_DIM);
+            mvwprintw(pad, line++, 2, "%d. %s", i, prop->name);
+            wattron(pad, A_DIM);
+            wprintw(pad, "%s%s: ", immutability, atomicity);
+
+            if ((int)strlen(value_str) > remaining_width)
+            {
+                char truncated_value[remaining_width + 1];
+                strncpy(truncated_value, value_str, remaining_width);
+                truncated_value[remaining_width] = '\0';
+                wprintw(pad, "%s", truncated_value);
+                mvwprintw(pad, line++, 2, "%s", value_str + remaining_width);
+            }
+            else
+            {
+                wprintw(pad, "%s", value_str);
+            }
+
+            drmModeFreeProperty(prop);
+        }
+    }
+    wattroff(pad, A_DIM);
+
+    drmModeFreeObjectProperties(props);
+
+    mvwprintw(pad, ++line, 1, "Press 'e' to go back.");
+
+    *content_line = line;
+    drmModeFreeCrtc(crtc);
+    drmModeFreeResources(resources);
+    return;
+
+err:
+    wrefresh(pad);
+    wgetch(pad);
+    return;
+}
+
+void display_connector(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    drmModeRes *resources = NULL;
+    drmModeConnector *connector = NULL;
+    int connector_index = -1;
+    char *endptr;
+
+    if (drm_fd < 0)
+    {
+        print_red_text(pad, line++, 1, "Failed to open DRM Device!\n");
+        goto err;
+    }
+
+    resources = drmModeGetResources(drm_fd);
+    if (!resources)
+    {
+        print_red_text(pad, line++, 1, "Failed to get DRM resources\n");
+        goto err;
+    }
+
+    connector_index = strtol(node->name + 9, &endptr, 10);
+
+    if (*endptr != '\0' || connector_index < 0 || connector_index >= resources->count_connectors)
+    {
+        mvwprintw(pad, line++, 1, "Invalid Connector name: %s\n", node->name);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    connector = drmModeGetConnector(drm_fd, resources->connectors[connector_index]);
+    if (!connector)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get Connector %d\n", connector_index);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "Connector ID: %d", connector->connector_id);
+    mvwprintw(pad, line++, 1, "No. of Encoders: %d", connector->count_encoders);
+    mvwprintw(pad, line++, 1, "Encoder ID: %d", connector->encoder_id);
+
+    line++;
+    mvwprintw(pad, line++, 1, "Possible Encoders: ");
+    for (int i = 0; i < connector->count_encoders; i++)
+    {
+        mvwprintw(pad, line++, 3, "Encoder %d: %d", i, connector->encoders[i]);
+    }
+
+    line++;
+    mvwprintw(pad, line++, 1, "Connection: ");
+    if (connector->connection == DRM_MODE_CONNECTED)
+        print_green_text(pad, -1, -1, "Connected");
+    else
+        print_red_text(pad, -1, -1, "Disconnected");
+
+    line++;
+    mvwprintw(pad, line++, 1, "Connector Type: %s", get_connector_type_name(connector->connector_type));
+    mvwprintw(pad, line++, 1, "Connector Type ID: %d", connector->connector_type_id);
+
+    mvwprintw(pad, line++, 1, "Subpixel Order: %d", connector->subpixel);
+    mvwprintw(pad, line++, 1, "MM Height: %d", connector->mmHeight);
+    mvwprintw(pad, line++, 1, "MM Width: %d", connector->mmWidth);
+
+    mvwprintw(pad, line++, 1, "Modes: %d", connector->count_modes);
+    wattron(pad, A_DIM);
+
+    line++;
+    for (int i = 0; i < connector->count_modes; i++)
+
+        if (connector->modes && i < connector->count_modes)
+        {
+            const drmModeModeInfo *mode = &connector->modes[i];
+
+            const char *preferred = (mode->type & DRM_MODE_TYPE_PREFERRED) ? " preferred" : "";
+            const char *driver = (mode->type & DRM_MODE_TYPE_DRIVER) ? " driver" : "";
+            const char *phsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? " phsync" : " nhsync";
+            const char *pvsync = (mode->flags & DRM_MODE_FLAG_PVSYNC) ? " pvsync" : " nvsync";
+            const char *interlace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? " interlace" : "";
+
+            double ratio = (double)mode->hdisplay / mode->vdisplay;
+            double refresh_rate = 0.0;
+            const char *aspect_ratio = NULL;
+
+            if (mode->vrefresh > 0)
+            {
+                refresh_rate = mode->vrefresh;
+            }
+            else if (mode->clock > 0 && mode->vtotal > 0)
+            {
+                refresh_rate = (double)(mode->clock * 1000) / (mode->htotal * mode->vtotal);
+            }
+
+            if (fabs(ratio - 16.0 / 9.0) < 0.01)
+            {
+                aspect_ratio = " 16:9";
+            }
+            else if (fabs(ratio - 4.0 / 3.0) < 0.01)
+            {
+                aspect_ratio = " 4:3";
+            }
+            else
+            {
+                aspect_ratio = "";
+            }
+
+            mvwprintw(pad, line++, 2,
+                      "%ux%u @%.2f%s%s%s%s%s%s",
+                      mode->hdisplay, mode->vdisplay, refresh_rate,
+                      driver, preferred, phsync, pvsync, interlace, aspect_ratio);
+        }
+
+    wattroff(pad, A_DIM);
+
+    mvwprintw(pad, line++, 1, "No. of Properties: %d", connector->count_props);
+
+    wattron(pad, A_DIM);
+    for (int i = 0; i < connector->count_props; i++)
+    {
+        drmModePropertyPtr prop = drmModeGetProperty(drm_fd, connector->props[i]);
+        if (prop)
+        {
+            char value_str[256] = {0};
+            uint64_t value = connector->prop_values[i];
+            int remaining_width = getmaxx(pad) - getcurx(pad);
+            const char *atomicity = (prop->flags & DRM_MODE_PROP_ATOMIC) ? " atomic" : " ";
+            const char *immutability = (prop->flags & DRM_MODE_PROP_IMMUTABLE) ? " immutable" : "";
+
+            if (prop->flags & DRM_MODE_PROP_BLOB)
+            {
+                snprintf(value_str, sizeof(value_str), "blob = %lu", value);
+            }
+            else if (prop->flags & DRM_MODE_PROP_ENUM)
+            {
+
+                snprintf(value_str, sizeof(value_str), "enum (");
+                for (int j = 0; j < prop->count_enums; j++)
+                {
+                    if (j > 0)
+                    {
+                        snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), ", ");
+                    }
+                    snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), "%s", prop->enums[j].name);
+                }
+                snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), ") = %s", prop->enums[value].name);
+            }
+            else if (prop->flags & DRM_MODE_PROP_RANGE)
+            {
+                snprintf(value_str, sizeof(value_str), "range [%lu, %lu] = %lu",
+                         prop->values[0], prop->values[1], value);
+            }
+            else if (prop->flags & DRM_MODE_PROP_OBJECT)
+            {
+                snprintf(value_str, sizeof(value_str), "object %s = %lu",
+                         get_drm_object_type_name(prop->values[0]), value);
+            }
+            else
+            {
+                snprintf(value_str, sizeof(value_str), "%lu", value);
+            }
+
+            wattroff(pad, A_DIM);
+            mvwprintw(pad, line++, 2, "%d. %s", i, prop->name);
+            wattron(pad, A_DIM);
+            wprintw(pad, "%s%s: ", immutability, atomicity);
+
+            if ((int)strlen(value_str) > remaining_width)
+            {
+                char truncated_value[remaining_width + 1];
+                strncpy(truncated_value, value_str, remaining_width);
+                truncated_value[remaining_width] = '\0';
+                wprintw(pad, "%s", truncated_value);
+                mvwprintw(pad, line++, 2, "%s", value_str + remaining_width);
+            }
+            else
+            {
+                wprintw(pad, "%s", value_str);
+            }
+
+            drmModeFreeProperty(prop);
+        }
+    }
+    wattroff(pad, A_DIM);
+
+    mvwprintw(pad, ++line, 1, "Press 'e' to go back.");
+
+    *content_line = line;
+    drmModeFreeConnector(connector);
+    drmModeFreeResources(resources);
+    return;
+
+err:
+    wrefresh(pad);
+    wgetch(pad);
+    return;
+}
+
+void display_encoder(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    drmModeRes *resources = NULL;
+    drmModeEncoder *encoder = NULL;
+    int encoder_id = -1;
+    char *endptr;
+
+    if (drm_fd < 0)
+    {
+        mvwprintw(pad, line++, 1, "Failed to open DRM Device!\n");
+        goto err;
+    }
+
+    resources = drmModeGetResources(drm_fd);
+    if (!resources)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get DRM resources\n");
+        goto err;
+    }
+
+    encoder_id = strtol(node->name + 7, &endptr, 10);
+    if (*endptr != '\0' || encoder_id < 0 || encoder_id >= resources->count_encoders)
+    {
+        mvwprintw(pad, line++, 1, "Invalid Encoder name: %s\n", node->name);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    encoder = drmModeGetEncoder(drm_fd, resources->encoders[encoder_id]);
+    if (!encoder)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get Encoder %d\n", encoder_id);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    line++;
+    mvwprintw(pad, line++, 1, "Encoder Type: ");
+    if (encoder->encoder_type == DRM_MODE_ENCODER_NONE)
+        print_red_text(pad, -1, -1, "NONE");
+    else
+        print_bold_text(pad, -1, -1, "%s", get_encoder_type_name(encoder->encoder_type));
+    line++;
+
+    mvwprintw(pad, line++, 1, "Encoder ID: %d", encoder->encoder_id);
+    mvwprintw(pad, line++, 1, "CRTC ID: %d", encoder->crtc_id);
+    mvwprintw(pad, line++, 1, "Possible CRTCs: %d", encoder->possible_crtcs);
+    mvwprintw(pad, line++, 1, "Possible Clones: %d", encoder->possible_clones);
+
+    mvwprintw(pad, ++line, 1, "Press 'e' to go back.");
+
+    *content_line = line;
+    drmModeFreeEncoder(encoder);
+    drmModeFreeResources(resources);
+    return;
+
+err:
+    wrefresh(pad);
+    wgetch(pad);
+    return;
+}
+
+void display_framebuffer(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    drmModeRes *resources = NULL;
+    drmModeFB *fb = NULL;
+    int framebuffer_id = -1;
+    char *endptr;
+
+    if (drm_fd < 0)
+    {
+        mvwprintw(pad, line++, 1, "Failed to open DRM Device!\n");
+        goto err;
+    }
+
+    resources = drmModeGetResources(drm_fd);
+    if (!resources)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get DRM resources\n");
+        goto err;
+    }
+
+    framebuffer_id = strtol(node->name + 11, &endptr, 10);
+    if (*endptr != '\0' || framebuffer_id < 0 || framebuffer_id >= resources->count_fbs)
+    {
+        mvwprintw(pad, line++, 1, "Invalid Framebuffer name: %s\n", node->name);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    fb = drmModeGetFB(drm_fd, resources->fbs[framebuffer_id]);
+    if (!fb)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get Framebuffer %d\n", framebuffer_id);
+        drmModeFreeResources(resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "Framebuffer ID: %d", fb->fb_id);
+    mvwprintw(pad, line++, 1, "Width: %d", fb->width);
+    mvwprintw(pad, line++, 1, "Height: %d", fb->height);
+    mvwprintw(pad, line++, 1, "Pitch: %d", fb->pitch);
+    mvwprintw(pad, line++, 1, "BPP: %d", fb->bpp);
+    mvwprintw(pad, line++, 1, "Depth: %d", fb->depth);
+    mvwprintw(pad, line++, 1, "Handle: %d", fb->handle);
+
+    mvwprintw(pad, ++line, 1, "Press 'e' to go back.");
+
+    *content_line = line;
+    drmModeFreeFB(fb);
+    drmModeFreeResources(resources);
+    return;
+
+err:
+    wrefresh(pad);
+    wgetch(pad);
+    return;
+}
+
+void display_plane(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    drmModePlaneRes *plane_resources = NULL;
+    drmModePlane *plane = NULL;
+    int plane_index = -1;
+    char *endptr;
+    drmModeObjectProperties *props = NULL;
+
+    if (drm_fd < 0)
+    {
+        mvwprintw(pad, line++, 1, "Failed to open DRM Device!\n");
+        goto err;
+    }
+
+    plane_resources = drmModeGetPlaneResources(drm_fd);
+    if (!plane_resources)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get DRM plane resources\n");
+        goto err;
+    }
+
+    plane_index = strtol(node->name + 5, &endptr, 10);
+    if (*endptr != '\0' || plane_index < 0 || plane_index >= (int)plane_resources->count_planes)
+    {
+        mvwprintw(pad, line++, 1, "Invalid Plane name: %s\n", node->name);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    plane = drmModeGetPlane(drm_fd, plane_resources->planes[plane_index]);
+    if (!plane)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get Plane %d\n", plane_index);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "Plane Index: %d", plane_index);
+    mvwprintw(pad, line++, 1, "Plane ID: %d", plane->plane_id);
+    mvwprintw(pad, line++, 1, "CRTC ID: %d", plane->crtc_id);
+    mvwprintw(pad, line++, 1, "Framebuffer ID: %d", plane->fb_id);
+    mvwprintw(pad, line++, 1, "Possible CRTCs: %d", plane->possible_crtcs);
+    mvwprintw(pad, line++, 1, "Gamma size: %u", plane->gamma_size);
+    mvwprintw(pad, line++, 1, "CRTC Position: (%d, %d)", plane->crtc_x, plane->crtc_y);
+
+    mvwprintw(pad, line++, 1, "Possible CRTC IDs: ");
+    for (int i = 0; i < 32; i++)
+    {
+        if (plane->possible_crtcs & (1 << i))
+        {
+            mvwprintw(pad, line++, 3, "CRTC %d", i);
+        }
+    }
+    line++;
+
+    mvwprintw(pad, line++, 1, "Number of formats: %u", plane->count_formats);
+    line++;
+
+    props = drmModeObjectGetProperties(drm_fd, plane->plane_id, DRM_MODE_OBJECT_PLANE);
+    if (!props)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get properties for Plane %u\n", plane->plane_id);
+        drmModeFreePlane(plane);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "Properties for Plane %u:", plane->plane_id);
+    line++;
+
+    for (uint32_t i = 0; i < props->count_props; i++)
+    {
+        drmModePropertyPtr prop = drmModeGetProperty(drm_fd, props->props[i]);
+        if (prop)
+        {
+            char value_str[256] = {0};
+            uint64_t value = props->prop_values[i];
+            int remaining_width = getmaxx(pad) - getcurx(pad);
+            const char *immutability = (prop->flags & DRM_MODE_PROP_IMMUTABLE) ? " immutable" : "";
+            const char *atomicity = (prop->flags & DRM_MODE_PROP_ATOMIC) ? " atomic" : " ";
+
+            if (prop->flags & DRM_MODE_PROP_BLOB)
+            {
+                snprintf(value_str, sizeof(value_str), "blob = %lu", value);
+            }
+            else if (prop->flags & DRM_MODE_PROP_ENUM)
+            {
+                snprintf(value_str, sizeof(value_str), "enum (");
+                for (int j = 0; j < prop->count_enums; j++)
+                {
+                    if (j > 0)
+                    {
+                        snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), ", ");
+                    }
+                    snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), "%s", prop->enums[j].name);
+                }
+                snprintf(value_str + strlen(value_str), sizeof(value_str) - strlen(value_str), ") = %s", prop->enums[value].name);
+            }
+            else if (prop->flags & DRM_MODE_PROP_RANGE)
+            {
+                snprintf(value_str, sizeof(value_str), "range [%lu, %lu] = %lu",
+                         prop->values[0], prop->values[1], value);
+            }
+            else if (prop->flags & DRM_MODE_PROP_OBJECT)
+            {
+                snprintf(value_str, sizeof(value_str), "object %s = %lu",
+                         get_drm_object_type_name(prop->values[0]), value);
+            }
+            else
+            {
+                snprintf(value_str, sizeof(value_str), "%lu", value);
+            }
+
+            wattroff(pad, A_DIM);
+            mvwprintw(pad, line++, 2, "%d. %s", i, prop->name);
+            wattron(pad, A_DIM);
+            wprintw(pad, "%s%s: ", immutability, atomicity);
+
+            if ((int)strlen(value_str) > remaining_width)
+            {
+                char truncated_value[remaining_width + 1];
+                strncpy(truncated_value, value_str, remaining_width);
+                truncated_value[remaining_width] = '\0';
+                wprintw(pad, "%s", truncated_value);
+                mvwprintw(pad, line++, 2, "%s", value_str + remaining_width);
+            }
+            else
+            {
+                wprintw(pad, "%s", value_str);
+            }
+
+            drmModeFreeProperty(prop);
+        }
+    }
+
+    drmModeFreeObjectProperties(props);
+
+    mvwprintw(pad, ++line, 1, "Press 'e' to go back.");
+
+    *content_line = line;
+    drmModeFreePlane(plane);
+    drmModeFreePlaneResources(plane_resources);
+    return;
+
+err:
+    wrefresh(pad);
+    wgetch(pad);
+    return;
+}
+
+void display_informats(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    drmModePlaneRes *plane_resources = NULL;
+    drmModePlane *plane = NULL;
+    drmModeObjectProperties *props = NULL;
+    int plane_index = -1;
+
+    if (drm_fd < 0)
+    {
+        mvwprintw(pad, line++, 1, "Failed to open DRM Device!\n");
+        goto err;
+    }
+
+    plane_resources = drmModeGetPlaneResources(drm_fd);
+    if (!plane_resources)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get DRM plane resources\n");
+        goto err;
+    }
+
+    if (strncmp(node->name, "IN_FORMATS", 10) == 0)
+    {
+        char *endptr;
+        plane_index = strtol(node->name + 10, &endptr, 10);
+        if (*endptr != '\0' || plane_index < 0 || plane_index >= (int)plane_resources->count_planes)
+        {
+            mvwprintw(pad, line++, 1, "Invalid Plane Index: %s\n", node->name);
+            drmModeFreePlaneResources(plane_resources);
+            goto err;
+        }
+    }
+    else
+    {
+        mvwprintw(pad, line++, 1, "Invalid format for node->name: %s\n", node->name);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    plane = drmModeGetPlane(drm_fd, plane_resources->planes[plane_index]);
+    if (!plane)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get Plane %d\n", plane_index);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "Plane Index: %d", plane_index);
+    mvwprintw(pad, line++, 1, "Plane ID: %d", plane->plane_id);
+
+    props = drmModeObjectGetProperties(drm_fd, plane->plane_id, DRM_MODE_OBJECT_PLANE);
+    if (!props)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get properties for Plane %u\n", plane->plane_id);
+        drmModeFreePlane(plane);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "IN_FORMATS for Plane %u:", plane->plane_id);
+    line++;
+
+    for (uint32_t i = 0; i < props->count_props; i++)
+    {
+        drmModePropertyPtr prop = drmModeGetProperty(drm_fd, props->props[i]);
+        if (prop)
+        {
+            uint64_t value = props->prop_values[i];
+
+            if (prop->flags & DRM_MODE_PROP_BLOB && strcmp(prop->name, "IN_FORMATS") == 0)
+            {
+                drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(drm_fd, value);
+                struct drm_format_modifier_blob *data = NULL;
+                uint32_t *fmts = NULL;
+                struct drm_format_modifier *mods = NULL;
+
+                if (!blob)
+                {
+                    log_message(LOG_ERROR, "drmModeGetPropertyBlob");
+                    return;
+                }
+
+                data = blob->data;
+
+                fmts = (uint32_t *)((char *)data + data->formats_offset);
+                mods = (struct drm_format_modifier *)((char *)data + data->modifiers_offset);
+
+                for (uint32_t j = 0; j < data->count_modifiers; j++)
+                {
+                    mvwprintw(pad, line++, 1, "Modifier %u: %s", j, get_basic_modifier_str(mods[j].modifier));
+                    mvwprintw(pad, line++, 3, "Formats: ");
+                    wattron(pad, A_DIM);
+                    for (uint32_t k = 0; k < data->count_formats; k++)
+                    {
+                        if (mods[j].formats & (1ULL << k))
+                        {
+                            mvwprintw(pad, line++, 5, "%s (0x%08x)", get_format_str(fmts[k]), fmts[k]);
+                        }
+                    }
+                    wattroff(pad, A_DIM);
+                }
+
+                drmModeFreePropertyBlob(blob);
+            }
+        }
+    }
+    drmModeFreeObjectProperties(props);
+    drmModeFreePlane(plane);
+    drmModeFreePlaneResources(plane_resources);
+    mvwprintw(pad, ++line, 1, "Press 'e' to go back.");
+
+    *content_line = line;
+    return;
+
+err:
+    wrefresh(pad);
+    return;
+}
+
+void display_formats(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    drmModePlaneRes *plane_resources = NULL;
+        drmModePlane *plane = NULL;
+    int plane_index = -1;
+
+    if (drm_fd < 0)
+    {
+        mvwprintw(pad, line++, 1, "Failed to open DRM Device!\n");
+        goto err;
+    }
+
+    plane_resources = drmModeGetPlaneResources(drm_fd);
+    if (!plane_resources)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get DRM plane resources\n");
+        goto err;
+    }
+
+    if (strncmp(node->name, "FORMATS", 7) == 0)
+    {
+        char *endptr;
+        plane_index = strtol(node->name + 7, &endptr, 10);
+        if (*endptr != '\0' || plane_index < 0 || plane_index >= (int)plane_resources->count_planes)
+        {
+            mvwprintw(pad, line++, 1, "Invalid Plane Index: %s\n", node->name);
+            drmModeFreePlaneResources(plane_resources);
+            goto err;
+        }
+    }
+    else
+    {
+        mvwprintw(pad, line++, 1, "Invalid format for node->name: %s\n", node->name);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    plane = drmModeGetPlane(drm_fd, plane_resources->planes[plane_index]);
+    if (!plane)
+    {
+        mvwprintw(pad, line++, 1, "Failed to get Plane %d\n", plane_index);
+        drmModeFreePlaneResources(plane_resources);
+        goto err;
+    }
+
+    mvwprintw(pad, line++, 1, "Plane ID: %d", plane->plane_id);
+
+    line++;
+    mvwprintw(pad, line++, 1, "No. of Plane formats %u:", plane->count_formats);
+    line++;
+
+    if (plane->count_formats > 0)
+    {
+        wattron(pad, A_DIM);
+        for (uint32_t i = 0; i < plane->count_formats; i++)
+        {
+            mvwprintw(pad, line++, 3, "%s (0x%08x)", get_format_str(plane->formats[i]), plane->formats[i]);
+        }
+        line++;
+        wattroff(pad, A_DIM);
+    }
+
+    drmModeFreePlane(plane);
+    drmModeFreePlaneResources(plane_resources);
+
+    mvwprintw(pad, ++line, 1, "Press 'e' to go back.");
+
+    *content_line = line;
+    return;
+
+err:
+    wrefresh(pad);
+    return;
+}
diff --git a/tools/displaytop/src/display_dump.c b/tools/displaytop/src/display_dump.c
new file mode 100644
index 000000000..f7ff84dbc
--- /dev/null
+++ b/tools/displaytop/src/display_dump.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "node.h"
+#include "utils.h"
+
+void single_file_dump(Node *node, const char *filePath, bool single)
+{
+    time_t now;
+    struct tm *t;
+    char dump_file_path[512];
+    FILE *file;
+    const int padHeight = 1000;
+    const int padWidth = 200;
+    WINDOW *virtualWin;
+    int line = 0;
+    char buffer[padWidth + 1];
+
+    if (!node || node->name[0] == '\0' || !node->display_function)
+    {
+        log_message(LOG_ERROR, "Invalid node provided for dumping");
+        return;
+    }
+
+    now = time(NULL);
+    t = localtime(&now);
+
+    if (single)
+    {
+        snprintf(dump_file_path, sizeof(dump_file_path), "%s/%s_%04d-%02d-%02d-%02d.%02d.%02d.txt",
+                 filePath, node->name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+                 t->tm_hour, t->tm_min, t->tm_sec);
+    }
+    else
+    {
+        snprintf(dump_file_path, sizeof(dump_file_path), "%s/%s.txt", filePath, node->name);
+    }
+
+    file = fopen(dump_file_path, "w");
+    if (!file)
+    {
+        log_message(LOG_ERROR, "Failed to open file: %s", dump_file_path);
+        return;
+    }
+    chmod(dump_file_path, 0777);
+
+    virtualWin = newwin(padHeight, padWidth, 0, 0);
+    if (!virtualWin)
+    {
+        log_message(LOG_ERROR, "Failed to create virtual window");
+        fclose(file);
+        return;
+    }
+
+    node->display_function(virtualWin, node, &line);
+
+    fprintf(file, "Dump Time: %04d-%02d-%02d %02d:%02d:%02d\n\n",
+            t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+            t->tm_hour, t->tm_min, t->tm_sec);
+
+    for (int y = 0; y < line; ++y)
+    {
+        wmove(virtualWin, y, 0);
+        winnstr(virtualWin, buffer, padWidth);
+        buffer[padWidth] = '\0';
+        fprintf(file, "%s\n", buffer);
+    }
+
+    log_message(LOG_INFO, "Dumped node '%s' to %s", node->name, dump_file_path);
+
+    delwin(virtualWin);
+    fclose(file);
+}
+
+static void recursive_dump_with_progress(Node *node, const char *parentDir,
+                                         int *current_count, int total_count, WINDOW *progress_win)
+{
+    char nodeDir[512];
+    bool hasChildren;
+    time_t now;
+    struct tm *t;
+
+    if (!node)
+        return;
+
+    hasChildren = (node->children_size > 0);
+
+    if (hasChildren)
+    {
+        now = time(NULL);
+        t = localtime(&now);
+
+        snprintf(nodeDir, sizeof(nodeDir), "%s/%s(%04d-%02d-%02d-%02d.%02d.%02d)",
+                 parentDir, node->name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+                 t->tm_hour, t->tm_min, t->tm_sec);
+
+        if (mkdir(nodeDir, 0777) == -1 && errno != EEXIST)
+        {
+            log_message(LOG_ERROR, "Error creating directory %s: %s", nodeDir, strerror(errno));
+            return;
+        }
+        (*current_count)++;
+    }
+    else
+    {
+        snprintf(nodeDir, sizeof(nodeDir), "%s", parentDir);
+    }
+
+    if (node->display_function)
+    {
+        single_file_dump(node, nodeDir, false);
+        (*current_count)++;
+    }
+
+    render_progress_bar(progress_win, *current_count, total_count);
+
+    for (int i = 0; i < node->children_size; ++i)
+    {
+        recursive_dump_with_progress(&node->children[i], nodeDir,
+                                     current_count, total_count, progress_win);
+    }
+}
+
+void display_dump_menu(Node *head)
+{
+    int total_nodes;
+    int winHeight, winWidth;
+    WINDOW *win;
+    int line;
+    int input;
+    int current_count;
+
+    if (!head)
+    {
+        log_message(LOG_ERROR, "Head node is NULL, cannot dump.");
+        return;
+    }
+
+    total_nodes = 0;
+    count_nodes(head, &total_nodes);
+
+    if (total_nodes == 0)
+    {
+        log_message(LOG_INFO, "No nodes found to dump.");
+        return;
+    }
+
+    getmaxyx(stdscr, winHeight, winWidth);
+
+    win = newwin(winHeight, winWidth, 0, 0);
+    wbkgd(win, COLOR_PAIR(6));
+    box(win, 0, 0);
+
+    draw_header(win, winWidth, "DUMP MENU", "Press ESC to exit");
+
+    line = 4;
+    wattron(win, A_BOLD);
+    mvwprintw(win, line++, 2, "You are about to dump %d nodes into files.", total_nodes);
+    line++;
+    mvwprintw(win, line++, 2, "Dumping menus under the path: %s", head->name);
+    line++;
+    wattroff(win, A_BOLD);
+    mvwprintw(win, line++, 2, "Proceed with dump? (y to confirm, ESC to cancel)");
+    wrefresh(win);
+
+    input = wgetch(win);
+    if (input != 'y' && input != 'Y')
+    {
+        delwin(win);
+        return;
+    }
+
+    log_message(LOG_INFO, "Starting dump from node: %s", head->name);
+
+    if (mkdir(DUMP_DIR, 0777) == -1 && errno != EEXIST)
+    {
+        log_message(LOG_ERROR, "Failed to create dump directory: %s", strerror(errno));
+        delwin(win);
+        return;
+    }
+
+    line++;
+    mvwprintw(win, line++, 2, "Progress:");
+    wrefresh(win);
+
+    current_count = 0;
+    recursive_dump_with_progress(head, DUMP_DIR, &current_count, total_nodes, win);
+
+    mvwprintw(win, line + 2, 2, "Dumping is over. Press any key to go back.");
+    wrefresh(win);
+    getch();
+
+    delwin(win);
+    endwin();
+}
\ No newline at end of file
diff --git a/tools/displaytop/src/display_search_bar.c b/tools/displaytop/src/display_search_bar.c
new file mode 100644
index 000000000..aa30b772b
--- /dev/null
+++ b/tools/displaytop/src/display_search_bar.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <form.h>
+
+#include "display.h"
+#include "utils.h"
+
+/**
+ * @brief Constructs a search path from a given node to the head node.
+ *
+ * This function constructs a search path string from the given node to the head node.
+ * The path is constructed by traversing from the given node up to the head node,
+ * appending each node's name to the path string, separated by " > ".
+ *
+ * @param node Pointer to the starting node.
+ * @param head Pointer to the head node until which path is required.
+ * @return A dynamically allocated string representing the search path.
+ *         The caller is responsible for freeing the allocated memory.
+ *         Returns NULL if either node or head is NULL.
+ */
+static char *construct_search_path(Node *node, Node *head)
+{
+    char buffer[1024];
+    char temp[1024];
+    char *path;
+    Node *current;
+
+    if (node == NULL || head == NULL)
+        return NULL;
+
+    buffer[0] = '\0';
+    path = NULL;
+    current = node;
+
+    while (current && strcmp(current->name, head->name) != 0)
+    {
+        if (snprintf(temp, sizeof(temp), "%s%s%s", current->name, buffer[0] ? " > " : "", buffer) >= (int)sizeof(temp))
+        {
+            log_message(LOG_ERROR, "Path string truncated: %s%s%s", current->name, buffer[0] ? " > " : "", buffer);
+            return NULL;
+        }
+        strncpy(buffer, temp, sizeof(buffer) - 1);
+        buffer[sizeof(buffer) - 1] = '\0';
+
+        current = current->parent;
+    }
+
+    path = (char *)malloc(strlen(buffer) + 1);
+    if (path)
+    {
+        strcpy(path, buffer);
+    }
+
+    return path;
+}
+
+/**
+ * @brief Displays the children of a given node in a new window.
+ *
+ * This function displays the children of a given node in a new window.
+ * The user can navigate through the children using the arrow keys and select a child by pressing Enter.
+ * The function returns the selected child node.
+ *
+ * @param node Pointer to the node whose children are to be displayed.
+ * @param head Pointer to the head node (current location in DisplayTop).
+ * @return Pointer to the selected child node.
+ *         Returns NULL if either node or node->children is NULL.
+ */
+static Node *display_children(Node *node, Node *head)
+{
+    int rows, cols;
+    int line;
+    int pad_pos;
+    int highlighted_index;
+    int ch;
+    WINDOW *pad;
+
+    if (node == NULL || node->children == NULL)
+        return NULL;
+
+    getmaxyx(stdscr, rows, cols);
+
+    line = 0;
+    pad_pos = 0;
+    highlighted_index = 0;
+    pad = newpad(100, cols - 2);
+
+    if (pad == NULL)
+        return NULL;
+
+    wbkgd(pad, COLOR_PAIR(6));
+
+    if (node->children_size > 0)
+    {
+        line++;
+
+        for (int i = 0; i < node->children_size; ++i)
+        {
+            if (highlighted_index == i)
+                wattron(pad, A_REVERSE);
+
+            mvwprintw(pad, line + i, 1, "%d. %s - %s", i + 1, node->children[i].name, construct_search_path(&node->children[i], head));
+            wattroff(pad, A_REVERSE);
+        }
+        prefresh(pad, pad_pos, 0, 8, 1, rows - 2, cols - 2);
+    }
+
+    while ((ch = getch()) != 27)
+    {
+        if (pad_pos > 0)
+            mvwprintw(pad, 0, cols - 5, "...");
+        else
+            mvwprintw(pad, 0, cols - 5, "   ");
+
+        if (pad_pos < node->children_size - (rows - 8))
+            mvwprintw(pad, rows - 1, cols - 5, "...");
+        else
+            mvwprintw(pad, rows - 1, cols - 5, "   ");
+
+        switch (ch)
+        {
+        case KEY_UP:
+            if (highlighted_index > 0)
+            {
+                highlighted_index--;
+                pad_pos = (highlighted_index < pad_pos) ? highlighted_index : pad_pos;
+            }
+            break;
+        case KEY_DOWN:
+            if (highlighted_index < node->children_size - 1)
+            {
+                highlighted_index++;
+                pad_pos = (highlighted_index >= pad_pos + rows - 8) ? highlighted_index - rows + 8 : pad_pos;
+            }
+            break;
+        case '\n':
+            delwin(pad);
+            return &node->children[highlighted_index];
+        default:
+            break;
+        }
+
+        for (int i = 0; i < node->children_size; ++i)
+        {
+            if (highlighted_index == i)
+                wattron(pad, A_REVERSE);
+
+            mvwprintw(pad, line + i, 1, "%d. %s - %s", i + 1, node->children[i].name, construct_search_path(&node->children[i], head));
+            wattroff(pad, A_REVERSE);
+        }
+
+        prefresh(pad, pad_pos, 0, 8, 1, rows - 2, cols - 2);
+    }
+
+    delwin(pad);
+    return head;
+}
+
+Node *display_search_bar(Node *head)
+{
+    int rows, cols;
+    WINDOW *win;
+    FIELD *fields[2];
+    FORM *form;
+    char input_buffer[256];
+    int ch, pos;
+    Node *results;
+    Node *result;
+
+    memset(input_buffer, 0, sizeof(input_buffer));
+    pos = 0;
+
+    getmaxyx(stdscr, rows, cols);
+    win = newwin(rows, cols, 0, 0);
+    wbkgd(win, COLOR_PAIR(6));
+    keypad(win, TRUE);
+    box(win, 0, 0);
+
+    print_bold_text(win, 1, 1, "Search Menu");
+    mvwprintw(win, 1, (cols - strlen("Searching under: %s")) / 2, "Searching under: %s", head->name);
+    mvwprintw(win, 1, cols - strlen("Press 'Esc' to exit ") - 1, "Press 'Esc' to exit");
+    mvwhline(win, 2, 1, 0, cols - 2);
+    mvwhline(win, 6, 1, 0, cols - 2);
+
+    fields[0] = new_field(1, cols - 4, 1, 1, 0, 0);
+    fields[1] = NULL;
+
+    set_field_back(fields[0], A_UNDERLINE);
+    field_opts_off(fields[0], O_AUTOSKIP);
+
+    form = new_form(fields);
+    set_form_win(form, win);
+    set_form_sub(form, derwin(win, 3, cols - 2, 3, 1));
+
+    wbkgd(form_sub(form), COLOR_PAIR(7));
+    box(form_sub(form), 0, 0);
+    post_form(form);
+    wrefresh(win);
+
+    while ((ch = getch()) != 27)
+    {
+        switch (ch)
+        {
+        case KEY_BACKSPACE:
+        case 127:
+        case 8:
+            if (pos > 0)
+            {
+                pos--;
+                input_buffer[pos] = '\0';
+                form_driver(form, REQ_DEL_PREV);
+            }
+            break;
+        case '\n':
+            if (pos > 0)
+            {
+                results = create_node("Search Results", NULL, NULL);
+                search_nodes(head, input_buffer, results);
+
+                if (results->children_size != 0)
+                {
+                    unpost_form(form);
+                    print_bold_text(win, 7, 2, "%d hits", results->children_size);
+                    wrefresh(win);
+                    result = display_children(results, head);
+                    free_form(form);
+                    free_field(fields[0]);
+                    delwin(win);
+                    endwin();
+                    return result;
+                }
+                else
+                {
+                    print_bold_text(win, 7, 2, "No results found");
+                }
+            }
+            break;
+        default:
+            if (pos < (int)(sizeof(input_buffer) - 1))
+            {
+                input_buffer[pos++] = ch;
+                input_buffer[pos] = '\0';
+                form_driver(form, ch);
+            }
+            break;
+        }
+        wrefresh(win);
+    }
+
+    unpost_form(form);
+    wrefresh(win);
+
+    getch();
+    free_form(form);
+    free_field(fields[0]);
+    delwin(win);
+    endwin();
+
+    return head;
+}
diff --git a/tools/displaytop/src/display_summary.c b/tools/displaytop/src/display_summary.c
new file mode 100644
index 000000000..a22ed097c
--- /dev/null
+++ b/tools/displaytop/src/display_summary.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "display.h"
+#include "utils.h"
+
+#define MAX_WIDTH getmaxx(pad)
+#define MAX_ENCODERS_PER_ROW ((MAX_WIDTH - 11) / 8)
+
+static void display_encoders(WINDOW *pad, drmModeRes *resources,int *line)
+{
+    int col_width = 6;
+    int max_per_row = MAX_ENCODERS_PER_ROW;
+    int start, end, i;
+    drmModeEncoder *encoder;
+
+    wattron(pad, A_BOLD);
+    mvwprintw(pad, (*line)++, 1, "Encoders - %d", resources->count_encoders);
+    wattroff(pad, A_BOLD);
+
+    for (start = 0; start < resources->count_encoders; start += max_per_row)
+    {
+        end = (start + max_per_row < resources->count_encoders) ? (start + max_per_row) : resources->count_encoders;
+
+        mvwprintw(pad, (*line)++, 2, "Encoder ID |");
+        for (i = start; i < end; i++)
+        {
+            encoder = drmModeGetEncoder(drm_fd, resources->encoders[i]);
+            if (encoder)
+            {
+                mvwprintw(pad, (*line) - 1, 14 + ((i - start) * (col_width + 1)), "%*d", col_width, encoder->encoder_id);
+                wprintw(pad, "|");
+                drmModeFreeEncoder(encoder);
+            }
+            else
+            {
+                mvwprintw(pad, (*line) - 1, 14 + ((i - start) * (col_width + 1)), "%*s", col_width, "N/A");
+                wprintw(pad, "|");
+            }
+        }
+
+        mvwprintw(pad, (*line)++, 2, "Type       |");
+        for (i = start; i < end; i++)
+        {
+            encoder = drmModeGetEncoder(drm_fd, resources->encoders[i]);
+            if (encoder)
+            {
+                mvwprintw(pad, (*line) - 1, 14 + ((i - start) * (col_width + 1)), "%*s", col_width, get_encoder_type_name(encoder->encoder_type));
+                wprintw(pad, "|");
+                drmModeFreeEncoder(encoder);
+            }
+            else
+            {
+                mvwprintw(pad, (*line) - 1, 14 + ((i - start) * (col_width + 1)), "%*s", col_width, "N/A");
+                wprintw(pad, "|");
+            }
+        }
+
+        mvwprintw(pad, (*line)++, 2, "CRTC ID    |");
+        for (i = start; i < end; i++)
+        {
+            encoder = drmModeGetEncoder(drm_fd, resources->encoders[i]);
+            if (encoder)
+            {
+                if (encoder->crtc_id != 0)
+                {
+                    wattron(pad, A_BOLD | COLOR_PAIR(2));
+                    mvwprintw(pad, (*line) - 1, 14 + ((i - start) * (col_width + 1)), "%*d", col_width, encoder->crtc_id);
+                    wattroff(pad, A_BOLD | COLOR_PAIR(2));
+                    wprintw(pad, "|");
+                }
+                else
+                {
+                    mvwprintw(pad, (*line) - 1, 14 + ((i - start) * (col_width + 1)), "%*d", col_width, encoder->crtc_id);
+                    wprintw(pad, "|");
+                }
+                drmModeFreeEncoder(encoder);
+            }
+            else
+            {
+                mvwprintw(pad, (*line) - 1, 14 + ((i - start) * (col_width + 1)), "%*s", col_width, "N/A");
+                wprintw(pad, "|");
+            }
+        }
+
+        (*line) += 1;
+    }
+}
+
+void display_summary(WINDOW *pad, Node *node, int *content_line)
+{
+    int line = 0;
+    int col_width;
+    drmModeRes *resources = NULL;
+    drmModeCrtc *crtc = NULL;
+    drmVersionPtr version = NULL;
+    uint64_t value;
+    drmDevicePtr devices[8];
+    int device_count;
+
+    wclear(pad);
+
+    print_bold_text(pad, line++, 1, "%s Summary", node->name);
+    line++;
+
+    print_dim_text(pad, line++, 1, "Fetching details for card: %s", find_drm_device(true));
+    line++;
+
+    if (drm_fd < 0)
+    {
+        mvwprintw(pad, line++, 2, "Failed to open DRM Device!\n");
+        goto error;
+    }
+
+    resources = drmModeGetResources(drm_fd);
+
+    if (!resources)
+    {
+        mvwprintw(pad, line++, 2, "Failed to get DRM resources\n");
+        goto error;
+    }
+
+    wattron(pad, A_BOLD);
+    mvwprintw(pad, line++, 1, "CRTCs - %d", resources->count_crtcs);
+    wattroff(pad, A_BOLD);
+
+    col_width = 10;
+    mvwprintw(pad, line++, 2, "CRTC ID   |");
+    for (int i = 0; i < resources->count_crtcs; i++)
+    {
+        crtc = drmModeGetCrtc(drm_fd, resources->crtcs[i]);
+
+        if (crtc)
+        {
+            if (crtc->mode_valid)
+            {
+                wattron(pad, A_BOLD | COLOR_PAIR(2));
+                mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*d", col_width, crtc->crtc_id);
+                wattroff(pad, A_BOLD | COLOR_PAIR(2));
+                wprintw(pad, "|");
+            }
+            else
+            {
+                wattron(pad, A_BOLD | COLOR_PAIR(3));
+                mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*d", col_width, crtc->crtc_id);
+                wattroff(pad, A_BOLD | COLOR_PAIR(3));
+                wprintw(pad, "|");
+            }
+            drmModeFreeCrtc(crtc);
+        }
+        else
+        {
+            mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*s|", col_width, "N/A");
+        }
+    }
+    line++;
+
+    wattron(pad, A_BOLD);
+    mvwprintw(pad, line++, 1, "Connectors - %d", resources->count_connectors);
+    wattroff(pad, A_BOLD);
+
+    col_width = 10;
+    mvwprintw(pad, line++, 2, "Connectors|");
+    for (int i = 0; i < resources->count_connectors; i++)
+    {
+        drmModeConnector *connector = drmModeGetConnector(drm_fd, resources->connectors[i]);
+        if (connector)
+        {
+            if (connector->connection == DRM_MODE_CONNECTED)
+            {
+                wattron(pad, A_BOLD | COLOR_PAIR(2));
+                mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*d", col_width, connector->connector_id);
+                wattroff(pad, A_BOLD | COLOR_PAIR(2));
+                wprintw(pad, "|");
+            }
+            else
+            {
+                wattron(pad, A_BOLD | COLOR_PAIR(3));
+                mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*d", col_width, connector->connector_id);
+                wattroff(pad, A_BOLD | COLOR_PAIR(3));
+                wprintw(pad, "|");
+            }
+            drmModeFreeConnector(connector);
+        }
+        else
+        {
+            mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*s|", col_width, "N/A");
+        }
+    }
+
+    mvwprintw(pad, line++, 2, "Type      |");
+    for (int i = 0; i < resources->count_connectors; i++)
+    {
+        drmModeConnector *connector = drmModeGetConnector(drm_fd, resources->connectors[i]);
+        if (connector)
+        {
+            const char *type_name = get_connector_type_name(connector->connector_type);
+            mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*s|", col_width, type_name);
+            drmModeFreeConnector(connector);
+        }
+        else
+        {
+            mvwprintw(pad, line - 1, 13 + (i * (col_width + 1)), "%*s|", col_width, "N/A");
+        }
+    }
+    line++;
+
+    display_encoders(pad, resources, &line);
+
+    version = drmGetVersion(drm_fd);
+    if (version)
+    {
+        wattron(pad, A_BOLD);
+        mvwprintw(pad, line++, 1, "DRM Driver: %s", version->name);
+        wattroff(pad, A_BOLD);
+        drmFreeVersion(version);
+    }
+    else
+    {
+        mvwprintw(pad, line++, 2, "Failed to get DRM version");
+    }
+
+    drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &value);
+    mvwprintw(pad, line++, 2, "DRM_CAP_TIMESTAMP_MONOTONIC: %lu", value);
+
+    drmGetCap(drm_fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &value);
+    mvwprintw(pad, line++, 2, "DRM_CAP_CRTC_IN_VBLANK_EVENT: %lu", value);
+
+    drmGetCap(drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
+    mvwprintw(pad, line++, 2, "DRM_CAP_ASYNC_PAGE_FLIP: %lu", value);
+
+    drmGetCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, &value);
+    mvwprintw(pad, line++, 2, "DRM_CLIENT_CAP_ATOMIC: %lu", value);
+
+    drmGetCap(drm_fd, DRM_CAP_ADDFB2_MODIFIERS, &value);
+    mvwprintw(pad, line++, 2, "DRM_CAP_ADDFB2_MODIFIERS: %lu", value);
+    line++;
+
+    device_count = drmGetDevices2(0, devices, 8);
+    if (device_count < 0)
+    {
+        mvwprintw(pad, line++, 2, "Failed to get DRM devices");
+    }
+    else
+    {
+        for (int i = 0; i < device_count; i++)
+        {
+            if (devices[i]->available_nodes & (1 << DRM_NODE_PRIMARY))
+            {
+                char available_nodes[256] = "";
+
+                wattron(pad, A_BOLD);
+                mvwprintw(pad, line++, 1, "Device: PCI %04x:%04x", devices[i]->deviceinfo.pci->vendor_id, devices[i]->deviceinfo.pci->device_id);
+                wattroff(pad, A_BOLD);
+
+                if (devices[i]->available_nodes & (1 << DRM_NODE_PRIMARY))
+                {
+                    strcat(available_nodes, "primary, ");
+                }
+                if (devices[i]->available_nodes & (1 << DRM_NODE_RENDER))
+                {
+                    strcat(available_nodes, "render, ");
+                }
+                if (strlen(available_nodes) > 0)
+                {
+                    available_nodes[strlen(available_nodes) - 2] = '\0';
+                }
+                mvwprintw(pad, line++, 2, "Available nodes: %s", available_nodes);
+            }
+        }
+        drmFreeDevices(devices, device_count);
+    }
+
+    drmModeFreeResources(resources);
+
+    *content_line = line;
+    return;
+
+error:
+    if (resources)
+    {
+        drmModeFreeResources(resources);
+    }
+
+    wrefresh(pad);
+    *content_line = line;
+    return;
+}
diff --git a/tools/displaytop/src/log.c b/tools/displaytop/src/log.c
new file mode 100644
index 000000000..6d38fee07
--- /dev/null
+++ b/tools/displaytop/src/log.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "log.h"
+
+static FILE *log_file = NULL;
+
+void init_log_system(void)
+{
+    log_file = fopen(LOG_FILE, "a");
+    if (!log_file)
+    {
+        fprintf(stderr, "Failed to open log file: %s\n", LOG_FILE);
+    }
+}
+
+void log_message(int level, const char *format, ...)
+{
+    time_t now;
+    struct tm *t;
+    char time_str[20];
+    const char *level_str;
+    va_list args;
+
+    if (!log_file)
+        return;
+
+    now = time(NULL);
+    t = localtime(&now);
+    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", t);
+
+    switch (level)
+    {
+    case LOG_INFO:
+        level_str = "INFO";
+        break;
+    case LOG_WARNING:
+        level_str = "WARNING";
+        break;
+    case LOG_ERROR:
+        level_str = "ERROR";
+        break;
+    default:
+        level_str = "UNKNOWN";
+        break;
+    }
+
+    va_start(args, format);
+    fprintf(log_file, "[%s] [%s] ", time_str, level_str);
+    vfprintf(log_file, format, args);
+    fprintf(log_file, "\n");
+    va_end(args);
+
+    fflush(log_file);
+}
+
+void close_log_system(void)
+{
+    if (log_file)
+    {
+        fclose(log_file);
+        log_file = NULL;
+    }
+}
diff --git a/tools/displaytop/src/main.c b/tools/displaytop/src/main.c
new file mode 100644
index 000000000..32b273e70
--- /dev/null
+++ b/tools/displaytop/src/main.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <ncurses.h>
+#include <menu.h>
+#include "node.h"
+#include "data.h"
+#include "display.h"
+#include "populate.h"
+#include "utils.h"
+
+int main(int argc, char *argv[])
+{
+    handle_cli_args(argc, argv);
+
+    init_log_system();
+
+    initscr();
+    cbreak();
+    noecho();
+    start_color();
+    set_escdelay(0);
+    keypad(stdscr, TRUE);
+
+    init_pair(1, COLOR_WHITE, COLOR_BLACK);
+    init_pair(2, COLOR_GREEN, COLOR_BLACK);
+    init_pair(3, COLOR_RED, COLOR_BLACK);
+    init_pair(4, COLOR_BLACK, COLOR_GREEN);
+    init_pair(5, COLOR_BLACK, COLOR_RED);
+    init_pair(6, COLOR_BLUE, COLOR_BLACK);
+    init_pair(7, COLOR_BLACK, COLOR_BLUE);
+
+    check_and_load_driver();
+    open_primary_drm_device();
+    populate_data();
+    display_win(stdscr, root);
+
+    endwin();
+    close_primary_drm_device();
+    close_log_system();
+
+    return 0;
+}
diff --git a/tools/displaytop/src/node.c b/tools/displaytop/src/node.c
new file mode 100644
index 000000000..4f1ca33a1
--- /dev/null
+++ b/tools/displaytop/src/node.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "node.h"
+
+Node* create_node(const char* name, void (*display_function)(WINDOW*, Node*, int*), Node* parent)
+{
+    Node *new_node = (Node *)malloc(sizeof(Node));
+    strncpy(new_node->name, name, sizeof(new_node->name) - 1);
+    new_node->name[sizeof(new_node->name) - 1] = '\0';
+    new_node->display_function = display_function;
+    new_node->parent = parent;
+    new_node->children = NULL;
+    new_node->children_size = 0;
+    return new_node;
+}
+
+void add_child(Node *parent, Node *child)
+{
+    parent->children = (Node *)realloc(parent->children, sizeof(Node) * (parent->children_size + 1));
+    parent->children[parent->children_size] = *child;
+    parent->children_size++;
+}
+
+void free_tree(Node *root)
+{
+    int i;
+
+    if (!root)
+        return;
+
+    for (i = 0; i < root->children_size; i++)
+    {
+        free_tree(&root->children[i]);
+    }
+    free(root->children);
+    free(root);
+}
+
+void print_path(Node *node)
+{
+    if (node->parent)
+    {
+        print_path(node->parent);
+        printw(" > %s", node->name);
+    }
+    else
+    {
+        printw("%s", node->name);
+    }
+}
+
+char *get_path(Node *node)
+{
+    size_t path_size;
+    Node *current;
+    char *path;
+    char *new_path;
+
+    if (!node)
+    {
+        return NULL;
+    }
+
+    path_size = 1;
+    current = node;
+    while (current)
+    {
+        path_size += strlen(current->name) + 3;
+        current = current->parent;
+    }
+
+    path = (char *)malloc(path_size);
+    if (!path)
+    {
+        return NULL;
+    }
+    path[0] = '\0';
+
+    current = node;
+    while (current)
+    {
+        new_path = (char *)malloc(strlen(current->name) + strlen(path) + 4);
+        if (!new_path)
+        {
+            free(path);
+            return NULL;
+        }
+
+        if (path[0] == '\0')
+        {
+            snprintf(new_path, strlen(current->name) + 1, "%s", current->name);
+        }
+        else
+        {
+            snprintf(new_path, strlen(current->name) + strlen(path) + 4, "%s > %s", current->name, path);
+        }
+
+        free(path);
+        path = new_path;
+        current = current->parent;
+    }
+
+    return path;
+}
+
+void count_nodes(Node *node, int *count)
+{
+    int i;
+
+    if (node == NULL)
+        return;
+
+    (*count)++;
+
+    for (i = 0; i < node->children_size; i++)
+    {
+        count_nodes(&node->children[i], count);
+    }
+}
\ No newline at end of file
diff --git a/tools/displaytop/src/populate.c b/tools/displaytop/src/populate.c
new file mode 100644
index 000000000..0872b0b43
--- /dev/null
+++ b/tools/displaytop/src/populate.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "data.h"
+#include "populate.h"
+
+void populate_data(void)
+{
+    root = create_node("Display Top", display_summary, NULL);
+
+    initialize_display_config();
+}
diff --git a/tools/displaytop/src/populate_display_config.c b/tools/displaytop/src/populate_display_config.c
new file mode 100644
index 000000000..a44efaf9e
--- /dev/null
+++ b/tools/displaytop/src/populate_display_config.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "populate.h"
+
+int create_crtc_nodes(drmModeRes *resources, Node *parent_node, int filter);
+int create_connector_nodes(drmModeRes *resources, Node *parent_node, int filter);
+int create_encoder_nodes(drmModeRes *resources, Node *parent_node, int filter);
+int create_framebuffer_nodes(drmModeRes *resources, Node *parent_node, int filter);
+int create_plane_nodes(Node *parent_node, int filter);
+
+int create_crtc_nodes(drmModeRes *resources, Node *parent_node, int filter)
+{
+    int crtc_count;
+    int i;
+    char crtc_name[10];
+    Node *crtc_node;
+    drmModeCrtc *crtc;
+
+    crtc_count = resources->count_crtcs;
+    log_message(LOG_INFO, "Creating CRTC nodes");
+
+    for (i = 0; i < crtc_count; ++i)
+    {
+        if (filter != -1 && i != filter)
+        {
+            continue;
+        }
+
+        snprintf(crtc_name, sizeof(crtc_name), "CRTC%d", i % 100);
+        crtc_node = create_node(crtc_name, display_crtc, parent_node);
+
+        crtc = drmModeGetCrtc(drm_fd, resources->crtcs[i]);
+        if (!crtc)
+        {
+            log_message(LOG_ERROR, "drmModeGetCrtc failed for CRTC %d", i % 100);
+            drmModeFreeResources(resources);
+            return 0;
+        }
+
+        create_plane_nodes(crtc_node, i);
+        create_encoder_nodes(resources, crtc_node, i);
+        create_connector_nodes(resources, crtc_node, i);
+
+        add_child(parent_node, crtc_node);
+
+        drmModeFreeCrtc(crtc);
+    }
+
+    return crtc_count;
+}
+
+int create_connector_nodes(drmModeRes *resources, Node *parent_node, int filter)
+{
+    int connector_count;
+    int i;
+    char connector_name[15];
+    Node *connector_node;
+
+    connector_count = resources->count_connectors;
+    log_message(LOG_INFO, "Creating Connector nodes");
+
+    for (i = 0; i < connector_count; ++i)
+    {
+        if (filter != -1 && i != filter)
+        {
+            continue;
+        }
+
+        snprintf(connector_name, sizeof(connector_name), "Connector%d", i % 100);
+        connector_node = create_node(connector_name, display_connector, parent_node);
+        add_child(parent_node, connector_node);
+    }
+
+    return connector_count;
+}
+
+int create_encoder_nodes(drmModeRes *resources, Node *parent_node, int filter)
+{
+    int encoder_count;
+    int i;
+    char encoder_name[15];
+    Node *encoder_node;
+
+    encoder_count = resources->count_encoders;
+    log_message(LOG_INFO, "Creating Encoder nodes");
+
+    for (i = 0; i < encoder_count; ++i)
+    {
+        if (filter != -1 && i != filter)
+        {
+            continue;
+        }
+
+        snprintf(encoder_name, sizeof(encoder_name), "Encoder%d", i % 100);
+        encoder_node = create_node(encoder_name, display_encoder, parent_node);
+        add_child(parent_node, encoder_node);
+    }
+
+    return encoder_count;
+}
+
+int create_framebuffer_nodes(drmModeRes *resources, Node *parent_node, int filter)
+{
+    int framebuffer_count;
+    int i;
+    char framebuffer_name[15];
+    Node *framebuffer_node;
+
+    framebuffer_count = resources->count_fbs;
+    log_message(LOG_INFO, "Creating Framebuffer nodes for %d framebuffers", framebuffer_count);
+
+    for (i = 0; i < framebuffer_count; ++i)
+    {
+        if (filter != -1 && i != filter)
+        {
+            continue;
+        }
+
+        snprintf(framebuffer_name, sizeof(framebuffer_name), "Framebuffer%d", i % 100);
+        framebuffer_node = create_node(framebuffer_name, display_framebuffer, parent_node);
+        add_child(parent_node, framebuffer_node);
+    }
+
+    return framebuffer_count;
+}
+
+int create_plane_nodes(Node *parent_node, int filter)
+{
+    drmModePlaneRes *plane_resources;
+    int plane_count;
+    int i;
+    drmModePlane *plane;
+    char plane_name[10];
+    char in_formats_name[15];
+    char out_formats_name[15];
+    Node *plane_node;
+    Node *in_formats_node;
+    Node *out_formats_node;
+
+    plane_resources = drmModeGetPlaneResources(drm_fd);
+    if (!plane_resources)
+    {
+        log_message(LOG_ERROR, "drmModeGetPlaneResources failed");
+        return 0;
+    }
+
+    plane_count = plane_resources->count_planes;
+    log_message(LOG_INFO, "Creating Plane nodes");
+
+    for (i = 0; i < plane_count; ++i)
+    {
+        plane = drmModeGetPlane(drm_fd, plane_resources->planes[i]);
+        if (!plane)
+        {
+            log_message(LOG_ERROR, "drmModeGetPlane failed for Plane %d", i % 100);
+            drmModeFreePlaneResources(plane_resources);
+            return 0;
+        }
+
+        if (filter != -1 && !(plane->possible_crtcs & (1 << filter)))
+        {
+            drmModeFreePlane(plane);
+            continue;
+        }
+
+        snprintf(plane_name, sizeof(plane_name), "Plane%d", i % 100);
+        plane_node = create_node(plane_name, display_plane, parent_node);
+
+        snprintf(in_formats_name, sizeof(in_formats_name), "IN_FORMATS%d", i % 100);
+        in_formats_node = create_node(in_formats_name, display_informats, plane_node);
+        add_child(plane_node, in_formats_node);
+
+        snprintf(out_formats_name, sizeof(out_formats_name), "FORMATS%d", i % 100);
+        out_formats_node = create_node(out_formats_name, display_formats, plane_node);
+        add_child(plane_node, out_formats_node);
+
+        add_child(parent_node, plane_node);
+        drmModeFreePlane(plane);
+    }
+
+    drmModeFreePlaneResources(plane_resources);
+    return plane_count;
+}
+
+void initialize_display_config(void)
+{
+    Node *display_config;
+    Node *crtc_nodes;
+    Node *plane_nodes;
+    Node *connector_nodes;
+    Node *encoder_nodes;
+    Node *framebuffer_nodes;
+    drmModeRes *resources;
+
+    log_message(LOG_INFO, "Initializing Display Configuration");
+
+    display_config = create_node("Display Configuration", NULL, root);
+    if (!display_config)
+    {
+        log_message(LOG_ERROR, "Failed to create Display Configuration node");
+        return;
+    }
+
+    if (drm_fd < 0)
+    {
+        log_message(LOG_ERROR, "Failed to open primary DRM device");
+        return;
+    }
+
+    resources = drmModeGetResources(drm_fd);
+    if (!resources)
+    {
+        log_message(LOG_ERROR, "drmModeGetResources failed");
+        return;
+    }
+
+    /* Create CRTC nodes */
+    crtc_nodes = create_node("CRTCs", NULL, display_config);
+    if (!crtc_nodes)
+    {
+        log_message(LOG_ERROR, "Failed to create CRTC nodes");
+        drmModeFreeResources(resources);
+        return;
+    }
+    create_crtc_nodes(resources, crtc_nodes, -1);
+    add_child(display_config, crtc_nodes);
+
+    /* Create Plane nodes */
+    plane_nodes = create_node("Planes", NULL, display_config);
+    if (!plane_nodes)
+    {
+        log_message(LOG_ERROR, "Failed to create Plane nodes");
+        drmModeFreeResources(resources);
+        return;
+    }
+    create_plane_nodes(plane_nodes, -1);
+    add_child(display_config, plane_nodes);
+
+    /* Create Connector nodes */
+    connector_nodes = create_node("Connectors", NULL, display_config);
+    if (!connector_nodes)
+    {
+        log_message(LOG_ERROR, "Failed to create Connector nodes");
+        drmModeFreeResources(resources);
+        return;
+    }
+    create_connector_nodes(resources, connector_nodes, -1);
+    add_child(display_config, connector_nodes);
+
+    /* Create Encoder nodes */
+    encoder_nodes = create_node("Encoders", NULL, display_config);
+    if (!encoder_nodes)
+    {
+        log_message(LOG_ERROR, "Failed to create Encoder nodes");
+        drmModeFreeResources(resources);
+        return;
+    }
+    create_encoder_nodes(resources, encoder_nodes, -1);
+    add_child(display_config, encoder_nodes);
+
+    /* Initialize Framebuffers */
+    framebuffer_nodes = create_node("Framebuffers", NULL, display_config);
+    if (!framebuffer_nodes)
+    {
+        log_message(LOG_ERROR, "Failed to create Framebuffer nodes");
+        drmModeFreeResources(resources);
+        return;
+    }
+    create_framebuffer_nodes(resources, framebuffer_nodes, -1);
+    add_child(display_config, framebuffer_nodes);
+
+    add_child(root, display_config);
+    drmModeFreeResources(resources);
+}
\ No newline at end of file
diff --git a/tools/displaytop/src/utils.c b/tools/displaytop/src/utils.c
new file mode 100644
index 000000000..ec8c8a649
--- /dev/null
+++ b/tools/displaytop/src/utils.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "utils.h"
+
+char *read_file(const char *filename)
+{
+    FILE *file;
+    long length;
+    char *data;
+
+    file = fopen(filename, "rb");
+    if (!file)
+    {
+        log_message(LOG_ERROR, "File opening failed");
+        return NULL;
+    }
+
+    fseek(file, 0, SEEK_END);
+    length = ftell(file);
+    fseek(file, 0, SEEK_SET);
+
+    data = (char *)malloc(length + 1);
+    if (data)
+    {
+        fread(data, 1, length, file);
+        data[length] = '\0';
+    }
+
+    fclose(file);
+    return data;
+}
+
+void strip_whitespace(char *str)
+{
+    char *start;
+    char *end;
+
+    start = str;
+
+    while (isspace((unsigned char)*start))
+        start++;
+
+    if (*start == 0)
+    {
+        *str = 0;
+        return;
+    }
+
+    end = start + strlen(start) - 1;
+    while (end > start && isspace((unsigned char)*end))
+        end--;
+
+    *(end + 1) = 0;
+
+    if (start != str)
+        memmove(str, start, end - start + 2);
+}
+
+void ensure_dump_directory(void)
+{
+    struct stat st;
+    int stat_result;
+    int mkdir_result;
+
+    stat_result = stat(DUMP_DIR, &st);
+    if (stat_result == 0 && S_ISDIR(st.st_mode))
+    {
+        log_message(LOG_INFO, "Directory %s already exists.\n", DUMP_DIR);
+        return;
+    }
+
+    mkdir_result = mkdir(DUMP_DIR, 0755);
+    if (mkdir_result == 0)
+    {
+        log_message(LOG_INFO, "Directory %s created successfully.\n", DUMP_DIR);
+    }
+    else
+    {
+        log_message(LOG_ERROR, "mkdir failed: %s\n", strerror(errno));
+    }
+}
\ No newline at end of file
diff --git a/tools/displaytop/src/utils_cli.c b/tools/displaytop/src/utils_cli.c
new file mode 100644
index 000000000..348169b4d
--- /dev/null
+++ b/tools/displaytop/src/utils_cli.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "utils.h"
+
+static void print_help(void)
+{
+    printf("Usage: sudo ./displaytop \n\n");
+
+    printf("for help: ./displaytop [OPTIONS]\n\n");
+    printf("Options:\n");
+    printf("  --help      Show this help message and exit\n");
+    printf("  --version   Show version information\n");
+    printf(" for more help read the documentation at the /docs folder. \n\n");
+
+    printf("ALL YOU NEED TO DO IS RUN THE TOOL WITH SUDO PERMISSION.\n\n");
+
+    printf("> Note:\n");
+    printf("> - Running DisplayTop without `sudo` may result in some menu options not being visible.\n");
+    printf("> - If the respective JSON files for MMIO and DPCD registers are not present, the corresponding menus will not be available.\n");
+    printf("> - The Ftrace menu will not be able to provide register name information without the aforementioned JSON files.\n\n");
+}
+
+static void print_version(void)
+{
+    printf("DisplayTop v1.0.0\n");
+}
+
+void handle_cli_args(int argc, char *argv[])
+{
+    if (argc > 1)
+    {
+        if (strcmp(argv[1], "--help") == 0)
+        {
+            print_help();
+            exit(0);
+        }
+        else if (strcmp(argv[1], "--version") == 0)
+        {
+            print_version();
+            exit(0);
+        }
+        else
+        {
+            printf("Unknown option: %s\n", argv[1]);
+            printf("Use --help for usage information.\n");
+            exit(1);
+        }
+    }
+}
diff --git a/tools/displaytop/src/utils_display.c b/tools/displaytop/src/utils_display.c
new file mode 100644
index 000000000..a1c9ad983
--- /dev/null
+++ b/tools/displaytop/src/utils_display.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "utils.h"
+
+void draw_header(WINDOW *win, int winWidth, const char *title, const char *helper)
+{
+    werase(win);
+    box(win, 0, 0);
+
+    wattron(win, A_BOLD);
+    mvwprintw(win, 1, 2, "%s", title);
+    mvwprintw(win, 1, winWidth - strlen(helper) - 2, "%s", helper);
+    wattroff(win, A_BOLD);
+
+    mvwhline(win, 2, 1, ACS_HLINE, winWidth - 2);
+    wrefresh(win);
+}
+
+void render_progress_bar(WINDOW *win, int current, int total)
+{
+    float progress;
+    int bar_start_y, bar_start_x, bar_width, filled, percent, i;
+
+    if (total == 0)
+        return;
+
+    progress = (float)current / total;
+    if (progress > 1.0f)
+        progress = 1.0f;
+
+    bar_start_y = 10;
+    bar_start_x = 2;
+    bar_width = getmaxx(win) - 14;
+    if (bar_width < 1)
+        return;
+
+    filled = (int)(progress * bar_width + 0.5f);
+
+    wattron(win, A_BOLD);
+    mvwprintw(win, bar_start_y, bar_start_x, "[");
+    wattroff(win, A_BOLD);
+
+    for (i = 0; i < bar_width; ++i)
+    {
+        if (i < filled)
+        {
+            wattron(win, COLOR_PAIR(7));
+            waddch(win, ' ');
+            wattroff(win, COLOR_PAIR(7));
+        }
+        else
+        {
+            wattron(win, COLOR_PAIR(2));
+            waddch(win, ' ');
+            wattroff(win, COLOR_PAIR(2));
+        }
+    }
+
+    wattron(win, A_BOLD);
+    waddch(win, ']');
+    percent = (int)(progress * 100.0f + 0.5f);
+    mvwprintw(win, bar_start_y, bar_start_x + bar_width + 2, "%3d%%", percent);
+    wattroff(win, A_BOLD);
+
+    wrefresh(win);
+}
+
+void print_bold_text(WINDOW *win, int line, int col, const char *text, ...)
+{
+    va_list args;
+    va_start(args, text);
+
+    wattron(win, A_BOLD);
+    wmove(win, line, col);
+    vw_printw(win, text, args);
+    wattroff(win, A_BOLD);
+
+    va_end(args);
+}
+
+void print_dim_text(WINDOW *win, int line, int col, const char *text, ...)
+{
+    va_list args;
+    va_start(args, text);
+
+    wattron(win, A_DIM);
+    wmove(win, line, col);
+    vw_printw(win, text, args);
+    wattroff(win, A_DIM);
+
+    va_end(args);
+}
+
+void print_red_text(WINDOW *win, int line, int col, const char *text, ...)
+{
+    va_list args;
+    va_start(args, text);
+
+    wattron(win, COLOR_PAIR(3));
+    wmove(win, line, col);
+    vw_printw(win, text, args);
+    wattroff(win, COLOR_PAIR(3));
+
+    va_end(args);
+}
+
+void print_green_text(WINDOW *win, int line, int col, const char *text, ...)
+{
+    va_list args;
+    va_start(args, text);
+
+    wattron(win, COLOR_PAIR(2));
+    wmove(win, line, col);
+    vw_printw(win, text, args);
+    wattroff(win, COLOR_PAIR(2));
+
+    va_end(args);
+}
+
+void set_string(char *dest, const char *src, size_t size)
+{
+    strncpy(dest, src, size - 1);
+    dest[size - 1] = '\0';
+}
+
+int check_size_change(WINDOW *win, int *height, int *width)
+{
+    int new_height, new_width;
+    getmaxyx(win, new_height, new_width);
+    move(1, 25);
+    if (new_height != *height || new_width != *width)
+    {
+        *height = new_height;
+        *width = new_width;
+        return 1;
+    }
+    return 0;
+}
+
+void print_wrapped_text(WINDOW *pad, int *line, int start, int size, const char *text, bool enclose_with_pipe)
+{
+    const char *ptr;
+    int len, adjust_len;
+
+    if (!text || !pad || !line || size <= 0)
+        return;
+
+    ptr = text;
+
+    while (*ptr)
+    {
+        len = ((int)strlen(ptr) > size) ? size - 1 : (int)strlen(ptr);
+
+        /* To ensure truncation doesn't break any words */
+        if (len < (int)strlen(ptr) && ptr[len] != ' ' && ptr[len - 1] != ' ')
+        {
+            adjust_len = len;
+            while (adjust_len > 0 && ptr[adjust_len] != ' ')
+                adjust_len--;
+
+            if (adjust_len > 0)
+                len = adjust_len;
+        }
+
+        if (enclose_with_pipe)
+            mvwprintw(pad, (*line)++, start, "| %-*.*s |", size, len, ptr);
+        else
+            mvwprintw(pad, (*line)++, start, "%-*.*s", size, len, ptr);
+
+        ptr += len;
+        while (*ptr == ' ')
+            ptr++;
+    }
+}
\ No newline at end of file
diff --git a/tools/displaytop/src/utils_driver.c b/tools/displaytop/src/utils_driver.c
new file mode 100644
index 000000000..7b24d2f41
--- /dev/null
+++ b/tools/displaytop/src/utils_driver.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "utils.h"
+
+static int is_driver_loaded(const char *driver)
+{
+    FILE *fp;
+    char buffer[1024];
+    int found = 0;
+
+    if (!driver)
+    {
+        log_message(LOG_ERROR, "Driver name is NULL.");
+        return 0;
+    }
+
+    fp = fopen("/proc/modules", "r");
+    if (!fp)
+    {
+        perror("Error opening /proc/modules");
+        return 0;
+    }
+
+    while (fgets(buffer, sizeof(buffer), fp))
+    {
+        if (strncmp(buffer, driver, strlen(driver)) == 0 && buffer[strlen(driver)] == ' ')
+        {
+            found = 1;
+            break;
+        }
+    }
+
+    fclose(fp);
+    return found;
+}
+
+static void load_driver(const char *driver)
+{
+    pid_t pid;
+
+    pid = fork();
+    if (pid == 0)
+    {
+        execlp("sudo", "sudo", "modprobe", driver, NULL);
+        exit(EXIT_FAILURE);
+    }
+    else if (pid < 0)
+    {
+        perror("Failed to fork process for modprobe");
+    }
+    else
+    {
+        wait(NULL);
+    }
+}
+
+static void show_driver_menu(void)
+{
+    int key;
+    int rows, cols;
+    WINDOW *win;
+    const char *options[] = {"Load i915", "Load xe", "Exit"};
+    int total_options = sizeof(options) / sizeof(options[0]);
+    int highlighted_index = 0;
+    int i;
+    int x_pos;
+    const char *driver;
+
+    getmaxyx(stdscr, rows, cols);
+
+    win = newwin(rows, cols, 0, 0);
+    if (!win)
+    {
+        log_message(LOG_ERROR, "Failed to create driver loading window.");
+        return;
+    }
+
+    if (!has_colors() || !COLOR_PAIR(2))
+    {
+        log_message(LOG_ERROR, "Colors not initialized properly.");
+        delwin(win);
+        return;
+    }
+
+    cbreak();
+    keypad(win, TRUE);
+    refresh();
+
+    wbkgd(win, COLOR_PAIR(2));
+    box(win, 0, 0);
+
+    while (1)
+    {
+        werase(win);
+        box(win, 0, 0);
+        mvwprintw(win, 2, (cols - 30) / 2, "Display Top - Select a Driver to Load");
+
+        for (i = 0; i < total_options; i++)
+        {
+            x_pos = (cols - strlen(options[i])) / 2;
+            if (x_pos < 0)
+                x_pos = 0;
+
+            if (i == highlighted_index)
+                wattron(win, A_REVERSE);
+
+            mvwprintw(win, rows / 2 + i, x_pos, "%s", options[i]);
+            wattroff(win, A_REVERSE);
+        }
+
+        mvwprintw(win, rows - 2, 2, "[UP/DOWN] Navigate [ENTER] Select [ESC] Exit");
+        wrefresh(win);
+
+        key = wgetch(win);
+
+        switch (key)
+        {
+        case KEY_UP:
+            highlighted_index = (highlighted_index == 0) ? total_options - 1 : highlighted_index - 1;
+            break;
+        case KEY_DOWN:
+            highlighted_index = (highlighted_index == total_options - 1) ? 0 : highlighted_index + 1;
+            break;
+        case '\n':
+            if (highlighted_index == 0 || highlighted_index == 1)
+            {
+                driver = (highlighted_index == 0) ? "i915" : "xe";
+                werase(win);
+                box(win, 0, 0);
+                mvwprintw(win, rows / 2, (cols - 30) / 2, "Loading driver: %s...", driver);
+                wrefresh(win);
+
+                load_driver(driver);
+
+                werase(win);
+                box(win, 0, 0);
+                mvwprintw(win, rows / 2, (cols - 30) / 2, "Driver %s loaded successfully.", driver);
+                mvwprintw(win, rows - 2, 2, "Press any key to continue...");
+                wrefresh(win);
+
+                wgetch(win);
+            }
+            delwin(win);
+            return;
+        case 27:
+            delwin(win);
+            return;
+        default:
+            break;
+        }
+    }
+}
+
+void check_and_load_driver(void)
+{
+    if (is_driver_loaded("i915"))
+    {
+        log_message(LOG_INFO, "i915 driver is already loaded.");
+    }
+    else if (is_driver_loaded("xe"))
+    {
+        log_message(LOG_INFO, "xe driver is already loaded.");
+    }
+    else
+    {
+        show_driver_menu();
+    }
+}
diff --git a/tools/displaytop/src/utils_drm.c b/tools/displaytop/src/utils_drm.c
new file mode 100644
index 000000000..fe5d8bc68
--- /dev/null
+++ b/tools/displaytop/src/utils_drm.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 "utils.h"
+
+int drm_fd = -1;
+#define MODE_INFO_STRING_LEN 128
+
+/**
+ * @brief Finds a DRM (Direct Rendering Manager) device path based on the specified type.
+ *
+ * This function searches the /dev/dri directory for a DRM device file that matches
+ * the specified type (primary or render). It returns the full path to the first matching
+ * device file found.
+ *
+ * @param primary A boolean indicating the type of DRM device to search for:
+ *                - true: Search for a primary DRM device (prefix "card*").
+ *                - false: Search for a render DRM device (prefix "renderD*").
+ *
+ * @return A dynamically allocated string containing the full path to the DRM device,
+ *         or NULL if no matching device is found or an error occurs. The caller is
+ *         responsible for freeing the returned string.
+ *
+ * @note Logs an error message if the /dev/dri directory cannot be opened, memory
+ *       allocation fails, or no matching device is found.
+ */
+char *find_drm_device(bool primary)
+{
+	DIR *drm_dir;
+	const char *prefix;
+	char *device_path;
+	struct dirent *entry;
+
+	drm_dir = opendir(DRM_DIR);
+	if (!drm_dir)
+	{
+		log_message(LOG_ERROR, "Failed to open /dev/dri directory");
+		return NULL;
+	}
+
+	prefix = primary ? DRM_PRIMARY_PREFIX : DRM_RENDER_PREFIX;
+	device_path = NULL;
+
+	while ((entry = readdir(drm_dir)) != NULL)
+	{
+		if (strncmp(entry->d_name, prefix, strlen(prefix)) == 0)
+		{
+			size_t path_len = strlen(DRM_DIR) + strlen(entry->d_name) + 1;
+			device_path = malloc(path_len);
+			if (!device_path)
+			{
+				log_message(LOG_ERROR, "Failed to allocate memory for device path");
+				break;
+			}
+			snprintf(device_path, path_len, "%s%s", DRM_DIR, entry->d_name);
+			break;
+		}
+	}
+
+	closedir(drm_dir);
+
+	if (!device_path)
+		log_message(LOG_ERROR, "No DRM %s devices found in %s", primary ? "primary (card*)" : "render (renderD*)", DRM_DIR);
+
+	return device_path;
+}
+
+/**
+ * @brief Opens the primary DRM (Direct Rendering Manager) device and configures it.
+ *
+ * This function locates and opens the primary DRM device, ensuring it is accessible
+ * for rendering operations. It also attempts to drop DRM master privileges if held
+ * and sets the client capability for universal planes.
+ *
+ * @note The function logs messages at different levels (error, warning, info) to
+ *       indicate the success or failure of various operations.
+ *
+ * Steps performed:
+ * 1. Finds the DRM device path using `find_drm_device`.
+ * 2. Opens the DRM device with read/write permissions and the close-on-exec flag.
+ * 3. Logs an error if the device cannot be opened.
+ * 4. Attempts to drop DRM master privileges using `drmDropMaster` and logs the result.
+ * 5. Sets the client capability for universal planes using `drmSetClientCap`.
+ *
+ * @warning Ensure that the `find_drm_device` function and `log_message` utility
+ *          are implemented correctly for this function to work as expected.
+ *
+ * @see drmDropMaster, drmSetClientCap
+ */
+void open_primary_drm_device(void)
+{
+	char *device_path = find_drm_device(true);
+	drm_fd = open(device_path, O_RDWR | O_CLOEXEC);
+
+	if (drm_fd < 0)
+		log_message(LOG_ERROR, "Failed to open DRM device");
+
+	if (drmDropMaster(drm_fd) < 0)
+		log_message(LOG_WARNING, "Master already being held by something else!");
+	else
+		log_message(LOG_INFO, "Dropped DRM master successfully");
+
+	drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+}
+
+/**
+ * @brief Closes the primary DRM (Direct Rendering Manager) device.
+ *
+ * This function checks if the DRM device file descriptor (`drm_fd`) is valid
+ * (greater than or equal to 0). If valid, it closes the file descriptor,
+ * resets it to -1, and logs a message indicating that the DRM device has been
+ * successfully closed.
+ *
+ * @note Ensure that `drm_fd` is properly initialized before calling this
+ * function. Closing an already closed or invalid file descriptor may lead to
+ * undefined behavior.
+ */
+void close_primary_drm_device(void)
+{
+	if (drm_fd >= 0)
+	{
+		close(drm_fd);
+		drm_fd = -1;
+		log_message(LOG_INFO, "Closed DRM device");
+	}
+}
+
+const char *get_drm_object_type_name(uint32_t object_type)
+{
+	switch (object_type)
+	{
+	case DRM_MODE_OBJECT_CRTC:
+		return "CRTC";
+	case DRM_MODE_OBJECT_CONNECTOR:
+		return "Connector";
+	case DRM_MODE_OBJECT_ENCODER:
+		return "Encoder";
+	case DRM_MODE_OBJECT_PLANE:
+		return "Plane";
+	case DRM_MODE_OBJECT_PROPERTY:
+		return "Property";
+	case DRM_MODE_OBJECT_FB:
+		return "Framebuffer";
+	default:
+		return "Unknown";
+	}
+}
+
+const char *get_connector_type_name(uint32_t connector_type)
+{
+	switch (connector_type)
+	{
+	case DRM_MODE_CONNECTOR_VGA:
+		return "VGA";
+	case DRM_MODE_CONNECTOR_DVII:
+		return "DVI-I";
+	case DRM_MODE_CONNECTOR_DVID:
+		return "DVI-D";
+	case DRM_MODE_CONNECTOR_DVIA:
+		return "DVI-A";
+	case DRM_MODE_CONNECTOR_Composite:
+		return "Composite";
+	case DRM_MODE_CONNECTOR_SVIDEO:
+		return "S-Video";
+	case DRM_MODE_CONNECTOR_LVDS:
+		return "LVDS";
+	case DRM_MODE_CONNECTOR_Component:
+		return "Component";
+	case DRM_MODE_CONNECTOR_9PinDIN:
+		return "9-pin DIN";
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		return "DP";
+	case DRM_MODE_CONNECTOR_HDMIA:
+		return "HDMI-A";
+	case DRM_MODE_CONNECTOR_HDMIB:
+		return "HDMI-B";
+	case DRM_MODE_CONNECTOR_TV:
+		return "TV";
+	case DRM_MODE_CONNECTOR_eDP:
+		return "eDP";
+	case DRM_MODE_CONNECTOR_VIRTUAL:
+		return "Virtual";
+	case DRM_MODE_CONNECTOR_DSI:
+		return "DSI";
+	case DRM_MODE_CONNECTOR_DPI:
+		return "DPI";
+	default:
+		return "Unknown";
+	}
+}
+
+const char *get_encoder_type_name(uint32_t encoder_type)
+{
+	switch (encoder_type)
+	{
+	case DRM_MODE_ENCODER_NONE:
+		return "None";
+	case DRM_MODE_ENCODER_DAC:
+		return "DAC";
+	case DRM_MODE_ENCODER_TMDS:
+		return "TMDS";
+	case DRM_MODE_ENCODER_LVDS:
+		return "LVDS";
+	case DRM_MODE_ENCODER_TVDAC:
+		return "TVDAC";
+	case DRM_MODE_ENCODER_VIRTUAL:
+		return "Virtual";
+	case DRM_MODE_ENCODER_DSI:
+		return "DSI";
+	case DRM_MODE_ENCODER_DPMST:
+		return "DPMST";
+	default:
+		return "Unknown";
+	}
+}
+
+const char *get_format_str(uint32_t format)
+{
+	switch (format)
+	{
+	case DRM_FORMAT_INVALID:
+		return "INVALID";
+	case DRM_FORMAT_C1:
+		return "C1";
+	case DRM_FORMAT_C2:
+		return "C2";
+	case DRM_FORMAT_C4:
+		return "C4";
+	case DRM_FORMAT_C8:
+		return "C8";
+	case DRM_FORMAT_D1:
+		return "D1";
+	case DRM_FORMAT_D2:
+		return "D2";
+	case DRM_FORMAT_D4:
+		return "D4";
+	case DRM_FORMAT_D8:
+		return "D8";
+	case DRM_FORMAT_R1:
+		return "R1";
+	case DRM_FORMAT_R2:
+		return "R2";
+	case DRM_FORMAT_R4:
+		return "R4";
+	case DRM_FORMAT_R8:
+		return "R8";
+	case DRM_FORMAT_R10:
+		return "R10";
+	case DRM_FORMAT_R12:
+		return "R12";
+	case DRM_FORMAT_R16:
+		return "R16";
+	case DRM_FORMAT_RG88:
+		return "RG88";
+	case DRM_FORMAT_GR88:
+		return "GR88";
+	case DRM_FORMAT_RG1616:
+		return "RG1616";
+	case DRM_FORMAT_GR1616:
+		return "GR1616";
+	case DRM_FORMAT_RGB332:
+		return "RGB332";
+	case DRM_FORMAT_BGR233:
+		return "BGR233";
+	case DRM_FORMAT_XRGB4444:
+		return "XRGB4444";
+	case DRM_FORMAT_XBGR4444:
+		return "XBGR4444";
+	case DRM_FORMAT_RGBX4444:
+		return "RGBX4444";
+	case DRM_FORMAT_BGRX4444:
+		return "BGRX4444";
+	case DRM_FORMAT_ARGB4444:
+		return "ARGB4444";
+	case DRM_FORMAT_ABGR4444:
+		return "ABGR4444";
+	case DRM_FORMAT_RGBA4444:
+		return "RGBA4444";
+	case DRM_FORMAT_BGRA4444:
+		return "BGRA4444";
+	case DRM_FORMAT_XRGB1555:
+		return "XRGB1555";
+	case DRM_FORMAT_XBGR1555:
+		return "XBGR1555";
+	case DRM_FORMAT_RGBX5551:
+		return "RGBX5551";
+	case DRM_FORMAT_BGRX5551:
+		return "BGRX5551";
+	case DRM_FORMAT_ARGB1555:
+		return "ARGB1555";
+	case DRM_FORMAT_ABGR1555:
+		return "ABGR1555";
+	case DRM_FORMAT_RGBA5551:
+		return "RGBA5551";
+	case DRM_FORMAT_BGRA5551:
+		return "BGRA5551";
+	case DRM_FORMAT_RGB565:
+		return "RGB565";
+	case DRM_FORMAT_BGR565:
+		return "BGR565";
+	case DRM_FORMAT_RGB888:
+		return "RGB888";
+	case DRM_FORMAT_BGR888:
+		return "BGR888";
+	case DRM_FORMAT_XRGB8888:
+		return "XRGB8888";
+	case DRM_FORMAT_XBGR8888:
+		return "XBGR8888";
+	case DRM_FORMAT_RGBX8888:
+		return "RGBX8888";
+	case DRM_FORMAT_BGRX8888:
+		return "BGRX8888";
+	case DRM_FORMAT_ARGB8888:
+		return "ARGB8888";
+	case DRM_FORMAT_ABGR8888:
+		return "ABGR8888";
+	case DRM_FORMAT_RGBA8888:
+		return "RGBA8888";
+	case DRM_FORMAT_BGRA8888:
+		return "BGRA8888";
+	case DRM_FORMAT_XRGB2101010:
+		return "XRGB2101010";
+	case DRM_FORMAT_XBGR2101010:
+		return "XBGR2101010";
+	case DRM_FORMAT_RGBX1010102:
+		return "RGBX1010102";
+	case DRM_FORMAT_BGRX1010102:
+		return "BGRX1010102";
+	case DRM_FORMAT_ARGB2101010:
+		return "ARGB2101010";
+	case DRM_FORMAT_ABGR2101010:
+		return "ABGR2101010";
+	case DRM_FORMAT_RGBA1010102:
+		return "RGBA1010102";
+	case DRM_FORMAT_BGRA1010102:
+		return "BGRA1010102";
+	case DRM_FORMAT_XRGB16161616:
+		return "XRGB16161616";
+	case DRM_FORMAT_XBGR16161616:
+		return "XBGR16161616";
+	case DRM_FORMAT_ARGB16161616:
+		return "ARGB16161616";
+	case DRM_FORMAT_ABGR16161616:
+		return "ABGR16161616";
+	case DRM_FORMAT_XRGB16161616F:
+		return "XRGB16161616F";
+	case DRM_FORMAT_XBGR16161616F:
+		return "XBGR16161616F";
+	case DRM_FORMAT_ARGB16161616F:
+		return "ARGB16161616F";
+	case DRM_FORMAT_ABGR16161616F:
+		return "ABGR16161616F";
+	case DRM_FORMAT_AXBXGXRX106106106106:
+		return "AXBXGXRX106106106106";
+	case DRM_FORMAT_YUYV:
+		return "YUYV";
+	case DRM_FORMAT_YVYU:
+		return "YVYU";
+	case DRM_FORMAT_UYVY:
+		return "UYVY";
+	case DRM_FORMAT_VYUY:
+		return "VYUY";
+	case DRM_FORMAT_AYUV:
+		return "AYUV";
+	case DRM_FORMAT_AVUY8888:
+		return "AVUY8888";
+	case DRM_FORMAT_XYUV8888:
+		return "XYUV8888";
+	case DRM_FORMAT_XVUY8888:
+		return "XVUY8888";
+	case DRM_FORMAT_VUY888:
+		return "VUY888";
+	case DRM_FORMAT_VUY101010:
+		return "VUY101010";
+	case DRM_FORMAT_Y210:
+		return "Y210";
+	case DRM_FORMAT_Y212:
+		return "Y212";
+	case DRM_FORMAT_Y216:
+		return "Y216";
+	case DRM_FORMAT_Y410:
+		return "Y410";
+	case DRM_FORMAT_Y412:
+		return "Y412";
+	case DRM_FORMAT_Y416:
+		return "Y416";
+	case DRM_FORMAT_XVYU2101010:
+		return "XVYU2101010";
+	case DRM_FORMAT_XVYU12_16161616:
+		return "XVYU12_16161616";
+	case DRM_FORMAT_XVYU16161616:
+		return "XVYU16161616";
+	case DRM_FORMAT_Y0L0:
+		return "Y0L0";
+	case DRM_FORMAT_X0L0:
+		return "X0L0";
+	case DRM_FORMAT_Y0L2:
+		return "Y0L2";
+	case DRM_FORMAT_X0L2:
+		return "X0L2";
+	case DRM_FORMAT_YUV420_8BIT:
+		return "YUV420_8BIT";
+	case DRM_FORMAT_YUV420_10BIT:
+		return "YUV420_10BIT";
+	case DRM_FORMAT_XRGB8888_A8:
+		return "XRGB8888_A8";
+	case DRM_FORMAT_XBGR8888_A8:
+		return "XBGR8888_A8";
+	case DRM_FORMAT_RGBX8888_A8:
+		return "RGBX8888_A8";
+	case DRM_FORMAT_BGRX8888_A8:
+		return "BGRX8888_A8";
+	case DRM_FORMAT_RGB888_A8:
+		return "RGB888_A8";
+	case DRM_FORMAT_BGR888_A8:
+		return "BGR888_A8";
+	case DRM_FORMAT_RGB565_A8:
+		return "RGB565_A8";
+	case DRM_FORMAT_BGR565_A8:
+		return "BGR565_A8";
+	case DRM_FORMAT_NV12:
+		return "NV12";
+	case DRM_FORMAT_NV21:
+		return "NV21";
+	case DRM_FORMAT_NV16:
+		return "NV16";
+	case DRM_FORMAT_NV61:
+		return "NV61";
+	case DRM_FORMAT_NV24:
+		return "NV24";
+	case DRM_FORMAT_NV42:
+		return "NV42";
+	case DRM_FORMAT_NV15:
+		return "NV15";
+	case DRM_FORMAT_NV20:
+		return "NV20";
+	case DRM_FORMAT_NV30:
+		return "NV30";
+	case DRM_FORMAT_P210:
+		return "P210";
+	case DRM_FORMAT_P010:
+		return "P010";
+	case DRM_FORMAT_P012:
+		return "P012";
+	case DRM_FORMAT_P016:
+		return "P016";
+	case DRM_FORMAT_P030:
+		return "P030";
+	case DRM_FORMAT_Q410:
+		return "Q410";
+	case DRM_FORMAT_Q401:
+		return "Q401";
+	case DRM_FORMAT_YUV410:
+		return "YUV410";
+	case DRM_FORMAT_YVU410:
+		return "YVU410";
+	case DRM_FORMAT_YUV411:
+		return "YUV411";
+	case DRM_FORMAT_YVU411:
+		return "YVU411";
+	case DRM_FORMAT_YUV420:
+		return "YUV420";
+	case DRM_FORMAT_YVU420:
+		return "YVU420";
+	case DRM_FORMAT_YUV422:
+		return "YUV422";
+	case DRM_FORMAT_YVU422:
+		return "YVU422";
+	case DRM_FORMAT_YUV444:
+		return "YUV444";
+	case DRM_FORMAT_YVU444:
+		return "YVU444";
+	default:
+		return "unknown";
+	}
+}
+
+const char *get_basic_modifier_str(uint64_t modifier)
+{
+	switch (modifier)
+	{
+	case I915_FORMAT_MOD_X_TILED:
+		return "I915_FORMAT_MOD_X_TILED";
+	case I915_FORMAT_MOD_Y_TILED:
+		return "I915_FORMAT_MOD_Y_TILED";
+	case I915_FORMAT_MOD_Yf_TILED:
+		return "I915_FORMAT_MOD_Yf_TILED";
+	case I915_FORMAT_MOD_Y_TILED_CCS:
+		return "I915_FORMAT_MOD_Y_TILED_CCS";
+	case I915_FORMAT_MOD_Yf_TILED_CCS:
+		return "I915_FORMAT_MOD_Yf_TILED_CCS";
+	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
+		return "I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS";
+	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
+		return "I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS";
+	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
+		return "I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC";
+	case I915_FORMAT_MOD_4_TILED:
+		return "I915_FORMAT_MOD_4_TILED";
+	case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
+		return "I915_FORMAT_MOD_4_TILED_DG2_RC_CCS";
+	case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
+		return "I915_FORMAT_MOD_4_TILED_DG2_MC_CCS";
+	case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
+		return "I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC";
+	case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
+		return "I915_FORMAT_MOD_4_TILED_MTL_RC_CCS";
+	case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
+		return "I915_FORMAT_MOD_4_TILED_MTL_MC_CCS";
+	case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
+		return "I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC";
+	case DRM_FORMAT_MOD_INVALID:
+		return "DRM_FORMAT_MOD_INVALID";
+	case DRM_FORMAT_MOD_LINEAR:
+		return "DRM_FORMAT_MOD_LINEAR";
+	case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
+		return "DRM_FORMAT_MOD_SAMSUNG_64_32_TILE";
+	case DRM_FORMAT_MOD_SAMSUNG_16_16_TILE:
+		return "DRM_FORMAT_MOD_SAMSUNG_16_16_TILE";
+	case DRM_FORMAT_MOD_QCOM_COMPRESSED:
+		return "DRM_FORMAT_MOD_QCOM_COMPRESSED";
+	case DRM_FORMAT_MOD_QCOM_TILED3:
+		return "DRM_FORMAT_MOD_QCOM_TILED3";
+	case DRM_FORMAT_MOD_QCOM_TILED2:
+		return "DRM_FORMAT_MOD_QCOM_TILED2";
+	case DRM_FORMAT_MOD_VIVANTE_TILED:
+		return "DRM_FORMAT_MOD_VIVANTE_TILED";
+	case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
+		return "DRM_FORMAT_MOD_VIVANTE_SUPER_TILED";
+	case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
+		return "DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED";
+	case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
+		return "DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED";
+	case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED:
+		return "DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB:
+		return "DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB:
+		return "DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB:
+		return "DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB:
+		return "DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB:
+		return "DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB:
+		return "DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB";
+	case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+		return "DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED";
+	case DRM_FORMAT_MOD_BROADCOM_SAND32:
+		return "DRM_FORMAT_MOD_BROADCOM_SAND32";
+	case DRM_FORMAT_MOD_BROADCOM_SAND64:
+		return "DRM_FORMAT_MOD_BROADCOM_SAND64";
+	case DRM_FORMAT_MOD_BROADCOM_SAND128:
+		return "DRM_FORMAT_MOD_BROADCOM_SAND128";
+	case DRM_FORMAT_MOD_BROADCOM_SAND256:
+		return "DRM_FORMAT_MOD_BROADCOM_SAND256";
+	case DRM_FORMAT_MOD_BROADCOM_UIF:
+		return "DRM_FORMAT_MOD_BROADCOM_UIF";
+	case DRM_FORMAT_MOD_ALLWINNER_TILED:
+		return "DRM_FORMAT_MOD_ALLWINNER_TILED";
+	default:
+		return "unknown";
+	}
+}
diff --git a/tools/displaytop/src/utils_search.c b/tools/displaytop/src/utils_search.c
new file mode 100644
index 000000000..449347b51
--- /dev/null
+++ b/tools/displaytop/src/utils_search.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <stdio.h>
+#include <string.h>
+
+#include "node.h"
+#include "utils.h"
+
+void search_nodes(Node *node, const char *searchInput, Node *results)
+{
+    if (node == NULL)
+    {
+        return;
+    }
+
+    if (strstr(node->name, searchInput) != NULL)
+    {
+        add_child(results, node);
+        return;
+    }
+
+    for (int i = 0; i < node->children_size; i++)
+    {
+        search_nodes(&node->children[i], searchInput, results);
+    }
+
+    return;
+}
\ No newline at end of file
diff --git a/tools/meson.build b/tools/meson.build
index f091af380..a5b02550d 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -121,3 +121,4 @@ endif
 subdir('i915-perf')
 subdir('xe-perf')
 subdir('null_state_gen')
+subdir('displaytop')
-- 
2.43.0



More information about the igt-dev mailing list