linux-stable/drivers/gpu/drm
maxime@cerno.tech defc98a013 drm/vc4: hdmi: Fix HSM clock too low on Pi4
[ Upstream commit 3bc6a37f59 ]

Commit ae71ab585c ("drm/vc4: hdmi: Enforce the minimum rate at
runtime_resume") reintroduced the call to clk_set_min_rate in an attempt
to fix the boot without a monitor connected on the RaspberryPi3.

However, that introduced a regression breaking the display output
entirely (black screen but no vblank timeout) on the Pi4.

This is due to the fact that we now have in a typical modeset at boot,
in vc4_hdmi_encoder_pre_crtc_configure(), we have a first call to
clk_set_min_rate() asking for the minimum rate of the HSM clock for our
given resolution, and then a call to pm_runtime_resume_and_get(). We
will thus execute vc4_hdmi_runtime_resume() which, since the commit
mentioned above, will call clk_set_min_rate() a second time with the
absolute minimum rate we want to enforce on the HSM clock.

We're thus effectively erasing the minimum mandated by the mode we're
trying to set. The fact that only the Pi4 is affected is due to the fact
that it uses a different clock driver that tries to minimize the HSM
clock at all time. It will thus lower the HSM clock rate to 120MHz on
the second clk_set_min_rate() call.

The Pi3 doesn't use the same driver and will not change the frequency on
the second clk_set_min_rate() call since it's still within the new
boundaries and it doesn't have the code to minimize the clock rate as
needed. So even though the boundaries are still off, the clock rate is
still the right one for our given mode, so everything works.

There is a lot of moving parts, so I couldn't find any obvious
solution:

  - Reverting the original is not an option, as that would break the Pi3
    again.

  - We can't move the clk_set_min_rate() call in _pre_crtc_configure()
    since because, on the Pi3, the HSM clock has the CLK_SET_RATE_GATE
    flag which prevents the clock rate from being changed after it's
    been enabled. Our calls to clk_set_min_rate() can change it, so they
    need to be done before clk_prepare_enable().

  - We can't remove the call to clk_prepare_enable() from the
    runtime_resume hook to put it into _pre_crtc_configure() either,
    since we need that clock to be enabled to access the registers, and
    we can't count on the fact that the display will be active in all
    situations (doing any CEC operation, or listing the modes while
    inactive are valid for example()).

  - We can't drop the call to clk_set_min_rate() in
    _pre_crtc_configure() since we would need to still enforce the
    minimum rate for a given resolution, and runtime_resume doesn't have
    access to the current mode, if there's any.

  - We can't copy the TMDS character rate into vc4_hdmi and reuse it
    since, because it's part of the KMS atomic state, it needs to be
    protected by a mutex. Unfortunately, some functions (CEC operations,
    mostly) can be reentrant (through the CEC framework) and still need
    a pm_runtime_get.

However, we can work around this issue by leveraging the fact that the
clk_set_min_rate() calls set boundaries for its given struct clk, and
that each different clk_get() call will return a different instance of
struct clk. The clock framework will then aggregate the boundaries for
each struct clk instances linked to a given clock, plus its hardware
boundaries, and will use that.

We can thus get an extra HSM clock user for runtime_pm use only, and use
our different clock instances depending on the context: runtime_pm will
use its own to set the absolute minimum clock setup so that we never
lock the CPU waiting for a register access, and the modeset part will
set its requirement for the current resolution. And we let the CCF do
the coordination.

It's not an ideal solution, but it's fairly unintrusive and doesn't
really change any part of the logic so it looks like a rather safe fix.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=2136234
Fixes: ae71ab585c ("drm/vc4: hdmi: Enforce the minimum rate at runtime_resume")
Reported-by: Peter Robinson <pbrobinson@gmail.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Tested-by: Peter Robinson <pbrobinson@gmail.com>
Link: https://lore.kernel.org/r/20221021131339.2203291-1-maxime@cerno.tech
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-11-16 10:03:52 +01:00
..
amd drm/amdkfd: Fix NULL pointer dereference in svm_migrate_to_ram() 2022-11-16 10:03:49 +01:00
arm drm/komeda: Fix handling of atomic commits in the atomic_commit_tail hook 2022-10-21 12:39:12 +02:00
armada drm: Remove linux/fb.h from drm_crtc.h 2022-07-05 21:14:02 +03:00
aspeed drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
ast drm/ast: Enable primary plane with CRTC 2022-06-27 11:10:43 +02:00
atmel-hlcdc drm: Remove linux/media-bus-format.h from drm_crtc.h 2022-07-05 21:15:13 +03:00
bridge drm/bridge: ps8640: Add back the 50 ms mystery delay after HPD 2022-11-04 00:00:30 +09:00
display drm/dp: Don't rewrite link config when setting phy test pattern 2022-10-21 12:39:17 +02:00
etnaviv Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux into drm-next 2022-05-17 12:20:04 +10:00
exynos sound updates for 6.0-rc1 2022-08-06 10:19:51 -07:00
fsl-dcu drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
gma500 drm/gma500: Fix (vblank) IRQs not working after suspend/resume 2022-09-09 14:04:30 +02:00
gud drm: Drop drm_blend.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
hisilicon drm/hisilicon: Add depends on MMU 2022-09-20 11:15:09 +02:00
hyperv PCI: Move PCI_VENDOR_ID_MICROSOFT/PCI_DEVICE_ID_HYPERV_VIDEO definitions to pci_ids.h 2022-09-05 17:00:54 +00:00
i2c sound updates for 6.0-rc1 2022-08-06 10:19:51 -07:00
i810
i915 drm/i915/sdvo: Grab mode_config.mutex during LVDS init to avoid WARNs 2022-11-16 10:03:49 +01:00
imx One patch for imx/dcss to get rid of a warning message, one off-by-one 2022-08-18 08:51:42 +10:00
ingenic drm: Remove linux/media-bus-format.h from drm_crtc.h 2022-07-05 21:15:13 +03:00
kmb drm: Remove linux/fb.h from drm_crtc.h 2022-07-05 21:14:02 +03:00
lib
lima drm/lima: Migrate to dev_pm_opp_set_config() 2022-07-08 11:27:33 +05:30
logicvc drm/logicvc: add missing of_node_put() in logicvc_layers_init() 2022-06-24 17:23:38 +02:00
mcde drm: Remove linux/i2c.h from drm_crtc.h 2022-07-05 21:15:23 +03:00
mediatek drm/mediatek: dsi: Move mtk_dsi_stop() call back to mtk_dsi_poweroff() 2022-09-22 07:31:43 +08:00
meson drm/meson: remove drm bridges at aggregate driver unbind time 2022-10-21 12:39:16 +02:00
mga
mgag200 drm/mgag200: Force 32 bpp on the console 2022-09-20 09:20:23 +02:00
msm drm/msm/a6xx: Fix kvzalloc vs state_kcalloc usage 2022-11-04 00:00:26 +09:00
mxsfb drm: Remove linux/media-bus-format.h from drm_crtc.h 2022-07-05 21:15:13 +03:00
nouveau drm/nouveau/nouveau_bo: fix potential memory leak in nouveau_bo_alloc() 2022-10-21 12:39:12 +02:00
omapdrm drm/omap: dss: Fix refcount leak bugs 2022-10-21 12:38:27 +02:00
panel drm/panel: use 'select' for Ili9341 panel driver helpers 2022-10-21 12:38:25 +02:00
panfrost drm/panfrost: devfreq: set opp to the recommended one to configure regulator 2022-09-08 11:03:52 +01:00
pl111 drm:pl111: Add of_node_put() when breaking out of for_each_available_child_of_node() 2022-10-21 12:38:23 +02:00
qxl drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
r128 drm/r128: Fix undefined behavior due to shift overflowing the constant 2022-05-21 18:02:47 +02:00
radeon drm/radeon: add a force flush to delay work when radeon 2022-08-19 17:07:06 -04:00
rcar-du Miscellaneous R-Car DU fixes and enhancements 2022-07-22 13:43:32 +10:00
rockchip drm/rockchip: dsi: Force synchronous probe 2022-11-10 18:17:39 +01:00
savage
scheduler drm/scheduler: Don't kill jobs in interrupt context 2022-07-15 10:09:15 -04:00
selftests drm/display/selftests: drop extra word 'for' in comments for MST selftests 2022-06-28 18:53:20 -04:00
shmobile drm: shmobile: Use backlight helper 2022-06-24 21:45:28 +02:00
sis
solomon drm for 5.20/6.0 2022-08-03 19:52:08 -07:00
sprd drm: Drop drm_blend.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
sti sound updates for 6.0-rc1 2022-08-06 10:19:51 -07:00
stm drm: Remove linux/media-bus-format.h from drm_crtc.h 2022-07-05 21:15:13 +03:00
sun4i One patch for imx/dcss to get rid of a warning message, one off-by-one 2022-08-18 08:51:42 +10:00
tdfx
tegra drm/tegra: Changes for v5.20-rc1 2022-07-12 16:50:05 +10:00
tests drm/format-helper: Fix test on big endian architectures 2022-10-21 12:38:23 +02:00
tidss drm: Remove linux/media-bus-format.h from drm_crtc.h 2022-07-05 21:15:13 +03:00
tilcdc drm: Remove linux/fb.h from drm_crtc.h 2022-07-05 21:14:02 +03:00
tiny drm/bochs: fix blanking 2022-10-21 12:38:26 +02:00
ttm drm/ttm: cleanup the resource of ghost objects after locking them 2022-09-08 09:50:21 +02:00
tve200 drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
udl drm/udl: Restore display mode on resume 2022-10-21 12:37:41 +02:00
v3d drm/v3d: Add support for bcm2711 2022-06-12 22:10:50 -01:00
vboxvideo drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
vc4 drm/vc4: hdmi: Fix HSM clock too low on Pi4 2022-11-16 10:03:52 +01:00
vgem
via
virtio virtio-gpu: fix shift wrapping bug in virtio_gpu_fence_event_create() 2022-10-21 12:38:29 +02:00
vkms drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
vmwgfx drm/vmwgfx: Fix memory leak in vmw_mksstat_add_ioctl() 2022-10-21 12:38:28 +02:00
xen Linux 5.19-rc6 2022-07-13 10:54:56 +10:00
xlnx drm: xlnx: add <linux/io.h> for readl/writel 2022-07-06 22:54:51 +03:00
drm_agpsupport.c
drm_aperture.c drm/aperture: Run fbdev removal before internal helpers 2022-07-09 11:12:05 -07:00
drm_atomic.c drm: Drop drm_blend.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_atomic_helper.c drm/atomic-helper: Add helper drm_atomic_helper_check_crtc_state() 2022-06-27 11:10:43 +02:00
drm_atomic_state_helper.c drm: Drop drm_blend.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_atomic_uapi.c drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_auth.c
drm_blend.c drm/doc: Fix comment typo 2022-06-28 07:56:32 +02:00
drm_bridge.c drm/bridge: Avoid uninitialized variable warning 2022-10-21 12:38:21 +02:00
drm_bridge_connector.c drm: Config orientation property if panel provides it 2022-06-21 08:52:59 -07:00
drm_buddy.c
drm_bufs.c
drm_cache.c
drm_client.c
drm_client_modeset.c drm: Drop drm_edid.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_color_mgmt.c
drm_connector.c drm: Remove linux/fb.h from drm_crtc.h 2022-07-05 21:14:02 +03:00
drm_context.c
drm_crtc.c drm: Drop drm_blend.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_crtc_helper.c drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_crtc_helper_internal.h
drm_crtc_internal.h drm/edid: abstract debugfs override EDID set/reset 2022-06-30 10:50:59 +03:00
drm_damage_helper.c drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_debugfs.c drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets 2022-09-02 16:38:51 +03:00
drm_debugfs_crc.c
drm_displayid.c drm/displayid: convert to drm_edid 2022-05-13 18:55:13 +03:00
drm_dma.c
drm_drv.c
drm_dumb_buffers.c
drm_edid.c drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets 2022-09-02 16:38:51 +03:00
drm_edid_load.c
drm_encoder.c drm: use ENOMEM for drmm_kzalloc allocation failures 2022-05-25 17:39:49 +02:00
drm_encoder_slave.c
drm_fb_cma_helper.c
drm_fb_helper.c drm/fb-helper: Fix out-of-bounds access 2022-06-27 11:10:43 +02:00
drm_file.c fs: remove no_llseek 2022-07-16 09:19:47 -04:00
drm_flip_work.c
drm_format_helper.c
drm_fourcc.c
drm_framebuffer.c
drm_gem.c drm/gem: Fix GEM handle release errors 2022-08-19 13:38:12 +02:00
drm_gem_atomic_helper.c drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_gem_cma_helper.c drm/cma-helper: Describe what a "contiguous chunk" actually means 2022-06-08 17:36:15 +02:00
drm_gem_framebuffer_helper.c drm/gem: Warn on trying to use a non-existing framebuffer plane 2022-05-19 19:25:23 +02:00
drm_gem_shmem_helper.c drm/shmem-helper: Add missing vunmap on error 2022-08-09 18:15:42 +02:00
drm_gem_ttm_helper.c drm/ttm: fix locking in vmap/vunmap TTM GEM helpers 2022-07-18 09:18:53 +02:00
drm_gem_vram_helper.c drm/gem-vram: Ignore planes that are unused by framebuffer format 2022-05-19 19:25:19 +02:00
drm_hashtab.c
drm_internal.h drm/gem: Fix GEM handle release errors 2022-08-19 13:38:12 +02:00
drm_ioc32.c
drm_ioctl.c drm: Prevent drm_copy_field() to attempt copying a NULL pointer 2022-10-21 12:39:12 +02:00
drm_irq.c
drm_kms_helper_common.c drm: Drop drm_edid.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_lease.c
drm_legacy.h
drm_legacy_misc.c
drm_lock.c
drm_managed.c
drm_memory.c
drm_mipi_dbi.c drm: Remove linux/fb.h from drm_crtc.h 2022-07-05 21:14:02 +03:00
drm_mipi_dsi.c drm/mipi-dsi: Detach devices when removing the host 2022-10-21 12:38:21 +02:00
drm_mm.c
drm_mode_config.c drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_mode_object.c
drm_modes.c drm: Remove linux/fb.h from drm_crtc.h 2022-07-05 21:14:02 +03:00
drm_modeset_helper.c drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
drm_modeset_lock.c
drm_nomodeset.c
drm_of.c drm: Remove linux/media-bus-format.h from drm_crtc.h 2022-07-05 21:15:13 +03:00
drm_panel.c
drm_panel_orientation_quirks.c drm: panel-orientation-quirks: Add quirk for Aya Neo Air 2022-10-21 12:39:14 +02:00
drm_pci.c
drm_plane.c
drm_plane_helper.c
drm_prime.c drm/gem: Fix GEM handle release errors 2022-08-19 13:38:12 +02:00
drm_print.c
drm_privacy_screen.c
drm_privacy_screen_x86.c
drm_probe_helper.c drm/probe-helper: add drm_connector_helper_get_modes() 2022-06-30 10:51:03 +03:00
drm_property.c
drm_rect.c
drm_scatter.c
drm_self_refresh_helper.c
drm_simple_kms_helper.c drm/simple-kms: Use drm_atomic_helper_check_crtc_state() 2022-06-27 11:10:43 +02:00
drm_syncobj.c drm/syncobj: add missing error return code in drm_syncobj_transfer_to_timeline() 2022-06-13 08:54:16 +02:00
drm_sysfs.c
drm_trace.h
drm_trace_points.c
drm_vblank.c
drm_vblank_work.c
drm_vm.c LoongArch: Add writecombine support for drm 2022-06-03 20:09:27 +08:00
drm_vma_manager.c
drm_writeback.c drm: Drop drm_framebuffer.h from drm_crtc.h 2022-06-20 23:53:55 +03:00
Kconfig drm: fix drm_mipi_dbi build errors 2022-10-21 12:38:25 +02:00
Makefile drm: lcdif: Add support for i.MX8MP LCDIF variant 2022-06-29 01:44:48 +02:00