Skip to content

drm/mipi-dbi: display a cropped region of an oversized framebuffer - #7589

Open
HorseyofCoursey wants to merge 3 commits into
raspberrypi:rpi-7.2.yfrom
HorseyofCoursey:spi-crop
Open

drm/mipi-dbi: display a cropped region of an oversized framebuffer#7589
HorseyofCoursey wants to merge 3 commits into
raspberrypi:rpi-7.2.yfrom
HorseyofCoursey:spi-crop

Conversation

@HorseyofCoursey

Copy link
Copy Markdown

Currently a drm/tiny MIPI-DBI panel can only scan out a framebuffer that
is exactly panel-sized, always from the origin. This series lets a client
allocate a larger framebuffer and choose the displayed region via the
plane source rectangle — a crop / pan with no scaling.

  1. drm/mipi-dbi: honor the plane source offset when flushing
    Pass the integer plane src origin into mipi_dbi_fb_dirty() and
    subtract it in mipi_dbi_set_window_address(). The buffer copy still
    uses framebuffer coordinates so it reads the right pixels from an
    oversized source. src=(0,0) behaviour is unchanged.

2/3. drm/tiny/{ili9341,hx8357d}: raise mode_config.max_width/height,
which were pinned to the panel size and rejected any non-panel-sized
framebuffer. Fixed mode / minimums / connector unchanged; the plane
check forbids scaling and repositioning and tx_buf is mode-sized, so
the flushed rectangle stays bounded by the panel.

Change 1 is in the shared core; changes 2/3 are the per-driver limit
bump (the max_* values moved into the tiny drivers in 7.2). Entirely
within the DBI path — no shared shadow-plane / damage-helper changes.

Tested (Pi Zero 2 W, generic 2.4" 240x320 ILI9341, landscape):

  • 480x640 framebuffer into 320x240: accepted (was "bad framebuffer
    width"), displayed from origin.
  • Offsets on both axes via kmstest -f 480x640-RG16 -v <x>,<y>-320x240:
    the displayed region tracks the source rectangle.
  • Native panel-sized framebuffer: no visual change.
  • Sustained 30fps full-frame video through the flush path: no
    performance regression.
    hx8357d: compile-tested only.

Follow-up, not in this series: mipi_dbi_fb_dirty() can skip the tx_buf
repack when the framebuffer stride matches the panel width (rows are
contiguous). Independent of this feature; will send separately.

Thanks to @6by9 for the guidance throughout! (:

mipi_dbi_fb_dirty() takes the damage rectangle from
drm_atomic_helper_damage_merged(), which is expressed in framebuffer
coordinates and already clipped to the plane's source rectangle.  It
then passed that rectangle straight to mipi_dbi_set_window_address(),
which is correct only while the source rectangle starts at (0,0) - i.e.
while the framebuffer is exactly panel-sized.

If a driver allows a framebuffer larger than the panel and the plane
selects a sub-region with a non-zero src_x/src_y, the controller was
still addressed in framebuffer coordinates, so the wrong part of the
panel was written and an out-of-range window could be programmed.

Pass the integer plane source origin down to mipi_dbi_fb_dirty() and
subtract it when programming the column/page address.  The copy into the
transfer buffer still uses the framebuffer-coordinate rectangle, so it
keeps reading the correct pixels from an oversized source.  With a
panel-sized framebuffer src_x/src_y are zero and behaviour is unchanged.

Signed-off-by: Jonathan Frazin <frazinjonathan@gmail.com>
The driver set mode_config.max_width/max_height equal to the panel
dimensions, so KMS rejected any framebuffer that was not exactly
panel-sized:

    ili9341 spi0.0: bad framebuffer width 480, should be >= 240 && <= 240

Raise the maximums so userspace can allocate a larger framebuffer and
choose the displayed region through the plane's source rectangle - a
crop / pan with no scaling.  The minimums, the fixed display mode and
the connector are unchanged, and drm_mipi_dbi now translates the source
offset when addressing the controller.

The transfer buffer is sized from the display mode, and the plane check
(drm_mipi_dbi_plane_helper_atomic_check) forbids scaling and
repositioning, so the flushed rectangle stays bounded by the panel size
regardless of the framebuffer dimensions.

Signed-off-by: Jonathan Frazin <frazinjonathan@gmail.com>
Same change as the preceding ili9341 patch: mode_config.max_width/height
were pinned to the panel dimensions, rejecting any framebuffer that was
not exactly panel-sized. Raise them so a sub-region of a larger
framebuffer can be displayed via the plane source rectangle, now that
drm_mipi_dbi translates the source offset.

The fixed mode, the minimums and the connector are unchanged; the plane
check forbids scaling and repositioning and tx_buf is sized from the
mode, so the flushed rectangle stays bounded by the panel.

Compile-tested only; the functional testing was done on ili9341.

Signed-off-by: Jonathan Frazin <frazinjonathan@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant