From eb8b85f63ed3c783ffbaf7e3d3f52725629c3ead Mon Sep 17 00:00:00 2001 From: The-going <48602507+The-going@users.noreply.github.com> Date: Fri, 19 Sep 2025 07:17:50 +0300 Subject: [PATCH] sunxi-6.16: Fix ASoC: soc-core, usb: dwc3, drm: sun4i --- ...core-merge-snd_soc_unregister_compon.patch | 80 +++++++++++++ ...Abort-suspend-on-soft-disconnect-fai.patch | 89 ++++++++++++++ ...-page-flip-after-vsync-is-complete-n.patch | 111 ++++++++++++++++++ 3 files changed, 280 insertions(+) create mode 100644 patch/kernel/archive/sunxi-6.16/0001-Revert-ASoC-soc-core-merge-snd_soc_unregister_compon.patch create mode 100644 patch/kernel/archive/sunxi-6.16/0002-Revert-usb-dwc3-Abort-suspend-on-soft-disconnect-fai.patch create mode 100644 patch/kernel/archive/sunxi-6.16/0003-drm-sun4i-Report-page-flip-after-vsync-is-complete-n.patch diff --git a/patch/kernel/archive/sunxi-6.16/0001-Revert-ASoC-soc-core-merge-snd_soc_unregister_compon.patch b/patch/kernel/archive/sunxi-6.16/0001-Revert-ASoC-soc-core-merge-snd_soc_unregister_compon.patch new file mode 100644 index 000000000..7b440761e --- /dev/null +++ b/patch/kernel/archive/sunxi-6.16/0001-Revert-ASoC-soc-core-merge-snd_soc_unregister_compon.patch @@ -0,0 +1,80 @@ +From f79f3df0f61a6c7bdc08e2318cb3f33398f50442 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Fri, 8 Aug 2025 17:54:21 +0200 +Subject: [PATCH 1/3] Revert "ASoC: soc-core: merge + snd_soc_unregister_component() and snd_soc_unregister_component_by_driver()" + +This reverts commit 144d6dfc7482455eabf8e8caa974a6e8d9572705. +--- + include/sound/soc.h | 2 +- + sound/soc/soc-core.c | 30 +++++++++++++++++++++++++----- + 2 files changed, 26 insertions(+), 6 deletions(-) + +diff --git a/include/sound/soc.h b/include/sound/soc.h +index 1fffef311c41..8d113ee8c2bc 100644 +--- a/include/sound/soc.h ++++ b/include/sound/soc.h +@@ -444,7 +444,7 @@ int snd_soc_register_component(struct device *dev, + int devm_snd_soc_register_component(struct device *dev, + const struct snd_soc_component_driver *component_driver, + struct snd_soc_dai_driver *dai_drv, int num_dai); +-#define snd_soc_unregister_component(dev) snd_soc_unregister_component_by_driver(dev, NULL) ++void snd_soc_unregister_component(struct device *dev); + void snd_soc_unregister_component_by_driver(struct device *dev, + const struct snd_soc_component_driver *component_driver); + struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 67bebc339148..ab615ec113d2 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -2927,14 +2927,34 @@ EXPORT_SYMBOL_GPL(snd_soc_register_component); + void snd_soc_unregister_component_by_driver(struct device *dev, + const struct snd_soc_component_driver *component_driver) + { +- const char *driver_name = NULL; ++ struct snd_soc_component *component; + +- if (component_driver) +- driver_name = component_driver->name; ++ if (!component_driver) ++ return; + ++ mutex_lock(&client_mutex); ++ component = snd_soc_lookup_component_nolocked(dev, component_driver->name); ++ if (!component) ++ goto out; ++ ++ snd_soc_del_component_unlocked(component); ++ ++out: ++ mutex_unlock(&client_mutex); ++} ++EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver); ++ ++/** ++ * snd_soc_unregister_component - Unregister all related component ++ * from the ASoC core ++ * ++ * @dev: The device to unregister ++ */ ++void snd_soc_unregister_component(struct device *dev) ++{ + mutex_lock(&client_mutex); + while (1) { +- struct snd_soc_component *component = snd_soc_lookup_component_nolocked(dev, driver_name); ++ struct snd_soc_component *component = snd_soc_lookup_component_nolocked(dev, NULL); + + if (!component) + break; +@@ -2943,7 +2963,7 @@ void snd_soc_unregister_component_by_driver(struct device *dev, + } + mutex_unlock(&client_mutex); + } +-EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver); ++EXPORT_SYMBOL_GPL(snd_soc_unregister_component); + + /* Retrieve a card's name from device tree */ + int snd_soc_of_parse_card_name(struct snd_soc_card *card, +-- +2.51.0 + diff --git a/patch/kernel/archive/sunxi-6.16/0002-Revert-usb-dwc3-Abort-suspend-on-soft-disconnect-fai.patch b/patch/kernel/archive/sunxi-6.16/0002-Revert-usb-dwc3-Abort-suspend-on-soft-disconnect-fai.patch new file mode 100644 index 000000000..9474d69e0 --- /dev/null +++ b/patch/kernel/archive/sunxi-6.16/0002-Revert-usb-dwc3-Abort-suspend-on-soft-disconnect-fai.patch @@ -0,0 +1,89 @@ +From 48c707b5f50a1cd87925a725e5c85ac06b19219f Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sat, 9 Aug 2025 10:10:42 +0200 +Subject: [PATCH 2/3] Revert "usb: dwc3: Abort suspend on soft disconnect + failure" + +This reverts commit 630a1dec3b0eba2a695b9063f1c205d585cbfec9. +--- + drivers/usb/dwc3/core.c | 9 ++------- + drivers/usb/dwc3/gadget.c | 22 +++++++++++++--------- + 2 files changed, 15 insertions(+), 16 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 91dec9c81a40..1e436ac6a1fa 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -2460,7 +2460,6 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) + { + u32 reg; + int i; +- int ret; + + if (!pm_runtime_suspended(dwc->dev) && !PMSG_IS_AUTO(msg)) { + dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) & +@@ -2480,9 +2479,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) + case DWC3_GCTL_PRTCAP_DEVICE_DISCONNECTED: + if (pm_runtime_suspended(dwc->dev)) + break; +- ret = dwc3_gadget_suspend(dwc); +- if (ret) +- return ret; ++ dwc3_gadget_suspend(dwc); + synchronize_irq(dwc->irq_gadget); + dwc3_core_exit(dwc); + break; +@@ -2517,9 +2514,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) + break; + + if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { +- ret = dwc3_gadget_suspend(dwc); +- if (ret) +- return ret; ++ dwc3_gadget_suspend(dwc); + synchronize_irq(dwc->irq_gadget); + } + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 74968f93d4a3..99fbd29d8f46 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -4821,15 +4821,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc) + int ret; + + ret = dwc3_gadget_soft_disconnect(dwc); +- /* +- * Attempt to reset the controller's state. Likely no +- * communication can be established until the host +- * performs a port reset. +- */ +- if (ret && dwc->softconnect) { +- dwc3_gadget_soft_connect(dwc); +- return -EAGAIN; +- } ++ if (ret) ++ goto err; + + spin_lock_irqsave(&dwc->lock, flags); + if (dwc->gadget_driver) +@@ -4837,6 +4830,17 @@ int dwc3_gadget_suspend(struct dwc3 *dwc) + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; ++ ++err: ++ /* ++ * Attempt to reset the controller's state. Likely no ++ * communication can be established until the host ++ * performs a port reset. ++ */ ++ if (dwc->softconnect) ++ dwc3_gadget_soft_connect(dwc); ++ ++ return ret; + } + + int dwc3_gadget_resume(struct dwc3 *dwc) +-- +2.51.0 + diff --git a/patch/kernel/archive/sunxi-6.16/0003-drm-sun4i-Report-page-flip-after-vsync-is-complete-n.patch b/patch/kernel/archive/sunxi-6.16/0003-drm-sun4i-Report-page-flip-after-vsync-is-complete-n.patch new file mode 100644 index 000000000..16a605a48 --- /dev/null +++ b/patch/kernel/archive/sunxi-6.16/0003-drm-sun4i-Report-page-flip-after-vsync-is-complete-n.patch @@ -0,0 +1,111 @@ +From aeb99ba3659e8147e9f01a5ddfd529f1e1b16358 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sat, 9 Aug 2025 14:47:14 +0200 +Subject: [PATCH 3/3] drm: sun4i: Report page flip after vsync is complete, not + in the middle + +See: https://xnux.eu/log/080.html + +Signed-off-by: Ondrej Jirman +--- + drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 ++++++++++++++++++++++++-- + drivers/gpu/drm/sun4i/sun4i_tcon.h | 4 ++++ + 2 files changed, 28 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c +index 221df37406d8..25c8bff308f2 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c +@@ -240,6 +240,9 @@ void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable) + if (enable) + val = mask; + ++ if (!enable && tcon->quirks->vblank_delay) ++ hrtimer_cancel(&tcon->flip_timer); ++ + regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val); + } + EXPORT_SYMBOL(sun4i_tcon_enable_vblank); +@@ -838,6 +841,17 @@ static void sun4i_tcon_finish_page_flip(struct drm_device *dev, + spin_unlock_irqrestore(&dev->event_lock, flags); + } + ++static enum hrtimer_restart sun4i_tcon_flip_timer_cb(struct hrtimer *timer) ++{ ++ struct sun4i_tcon *tcon = container_of(timer, ++ struct sun4i_tcon, flip_timer); ++ ++ drm_crtc_handle_vblank(&tcon->crtc->crtc); ++ sun4i_tcon_finish_page_flip(tcon->drm, tcon->crtc); ++ ++ return HRTIMER_NORESTART; ++} ++ + static irqreturn_t sun4i_tcon_handler(int irq, void *private) + { + struct sun4i_tcon *tcon = private; +@@ -853,8 +867,12 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private) + SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT))) + return IRQ_NONE; + +- drm_crtc_handle_vblank(&scrtc->crtc); +- sun4i_tcon_finish_page_flip(drm, scrtc); ++ if (tcon->quirks->vblank_delay) { ++ hrtimer_start(&tcon->flip_timer, us_to_ktime(250), HRTIMER_MODE_REL); ++ } else { ++ drm_crtc_handle_vblank(&scrtc->crtc); ++ sun4i_tcon_finish_page_flip(drm, scrtc); ++ } + + /* Acknowledge the interrupt */ + regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, +@@ -903,6 +921,9 @@ static int sun4i_tcon_init_irq(struct device *dev, + struct platform_device *pdev = to_platform_device(dev); + int irq, ret; + ++ hrtimer_setup(&tcon->flip_timer, sun4i_tcon_flip_timer_cb, ++ CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; +@@ -1616,6 +1637,7 @@ static const struct sun4i_tcon_quirks sun50i_a64_lcd_quirks = { + .restores_rate = true, + .dclk_min_div = 1, + .setup_lvds_phy = sun6i_tcon_setup_lvds_phy, ++ .vblank_delay = true, + }; + + static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h +index 729d64b78846..2bf91fb4872c 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h +@@ -12,6 +12,7 @@ + + #include + ++#include + #include + #include + #include +@@ -252,6 +253,8 @@ struct sun4i_tcon_quirks { + bool polarity_in_ch0; /* some tcon1 channels have polarity bits in tcon0 pol register */ + bool restores_rate; /* restores the initial rate when rate changes */ + u8 dclk_min_div; /* minimum divider for TCON0 DCLK */ ++ bool vblank_delay; /* delay page flip reporting for 250us (TCON report vblank ++ shortly before register flip) */ + + /* callback to handle tcon muxing options */ + int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *); +@@ -289,6 +292,7 @@ struct sun4i_tcon { + + /* Associated crtc */ + struct sun4i_crtc *crtc; ++ struct hrtimer flip_timer; + + int id; + +-- +2.51.0 +