Skip to content

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

Open
HorseyofCoursey wants to merge 635 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 635 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! (:

6by9 and others added 30 commits August 28, 2026 11:26
vc4_dsi_bridge_disable wasn't resetting things during shutdown,
so add that in.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The block must be enabled for the FIFO resets to be actioned,
so ensure this is the case.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The pixel to byte FIFO appears to not always reset correctly,
which can lead to colour errors and/or horizontal shifts.
Reset on every vblank to work around the issue.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The TC358762 bridge and panel decodes the mode differently on
DSI0 to DSI1 for no obvious reason, and results in a shift off
the screen.
Whilst it would be possible to change the compatible used for
the panel, that then messes up Pi5.

As it appears to be restricted to vc4 DSI0, fix up the mode
in vc4_dsi.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Some DSI peripheral drivers wish to send commands in the
post_disable or panel unprepare callback. These are called
after the DSI host's disable call, but before the host's
post_disable if pre_enable_prev_first is set.

Don't reset the block until post_disable to allow these
commands to be sent.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The DSI block appears to be able to come up stuck in a condition where
it leaves the lanes in HS mode or just jabbering. This stops LP
transfers from completing as there is no LP time available. This is
signalled via the LP1 contention error.

Enabling video briefly clears that condition, so if we detect the
error condition, enable video mode and then retry.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Similar to the ch7006 and nouveau drivers, introduce a "tv_mode" module
parameter that allow setting the TV norm by specifying vc4.tv_norm= on
the kernel command line.

If that is not specified, try inferring one of the most popular norms
(PAL or NTSC) from the video mode specified on the command line. On
Raspberry Pis, this causes the most common cases of the sdtv_mode
setting in config.txt to be respected.

Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>

drm/vc4: Do not reset tv mode as this is already handled by framework

In vc4_vec_connector_reset, the tv mode is already reset to the
property default by drm_atomic_helper_connector_tv_reset, so there
is no need for a local fixup to potentially some other default.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
With the command line parser now providing the information about
the tv mode, use that as the preferred choice for initialising the
default of the tv_mode property.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
See: https://forum.libreelec.tv/thread/24783-tv-avr-turns-back-on-right-after-turning-them-off

While the kernel provides a :D flag for assuming device is connected,
it doesn't stop this function from being called and generating a cec_phys_addr_invalidate
message when hotplug is deasserted.

That message provokes a flurry of CEC messages which for many users results in the TV
switching back on again and it's very hard to get it to stay switched off.

It seems to only occur with an AVR and TV connected but has been observed across a
number of manufacturers.

The issue started with raspberrypi#4371
and this provides an optional way of getting back the old behaviour

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
The intention of the vc4.force_hotplug setting is to
ignore hotplug completely.

It can be used when a display toggles hotplug when
switching AV inputs, going into standby or changing a
KVM switch, and some side effect of that is unwanted.

It turns out while vc4.force_hotplug currently makes
hotplug always read as asserted, that isn't enough to
stop drm doing lots of stuff, including re-reading
the edid.

An example of what drm does with a hotplug deasert/assert
and vc4.force_hotplug=1 currently is:

https://paste.debian.net/hidden/dc07434b/

That is unwanted. Lets ignore the hotplug interrupt
completely so drm is blissfully unaware of the hotplug change.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
There appears to be a requirement for some devices
(I'm testing with a 8K VRROOM 40Gbps HDMI switch)
for a measable delay between removing the hdmi phy output from
the old mode, to enabling the hdmi phy output for the new mode.

Without the delay, a mode switch has a small change of getting a permanent
'no signal', which requires a subsequent mode switch or a unplug/replug
to redetect.

Switching between 4kp24/25/30 modes fails about 5% of time in my testing.

Add a delay to make it impossible to switch faster than this.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
The body of this function was missing so we don't reset the phy
when disabling it.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
The current reset code doesn't actually stop the hdmi output.
That makes it difficult for displays to handle a mode set.

Powering down the PLL does actually remove the hdmi signal
and makes mode sets more reliable

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
There are no MEDIA_BUS_FMT_* defines for GRB or BRG, and adding
them is a pain.

Add a DT override to allow setting the order.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Seeing as the HVS can be configured with regard the scaling filter,
and DRM now supports selecting scaling filters at a per CRTC or
per plane level, we can implement it.

Default remains as the Mitchell/Netravali filter, but nearest
neighbour is now also implemented.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The documentation says that the TPZ filter can not upscale,
and requesting a scaling factor > 1:1 will output the original
image in the top left, and repeat the right/bottom most pixels
thereafter.
That fits perfectly with upscaling a 1x1 image which is done
a fair amount by some compositors to give solid colour, and it
saves a large amount of LBM (TPZ is based on src size, whilst
PPF is based on dest size).

Select TPZ filter for images with source rectangle <=1.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The register to enable/disable background fill was being set
from atomic flush, however that will be applied immediately and
can be a while before the vblank. If it was required for the
current frame but not for the next one, that can result in
corruption for part of the current frame.

Store the state in vc4_hvs, and update it on vblank.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The HVS can accept an arbitrary number of planes, provided
that the overall pixel read load is within limits, and
the display list can fit into the dlist memory.

Now that DRM will support 64 planes per device, increase
the number of overlay planes from 16 to 48 so that the
dlist complexity can be increased (eg 4x4 video wall on
each of 3 displays).

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Instead of having 48 generic overlay planes, assign 32 to the
writeback connector so that there is no ambiguity in wlroots
when trying to find a plane for composition using the writeback
connector vs display.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The transposer/writeback connector should be running with a
lower priority, so shouldn't be factored into the load
calculations.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
As the writeback connector doesn't have the same realtime
constraints of a live display, drop the panic priority for it.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
The txp block can implement transpose as it writes out the image
data, so expose that through the new connector rotation property.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm: vc4: txp: Do not allow 24bpp formats when transposing

The hardware doesn't support transposing to 24bpp (RGB888/BGR888)
formats. There's no way to advertise this through DRM, so block
it from atomic_check instead.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: txp: fix incorrect width and height check logic in vc4_txp_atomic_check

Since incorrect conditional operator was used in vc4_txp_atomic_check(),
the check may be bypassed if only one of the width or height does
not match.

To prevent this, the conditional operator must be corrected.

Signed-off-by: Jeongjun Park <aha310510@gmail.com>
Currently, booting with no hdmi connected has:
pi@pi4:~ $ vcgencmd measure_clock hdmi pixel
frequency(9)=120010256
frequency(29)=74988280

After connecting hdmi we get:
pi@pi4:~ $ vcgencmd measure_clock hdmi pixel
frequency(9)=300005856
frequency(29)=149989744

and that persists after disconnecting hdmi

I can measure this on a power supply as 10mA@5.2V (52mW).

We should always remove clk_set_min_rate requests
when we no longer need them.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Whilst BCM2712 does fix using odd horizontal timings, it doesn't
work with interlaced modes.

Drop the workaround for interlaced modes and revert to the same
behaviour as BCM2711.

raspberrypi#6281

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
This is a squash of all firmware-kms related patches from previous
branches, up to and including
"drm/vc4: Set the possible crtcs mask correctly for planes with FKMS"
plus a couple of minor fixups for the 5.9 branch.
Please refer to earlier branches for full history.

This patch includes work by Eric Anholt, James Hughes, Phil Elwell,
Dave Stevenson, Dom Cobley, and Jonathon Bell.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Fixup firmware-kms after "drm/atomic: Pass the full state to CRTC atomic enable/disable"

Prototype for those calls changed, so amend fkms (which isn't
upstream) to match.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Fixup fkms for API change

Atomic flush and check changed API, so fix up the downstream-only
FKMS driver.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Make normalize_zpos conditional on using fkms

Eric's view was that there was no point in having zpos
support on vc4 as all the planes had the same functionality.

Can be later squashed into (and fixes):
drm/vc4: Add firmware-kms mode

Signed-off-by: Dom Cobley <popcornmix@gmail.com>

drm/vc4: FKMS: Change of Broadcast RGB mode needs a mode change

The Broadcast RGB (aka HDMI limited/full range) property is only
notified to the firmware on mode change, so this needs to be
signalled when set.

raspberrypi/firmware#1580

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

vc4/drv: Only notify firmware of display done with kms

fkms driver still wants firmware display to be active

Signed-off-by: Dom Cobley <popcornmix@gmail.com>

ydrm/vc4: fkms: Fix margin calculations for the right/bottom edges

The calculations clipped the right/bottom edge of the clipped
range based on the left/top margins.

raspberrypi#4447

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: fkms: Use new devm_rpi_firmware_get api

drm/kms: Add allow_fb_modifiers

Signed-off-by: Dom Cobley <popcornmix@gmail.com>

drm/vc4: Add async update support for cursor planes

Now that cursors are implemented as regular planes, all cursor
movements result in atomic updates. As the firmware-kms driver
doesn't support asynchronous updates, these are synchronous, which
limits the update rate to the screen refresh rate. Xorg seems unaware
of this (or at least of the effect of this), because if the mouse is
configured with a higher update rate than the screen then continuous
mouse movement results in an increasing backlog of mouse events -
cue extreme lag.

Add minimal support for asynchronous updates - limited to cursor
planes - to eliminate the lag.

See: raspberrypi#4971
     raspberrypi#4988

Signed-off-by: Phil Elwell <phil@raspberrypi.com>

drivers/gpu/drm/vc4: Add missing 32-bit RGB formats

The missing 32-bit per pixel ABGR and various "RGB with an X value"
formats are added. Change sent by Dave Stevenson.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>

drm: vc4: Fixup duplicated macro definition in vc4_firmware_kms

Both vc4_drv.h and vc4_firmware_kms.c had definitions for
to_vc4_crtc.

Rename the fkms one to make it unique, and drop the magic
define vc4_crtc vc4_kms_crtc
define to_vc4_crtc to_vc4_kms_crtc
that renamed half the variable and function names in a slightly
unexpected way.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: Fix FKMS for when the YUV chroma planes are different buffers

The code was assuming that it was a single buffer with offsets,
when kmstest uses separate buffers and 0 offsets for each plane.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: fkms: Rename plane related functions

The name collide with the Full KMS functions that are going to be made
public.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

drm/vc4_fkms: Fix up interrupt handler for both 2835/2711 and 2712

2712 has switched from using the SMI peripheral to another interrupt
source for the vsync interrupt, so handle both sources cleanly.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

drm/vc4: fkms: No SMI abuse needed on BCM2712

Since we don't use the (absent) SMI block to create interrupts on
BCM2712, there's no need to map any registers.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
Testing whether the VideoCore generation we want to mock is vc5 or vc4
worked so far, but will be difficult to extend to support BCM2712 (VC6).

Convert to a switch.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
The DRM device pointer and the DRM encoder pointer are redundant, since
the latter is attached to the former and we can just follow the
drm_encoder->dev pointer.

Let's remove the drm_device pointer argument.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Some tests will need to retrieve the output that was just allocated by
vc4_mock_atomic_add_output().

Instead of making them look them up in the DRM device, we can simply
make vc4_mock_atomic_add_output() return an error pointer that holds the
allocated output instead of the error code.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
The BCM2712 has a simpler pipeline that can only output to a writeback
connector and two HDMI controllers.

Let's allow our kunit tests to create a mock of that pipeline.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
bemug-st and others added 22 commits August 28, 2026 11:27
Commit e4a4f2e upstream.

In the driver initialization, the index of the default media bus code
from the supported media bus code array is passed directly to the
vd55g1_get_fmt_code() function instead of the proper media bus code.

This works correctly as a proper media bus code is set after
initialization but could not have been the case. This also resulted in
mutliple "Unsupported mbus format" error messages.

Retrieve the media bus code from the media bus code array, and pass this
media bus code to vd55g1_get_fmt_code() instead of the code index.

Rename VD55G1_MBUS_CODE_DEF to VD55G1_MBUS_CODE_IDX_DEF and
VD55G1_MODE_DEF to VD55G1_MODE_IDX_DEF while at it to avoid future
confusions. Display the guilty error code in warning message.

Cc: stable@vger.kernel.org
Fixes: e138e7f ("media: i2c: vd55g1: Add support for vd65g4 RGB variant")
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Commit 3e275097e206a67f2b691c8167313871ee421cd7 upstream.

vd55g1_update_pad_fmt() is called in vd55g1_init_state(). But
vd55g1_set_pad_fmt(), called at the end of vd55g1_init_state(), also
calls vd55g1_update_pad_fmt() itself.

Enhance readability and clear confusion by only preparing the format in
vd55g1_init_state() and let vd55g1_set_pad_fmt() update it instead,
effectively calling it only 1 time instead of 2.

Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Commit 113a84d upstream

Apply digital gain to all channels, each channel representing a color.

Cc: stable@vger.kernel.org
Fixes: e138e7f ("media: i2c: vd55g1: Add support for vd65g4 RGB variant")
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Commit eaa329aff7bb272f7ba6881de14eb3a4c6626ed5 upstream

Define it as a new monochrome variant of vd65g4.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Commit 7a1e523 upstream

vd55g4 is the same device as vd65g4 but outputs in monochrome instead of
RGB. Adapt the driver structure according to this new variant, and add
its support.

Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Commit 92a59c24cb688b5faecdb6047a377fc76bc093da upstream

Running the sensor on 10 bits mode resulted in FPS being 25% faster than
it should be. This issue did not appear in 8 bits mode. This is mostly
noticeable with libcamera as it can set a target FPS value directly.

This is caused by the V4L2_CID_PIXEL_RATE control being dynamically
changed according to the media bus code, while it should be the same
regardless of the code.

Since we already compute the pixel_clock, use it directly for
V4L2_CID_PIXEL_RATE instead.

Suggested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
…handler

commit 9378156 upstream.

Split the pps-gpio interrupt handler into a primary (hardirq) handler that
captures the PPS timestamp at interrupt entry, and a threaded handler that
processes the event.  This produces the same two-part handler structure on
both PREEMPT_RT and non-RT kernels.

On non-RT kernels the threaded portion runs immediately after the primary,
with no behavioral change compared to the previous single-handler
implementation.

On PREEMPT_RT, where interrupt handlers are force-threaded by default, the
previous single-handler implementation captured the timestamp inside the
threaded portion, after IRQ-thread scheduling delay.  With the split, the
timestamp is captured in true hardirq context as it is on non-RT kernels,
eliminating a significant source of PPS jitter on RT systems.

Link: https://lore.kernel.org/2e32729029fbf6977ecf04665eb00f2efd3e2c17.1780359378.git.calvin@wbinvd.org
Signed-off-by: Michael Byczkowski <by@by-online.de>
Signed-off-by: Calvin Owens <calvin@wbinvd.org>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Tested-by: Michael Byczkowski <by@by-online.de>
Tested-by: Calvin Owens <calvin@wbinvd.org>
Acked-by: Rodolfo Giometti <giometti@enneenne.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Add a preserve_mmc parameter to the sdhost overlay that allows
removing fragment@1 and fragment@2 (which disable mmc and mmcnr).
This is needed on Compute Module when using gpios_22_27 mode,
since disabling the other MMC interfaces would break WiFi on CM.

Signed-off-by: zjzhao <zjzhao@edatec.cn>
When the current dw_axi_dma_chan_prep_slave_sg implementation is given a
span larger than the maximum supported by the DMAC it attempts to
divide it into a number of roughly equal-sized segments. This requires
care that the results are all multiples of the transfer unit, e.g. words
for transfers with a hardware register.

Simplify the logic, and make some of the data arrive ver slightly
earlier, by making all segments as large as possible except for the
last one.

See: raspberrypi#7543

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regardless of what individual devices can support, there's no harm in
allowing users to try higher sample rates.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
drm_calc_timestamping_constants() derives the vblank interval from the
crtc timings and then halves it for interlaced modes, on the basis that
a field is half a frame. That is only correct while the crtc timings
still describe a whole frame.

drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V) already halves
crtc_vdisplay, crtc_vsync_start, crtc_vsync_end and crtc_vtotal for an
interlaced mode. For a driver that uses it, crtc_htotal * crtc_vtotal is
therefore a field and not a frame, the result is halved a second time,
and every consumer of framedur_ns believes vblanks arrive twice as often
as they do.

vc4 is affected. vc4_hdmi_encoder_atomic_check() applies
CRTC_INTERLACE_HALVE_V to the adjusted mode ("Rebuilds every crtc_*
field, so CRTC_INTERLACE_HALVE_V is needed too") because the pixelvalve
is programmed with per-field vertical timings, and
vc4_crtc_get_scanout_position() correspondingly reports a field relative
vpos. The timings and the scanout position are consistently per-field;
only framedur_ns is not.

On a Raspberry Pi 4 driving 1920x1080i@60 (74.25 MHz, htotal 2200,
vtotal 1125) a field lasts 16.667 ms, so vblanks arrive 60 times a
second. The kernel computes:

  2200 * 562 * 1000000 / 74250 = 16651851 ns   already one field
                         / 2   =  8325925 ns   half a field

To see it, put the display in an interlaced mode and ask the kernel to
print its own constants:

  # echo 1 > /sys/module/drm/parameters/debug
  # (trigger a modeset)
  # dmesg | grep drm_calc_timestamping_constants
  crtc 102: hwmode: htotal 2200, vtotal 562, vdisplay 540
  crtc 102: clock 74250 kHz framedur 8325925 linedur 29629
  # echo 0 > /sys/module/drm/parameters/debug

framedur should be 16651851 for a 60 Hz field rate, and the vtotal 562
on the line above shows the timings have already been halved.

The error reaches userspace. When vblank interrupts are not held on,
drm_update_vblank_count() advances the counter by elapsed time divided
by framedur_ns, so on the mode above DRM_IOCTL_CRTC_GET_SEQUENCE climbs
at 120/s instead of 60/s, with sequence_ns advancing 8.33 ms per count.
Anything pacing on that runs at twice speed: this was found from Kodi's
display clock, which plays a 25fps file at double rate on an interlaced
desktop because it advances its clock once per counted vblank.

Only halve when the crtc timings still describe a frame. Drivers that
leave crtc_vtotal alone are unaffected; drivers that halved it get the
field duration their own timings describe.

A small residue remains for the latter: 1125/2 truncates to 562, so
16651851 ns is 0.09% short of the exact 16666666 ns. That is inherent in
deriving a duration from already halved timings, and is a great deal
smaller than the factor of two it replaces.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Commit 6c96741 ("gpiolib: Avoid the hotplug performance reduction")
stubs out gpiolib's SRCU read-side locking to recover the throughput lost
to the hotplug interlock. That trade-off is deliberate, but it leaves the
core's lockdep_assert_held(&gc->gpiodev->srcu) checks in place while the
lock is never actually taken. Since those are WARN_ON(), every GPIO access
splats with CONFIG_LOCKDEP=y and the log fills up with backtraces.

Therefore, only enable REJECT_HOTPLUG_TAX when CONFIG_LOCKDEP is
disabled. This way, the optimisation is kept for production builds, but
developers can still debug the kernel with lockdep enabled.

Fixes: 6c96741 ("gpiolib: Avoid the hotplug performance reduction")
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Format Y12 didn't have a valid "valid_colorspaces" field which
meant libcamera errored out selecting it as the colorspace didn't
match.

The colorspace was previously validated by v4l2-compliance
and failed if it wasn't "valid" for the chosen pixel format.
That test appear to have been dropped/amended.

Rather than just adding the "valid_colorspaces" value for Y12,
remove the whole thing.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Enable CONFIG_SND_SOC_RT5616 in all Pi kernel configurations so the
kernel build produces snd-soc-rt5616.ko (and its dependency
snd-soc-rl6231.ko) for the RT5616 audio codec overlay:

- arch/arm64/configs/bcm2711_defconfig
- arch/arm64/configs/bcm2712_defconfig
- arch/arm64/configs/bcm2711_rt_defconfig
- arch/arm/configs/bcm2709_defconfig
- arch/arm/configs/bcmrpi_defconfig

Signed-off-by: zjzhao <zjzhao@edatec.cn>
Add an overlay for the Realtek RT5616 I2S audio codec:
- rt5616-mclk: 12.288 MHz fixed clock feeding the codec MCLK pin
- rt5616@1b: codec on I2C1 at 0x1b with the mclk clock
- simple-audio-card: I2S link to the I2S consumer controller
  (GPIO 18-21) with mclk-fs = 256 for 48 kHz operation

The codec is the clock master (bitclock/frame master); the RP1 I2S
consumer block only supports slave mode, so the bitclock-master and
frame-master properties point at the codec side.

The alsaname parameter overrides the ALSA card name.

Tested on Raspberry Pi 5 (EDATEC IPC3020) with:
  dtoverlay=rt5616

Signed-off-by: zjzhao <zjzhao@edatec.cn>
Add optional media board support to the wm8960-soundcard overlay:
- mclk: Overrides the MCLK clock frequency (default 12.288 MHz)
- media: Switches to the media board configuration: 24 MHz MCLK,
  enables headphone jack detection (wlf,hp-cfg) and an on-board
  microphone / dual speaker sound card.

The parameters are implemented as dormant fragments and have no
effect unless explicitly activated, preserving full backward
compatibility with existing configurations.

Tested on Raspberry Pi 5 (EDATEC media board) with:
  dtoverlay=wm8960-soundcard,media=on

Signed-off-by: zjzhao <zjzhao@edatec.cn>
… size

struct mmal_msg is a 512-byte stack buffer: a 24-byte header plus a
488-byte union. Within that union, mmal_msg_port_parameter_set places its
384-byte value[] at offset 16, so the field ends 88 bytes short of the
end of the union.

port_parameter_set() copies value_size bytes into that field without
checking it against the field size. A value_size of 385..472 corrupts the
rest of the union, and anything above 472 runs off the end of the
on-stack struct mmal_msg. send_synchronous_mmal_msg() does reject a
payload longer than the union can hold, which covers exactly the second
case, but it is only reached after the memcpy has already happened.

port_parameter_get() has the mirror-image problem: *value_size is both
advertised to the firmware as the space available and used to bound the
copy out of the reply, so a caller asking for more than 384 bytes reads
past value[] in the received message and into whatever follows it in the
VCHIQ slot.

No in-tree caller can trigger either: every call site passes a sizeof()
of a fixed structure, the largest being the 280-byte encoding list read
by bcm2835_isp_get_supported_fmts(). Both functions are reachable through
exported symbols though, so reject an oversized size rather than relying
on callers to get it right.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
…fails

Both VC_SM_CMA_CMD_ALLOC and VC_SM_CMA_CMD_IMPORT_DMABUF install a
dmabuf fd into the caller's fd table before copying the result struct
back out. If that copy_to_user() fails the ioctl returns -EFAULT, but
the fd stays installed and userspace never learns its number, so it
cannot close it.

For ALLOC that leaves the CMA allocation, the vc_sm_buffer and the VPU
mapping pinned until the process exits, and lets a caller pin an fd per
ioctl up to RLIMIT_NOFILE. Release the fd with close_fd() instead.

IMPORT is worse. dma_buf_fd() does not take a reference of its own, it
transfers the caller's reference to the fd table. Once it has succeeded
the dma_buf_put() on the copy_to_user() error path drops a reference the
ioctl no longer owns, freeing the dmabuf while the installed fd still
points at it - a refcount underflow and a use-after-free on the
subsequent close. Split the two conditions so dma_buf_put() only runs
when dma_buf_fd() actually failed, and use close_fd() otherwise.

While here, propagate the dma_buf_fd() error in vc_sm_cma_ioctl_alloc()
rather than falling into the error path with ret still 0, which made the
ioctl report success with an uninitialised handle.

The device is registered with mode 0666, so this is reachable by any
local user.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Each packet RAM slot is VC4_HDMI_PACKET_STRIDE (36) bytes: nine 32-bit
words holding a 3-byte packet header followed by four 7-byte subpackets.
The even words carry three bytes and the odd words four, so a slot can
only ever hold 31 bytes of infoframe.

vc4_hdmi_write_infoframe() instead loops over the infoframe seven bytes
at a time and emits two words per iteration, consuming ceil(len / 7) * 8
bytes of RAM. For any infoframe longer than 28 bytes that is more than
the slot holds, and the trailing write lands on the first word of the
next slot. The subsequent loop that clears the remainder of the slot is
skipped as well, since packet_reg has already passed packet_reg_next.

Today the only infoframe large enough to trigger this is the 30-byte
Dynamic Range and Mastering infoframe, which occupies slot 7 and spills
into slot 8, so nothing observable happens. A full-length (31-byte)
vendor infoframe would occupy slot 1 and zero the header word of slot 2,
corrupting the AVI infoframe written just before it.

Stop the loop once the slot is full, and reject infoframes that cannot
fit rather than silently truncating them. The limit matches the largest
infoframe hdmi_infoframe_pack() can produce,
HDMI_INFOFRAME_HEADER_SIZE + HDMI_MAX_INFOFRAME_SIZE, so no valid caller
is affected.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
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>

@6by9 6by9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on my hx8357 (PiTFT 3.5" resistive) and works as expected.

Altering to kmstest -v -p 0,0-320x420 480x640-RG16 -v <x>,<y>-320x480 is still rejected as that would be scaling the plane rather than cropping, so that's all good.

For me with this display (and quite probably your ili9341) it always goes through the copy path as swap_bytes is set, needing to swap the two bytes in RGB565.
That's a limitation of the SPI controller in Pi0-4. It looks like Pi5 should support 16 bit transfers (and possibly 32bit) and hence not need the swap flag.

Once we have this series tidied up, we can look at sending it upstream.

@HorseyofCoursey

Copy link
Copy Markdown
Author

@6by9 Thanks for testing on the hx8357d. Good point on swap bytesm, makes sense the zero-copy path never fires on Pi 0–4, so the stride-match optimization would only ever help Pi 5.

@6by9

6by9 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Ideally all the tiny drm drivers that use mipi-dbi-spi would benefit from the increase in max_width/max_height, but no rush. That can be done when sending upstream.

@HorseyofCoursey

Copy link
Copy Markdown
Author

Makes sense, and upstream it collapses to a single change in drm_mipi_dbi.c since mainline still has the limits in the core, so all the mipi-dbi drivers get it for free there. Only 7.2.y needs the per-driver version. Happy to do the full 7.2.y sweep separately if you want it before the upstream submission, otherwise I'll fold it into that. Once this lands in 7.2.y, do you want to send it to dri-devel yourself, or would you rather I do it with you CC'd? Happy either way; if I send it I'll rebase onto drm-misc-next and collapse 2/3 into the single core change first.

@pelwell
pelwell force-pushed the rpi-7.2.y branch 4 times, most recently from 5c0bf85 to 71ba7f2 Compare September 7, 2026 10:30
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.