# Linux Framebuffer (/integration/embedded_linux/drivers/fbdev)



Overview [#overview]

The [Linux framebuffer (fbdev)](https://en.wikipedia.org/wiki/Linux_framebuffer) is a kernel subsystem that
exposes a video framebuffer to user space through a device file, typically `/dev/fb0`. It is hardware-independent
and needs no user-space graphics libraries at all, which makes this the simplest way to put LVGL on a screen:
open the device, write pixels.

That simplicity is also its limit. fbdev has no modesetting, no GPU path and no page-flip guarantees. It is
the right choice for minimal systems and for kernels that expose nothing else; on anything modern prefer
[DRM/KMS](/integration/embedded_linux/drivers/drm), which supersedes fbdev and can reach the GPU.

Prerequisites [#prerequisites]

A framebuffer device, usually `/dev/fb0`, and permission to open it.

Configuration [#configuration]

Enable <ApiLink name="LV_USE_LINUX_FBDEV" />.

Options [#options]

| Symbol                        | Default                          | Effect                                                                        |
| ----------------------------- | -------------------------------- | ----------------------------------------------------------------------------- |
| `LV_LINUX_FBDEV_RENDER_MODE`  | `LV_DISPLAY_RENDER_MODE_PARTIAL` | Render mode; see below.                                                       |
| `LV_LINUX_FBDEV_BUFFER_COUNT` | `1`                              | `1` or `2` screen-sized buffers, or `0` for a custom-sized partial buffer.    |
| `LV_LINUX_FBDEV_BUFFER_SIZE`  | `60`                             | Height in rows of the partial buffer. Only used when the buffer count is `0`. |
| `LV_LINUX_FBDEV_MMAP`         | on                               | Access the framebuffer via `mmap()` instead of `write()` calls.               |
| `LV_LINUX_FBDEV_BSD`          | off                              | Use the BSD flavour of the framebuffer device.                                |

`LV_LINUX_FBDEV_RENDER_MODE` accepts <ApiLink name="LV_DISPLAY_RENDER_MODE_PARTIAL" />,
<ApiLink name="LV_DISPLAY_RENDER_MODE_DIRECT" /> or <ApiLink name="LV_DISPLAY_RENDER_MODE_FULL" />.

The buffer count and the render mode constrain each other: two screen-sized buffers require a non-partial
render mode, and a custom-sized buffer requires the partial one.

Usage [#usage]

<Callout type="tip">
  [LVGL's linux port](https://github.com/lvgl/lv_port_linux) can be used to quickly get started with LVGL's FBDEV backend.
</Callout>

Create the display with <ApiLink name="lv_linux_fbdev_create" />, then point it at a device node with
<ApiLink name="lv_linux_fbdev_set_file" />.

```c title=" " lineNumbers=1
lv_display_t * disp = lv_linux_fbdev_create();
lv_linux_fbdev_set_file(disp, "/dev/fb0");
```

The resolution and color format come from the device, the driver reads them from the framebuffer's
`ioctl` info, so there is nothing to configure.

If the screen stays black or draws partially [#if-the-screen-stays-black-or-draws-partially]

Try <ApiLink name="LV_DISPLAY_RENDER_MODE_DIRECT" /> first. If that does not help, force a refresh of the
whole screen on every flush with <ApiLink name="lv_linux_fbdev_set_force_refresh" />. This costs performance,
so only enable it when it is genuinely needed.

Hide the blinking cursor [#hide-the-blinking-cursor]

The kernel console leaves a blinking cursor on the framebuffer. How to disable it depends on the platform;
on a Raspberry Pi, add `vt.global_cursor_default=0` to `/boot/cmdline.txt`.

Wrong resolution after boot [#wrong-resolution-after-boot]

The kernel sizes the framebuffer when it initializes, based on what the display reports. If the board powers
up before the screen (common with HDMI) the kernel may pick the wrong resolution, leaving both the visible
and virtual resolutions incorrect.

Check what the kernel actually chose:

```sh title="sh" lineNumbers=1
fbset -fb /dev/fb0
```

The fix is procedural: make sure the display is connected and powered before the board boots.

Support [#support]

| Capability                  | Value                                                                                                                                   |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Rotation                    | Software                                                                                                                                |
| Runtime resolution change   | No                                                                                                                                      |
| Runtime color format change | No                                                                                                                                      |
| Color formats               | L8, RGB565, RGB888 or XRGB8888, chosen from the framebuffer's bit depth (8, 16, 24 or 32)                                               |
| Multiple displays / windows | Yes                                                                                                                                     |
| Hardware acceleration       | None                                                                                                                                    |
| Render mode                 | Partial (default) — configurable via `LV_LINUX_FBDEV_RENDER_MODE`                                                                       |
| Input                       | None built in. Pair with [evdev](/integration/embedded_linux/drivers/evdev) or [libinput](/integration/embedded_linux/drivers/libinput) |

<Callout type="info" title="8bpp needs a grayscale framebuffer">
  An 8bpp framebuffer maps to `LV_COLOR_FORMAT_L8`, which writes one luminance byte per pixel, so the device has to report a grayscale format.
  Colour 8bpp framebuffers (palette-indexed, packed RGB332, or FOURCC) are rejected and <ApiLink name="lv_linux_fbdev_set_file" />
  returns `LV_RESULT_INVALID`.

  Check what yours reports with `fbset -i -fb /dev/fb0`.
</Callout>

See Also [#see-also]

* [DRM](/integration/embedded_linux/drivers/drm) - the modern replacement, with modesetting and a GPU path
* [evdev](/integration/embedded_linux/drivers/evdev) - simplest input pairing for this driver
* [libinput](/integration/embedded_linux/drivers/libinput) - input with device quirks and full keyboard support
* [lv\_port\_linux](https://github.com/lvgl/lv_port_linux) - reference project
