diff mbox series

[v6,3/3] drm/rockchip: Add basic RK3588 HDMI output support

Message ID 20240906-b4-rk3588-bridge-upstream-v6-3-a3128fb103eb@collabora.com (mailing list archive)
State New
Headers show
Series Add initial support for the Rockchip RK3588 HDMI TX Controller | expand

Commit Message

Cristian Ciocaltea Sept. 6, 2024, 1:17 a.m. UTC
The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
Samsung IP block.

Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
without audio, CEC or any of the HDMI 2.1 specific features.

Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/rockchip/Kconfig               |   8 +
 drivers/gpu/drm/rockchip/Makefile              |   1 +
 drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 437 +++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c    |   2 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h    |   1 +
 5 files changed, 449 insertions(+)

Comments

kernel test robot Sept. 9, 2024, 12:42 a.m. UTC | #1
Hi Cristian,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 8400291e289ee6b2bf9779ff1c83a291501f017b]

url:    https://github.com/intel-lab-lkp/linux/commits/Cristian-Ciocaltea/drm-bridge-synopsys-Add-DW-HDMI-QP-TX-Controller-support-library/20240906-092027
base:   8400291e289ee6b2bf9779ff1c83a291501f017b
patch link:    https://lore.kernel.org/r/20240906-b4-rk3588-bridge-upstream-v6-3-a3128fb103eb%40collabora.com
patch subject: [PATCH v6 3/3] drm/rockchip: Add basic RK3588 HDMI output support
config: powerpc64-randconfig-r122-20240908 (https://download.01.org/0day-ci/archive/20240909/202409090615.l6BkuR5K-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce: (https://download.01.org/0day-ci/archive/20240909/202409090615.l6BkuR5K-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409090615.l6BkuR5K-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c:679:24: sparse: sparse: incorrect type in return expression (different address spaces) @@     expected struct dw_hdmi_qp * @@     got void [noderef] __iomem *[assigned] regs @@
   drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c:679:24: sparse:     expected struct dw_hdmi_qp *
   drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c:679:24: sparse:     got void [noderef] __iomem *[assigned] regs

vim +679 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c

4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  653  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  654  struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  655  				   struct drm_encoder *encoder,
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  656  				   const struct dw_hdmi_qp_plat_data *plat_data)
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  657  {
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  658  	struct device *dev = &pdev->dev;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  659  	struct dw_hdmi_qp *hdmi;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  660  	void __iomem *regs;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  661  	int ret;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  662  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  663  	if (!plat_data->phy_ops || !plat_data->phy_ops->init ||
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  664  	    !plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) {
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  665  		dev_err(dev, "Missing platform PHY ops\n");
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  666  		return ERR_PTR(-ENODEV);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  667  	}
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  668  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  669  	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  670  	if (!hdmi)
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  671  		return ERR_PTR(-ENOMEM);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  672  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  673  	INIT_DELAYED_WORK(&hdmi->scramb_work, dw_hdmi_qp_scramb_work);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  674  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  675  	hdmi->dev = dev;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  676  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  677  	regs = devm_platform_ioremap_resource(pdev, 0);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  678  	if (IS_ERR(regs))
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06 @679  		return regs;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  680  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  681  	hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  682  	if (IS_ERR(hdmi->regm)) {
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  683  		dev_err(dev, "Failed to configure regmap\n");
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  684  		return ERR_CAST(hdmi->regm);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  685  	}
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  686  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  687  	hdmi->phy.ops = plat_data->phy_ops;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  688  	hdmi->phy.data = plat_data->phy_data;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  689  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  690  	dw_hdmi_qp_init_hw(hdmi);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  691  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  692  	ret = devm_request_threaded_irq(dev, plat_data->main_irq,
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  693  					dw_hdmi_qp_main_hardirq, NULL,
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  694  					IRQF_SHARED, dev_name(dev), hdmi);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  695  	if (ret)
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  696  		return ERR_PTR(ret);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  697  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  698  	hdmi->bridge.driver_private = hdmi;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  699  	hdmi->bridge.funcs = &dw_hdmi_qp_bridge_funcs;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  700  	hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  701  			   DRM_BRIDGE_OP_EDID |
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  702  			   DRM_BRIDGE_OP_HDMI |
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  703  			   DRM_BRIDGE_OP_HPD;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  704  	hdmi->bridge.of_node = pdev->dev.of_node;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  705  	hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  706  	hdmi->bridge.vendor = "Synopsys";
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  707  	hdmi->bridge.product = "DW HDMI QP TX";
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  708  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  709  	hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  710  	if (IS_ERR(hdmi->bridge.ddc))
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  711  		hdmi->bridge.ddc = NULL;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  712  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  713  	ret = devm_drm_bridge_add(dev, &hdmi->bridge);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  714  	if (ret)
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  715  		return ERR_PTR(ret);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  716  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  717  	ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  718  				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  719  	if (ret)
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  720  		return ERR_PTR(ret);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  721  
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  722  	return hdmi;
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  723  }
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  724  EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);
4ae2f13b217e6c Cristian Ciocaltea 2024-09-06  725
Heiko Stübner Sept. 10, 2024, 11:27 a.m. UTC | #2
Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
> Samsung IP block.
> 
> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
> without audio, CEC or any of the HDMI 2.1 specific features.
> 
> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> ---
>  drivers/gpu/drm/rockchip/Kconfig               |   8 +
>  drivers/gpu/drm/rockchip/Makefile              |   1 +
>  drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 437 +++++++++++++++++++++++++
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c    |   2 +
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h    |   1 +
>  5 files changed, 449 insertions(+)
> 
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 7df875e38517..4da7cef24f57 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -8,6 +8,7 @@ config DRM_ROCKCHIP
>  	select VIDEOMODE_HELPERS
>  	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
>  	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
> +	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
>  	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
>  	select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
>  	select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
> @@ -63,6 +64,13 @@ config ROCKCHIP_DW_HDMI
>  	  enable HDMI on RK3288 or RK3399 based SoC, you should select
>  	  this option.
>  
> +config ROCKCHIP_DW_HDMI_QP
> +	bool "Rockchip specific extensions for Synopsys DW HDMI QP"

this needs a
+       select DRM_BRIDGE_CONNECTOR

now, otherwise it can't link the drm_bridge_connector_init function
Cristian Ciocaltea Sept. 10, 2024, 12:06 p.m. UTC | #3
On 9/10/24 2:27 PM, Heiko Stübner wrote:
> Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
>> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
>> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
>> Samsung IP block.
>>
>> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
>> without audio, CEC or any of the HDMI 2.1 specific features.
>>
>> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
>> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
>> Tested-by: Heiko Stuebner <heiko@sntech.de>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
>> ---
>>  drivers/gpu/drm/rockchip/Kconfig               |   8 +
>>  drivers/gpu/drm/rockchip/Makefile              |   1 +
>>  drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 437 +++++++++++++++++++++++++
>>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c    |   2 +
>>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h    |   1 +
>>  5 files changed, 449 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
>> index 7df875e38517..4da7cef24f57 100644
>> --- a/drivers/gpu/drm/rockchip/Kconfig
>> +++ b/drivers/gpu/drm/rockchip/Kconfig
>> @@ -8,6 +8,7 @@ config DRM_ROCKCHIP
>>  	select VIDEOMODE_HELPERS
>>  	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
>>  	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
>> +	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
>>  	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
>>  	select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
>>  	select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
>> @@ -63,6 +64,13 @@ config ROCKCHIP_DW_HDMI
>>  	  enable HDMI on RK3288 or RK3399 based SoC, you should select
>>  	  this option.
>>  
>> +config ROCKCHIP_DW_HDMI_QP
>> +	bool "Rockchip specific extensions for Synopsys DW HDMI QP"
> 
> this needs a
> +       select DRM_BRIDGE_CONNECTOR
> 
> now, otherwise it can't link the drm_bridge_connector_init function

That's because of a recent change [1] which I was aware of, but didn't
actually follow when that got merged.  This series is still based on
v6.11-rc1, hence we should probably switch to linux-next starting with the
next revision.

Thanks,
Cristian

[1] https://lore.kernel.org/dri-devel/20240715-drm-bridge-connector-fix-hdmi-reset-v4-4-61e6417cfd99@linaro.org/
Heiko Stübner Sept. 10, 2024, 3:07 p.m. UTC | #4
Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
> Samsung IP block.
> 
> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
> without audio, CEC or any of the HDMI 2.1 specific features.
> 
> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>

I had switched from the v3 to this v6 in my playground-kernel today,
with v3 I've never seen those, but now with v6 I have gotten multiple
times:

[  805.730608] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP
[  805.739764] Modules linked in: snd_soc_simple_card crct10dif_ce snd_soc_simple_card_utils panthor drm_gpuvm drm_exec fuse
[  805.752031] CPU: 3 UID: 0 PID: 775 Comm: Xorg Not tainted 6.11.0-rc7-00099-g459302f1f908-dirty #934
[  805.762143] Hardware name: Theobroma Systems RK3588-Q7 SoM on Haikou devkit (DT)
[  805.770407] pstate: 204000c9 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  805.778186] pc : regmap_mmio_read32le+0x8/0x20
[  805.783155] lr : regmap_mmio_read+0x44/0x70
[  805.787828] sp : ffff80008293b830
[  805.791516] x29: ffff80008293b830 x28: ffff80008293bce8 x27: ffff0001f20ab080
[  805.799495] x26: ffff800081139500 x25: 0000000000000000 x24: 0000000000000010
[  805.807472] x23: 0000000000000000 x22: ffff0001f5a4b400 x21: ffff80008293b8c4
[  805.815450] x20: 0000000000000968 x19: ffff0001f5a27a80 x18: 0000000000000070
[  805.823428] x17: 0002441400000005 x16: 000004650441043c x15: 0438000008980804
[  805.831406] x14: 07d8089807800780 x13: 0438000008980804 x12: ffff800081133630
[  805.839384] x11: 0002441400000005 x10: 000004650441043c x9 : ffff800081a59000
[  805.847361] x8 : 07d8089807800780 x7 : 0000000000000000 x6 : ffff0001f5b453c0
[  805.855339] x5 : ffff800080750dc0 x4 : 0000000000000968 x3 : 0000000000000968
[  805.863316] x2 : ffff800080751520 x1 : 0000000000000968 x0 : ffff800083b20968
[  805.871294] Call trace:
[  805.874012]  regmap_mmio_read32le+0x8/0x20
[  805.878588]  _regmap_bus_reg_read+0x6c/0xac
[  805.883262]  _regmap_read+0x60/0xd8
[  805.887159]  _regmap_update_bits+0xf4/0x140
[  805.891832]  regmap_update_bits_base+0x64/0xa0
[  805.896797]  dw_hdmi_qp_bridge_atomic_enable+0x134/0x220
[  805.902734]  drm_atomic_bridge_chain_enable+0x54/0xc8
[  805.908380]  drm_atomic_helper_commit_modeset_enables+0x194/0x280
[  805.915190]  drm_atomic_helper_commit_tail_rpm+0x50/0xa0
[  805.921125]  commit_tail+0xa0/0x1a0
[  805.925021]  drm_atomic_helper_commit+0x17c/0x1b0
[  805.930276]  drm_atomic_commit+0xb8/0x100
[  805.934754]  drm_atomic_connector_commit_dpms+0xe0/0x110
[  805.940690]  drm_mode_obj_set_property_ioctl+0x1c0/0x420
[  805.946626]  drm_connector_property_set_ioctl+0x3c/0x68
[  805.952465]  drm_ioctl_kernel+0xc0/0x130
[  805.956846]  drm_ioctl+0x214/0x4a0
[  805.960643]  __arm64_sys_ioctl+0xac/0xf8
[  805.965025]  invoke_syscall+0x48/0x104
[  805.969214]  el0_svc_common.constprop.0+0x40/0xe0
[  805.974470]  do_el0_svc+0x1c/0x28
[  805.978171]  el0_svc+0x34/0xe0
[  805.981582]  el0t_64_sync_handler+0x120/0x12c
[  805.986449]  el0t_64_sync+0x190/0x194
[  805.990540] Code: d503201f d503201f f9400000 8b214000 (b9400000)

I guess that might be some clocking issue?
Heiko Stübner Sept. 10, 2024, 3:21 p.m. UTC | #5
Am Dienstag, 10. September 2024, 17:07:57 CEST schrieb Heiko Stübner:
> Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
> > The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
> > Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
> > Samsung IP block.
> > 
> > Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
> > without audio, CEC or any of the HDMI 2.1 specific features.
> > 
> > Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
> > Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> > Tested-by: Heiko Stuebner <heiko@sntech.de>
> > Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> 
> I had switched from the v3 to this v6 in my playground-kernel today,
> with v3 I've never seen those, but now with v6 I have gotten multiple
> times:
> 
> [  805.730608] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP
> [  805.739764] Modules linked in: snd_soc_simple_card crct10dif_ce snd_soc_simple_card_utils panthor drm_gpuvm drm_exec fuse
> [  805.752031] CPU: 3 UID: 0 PID: 775 Comm: Xorg Not tainted 6.11.0-rc7-00099-g459302f1f908-dirty #934
> [  805.762143] Hardware name: Theobroma Systems RK3588-Q7 SoM on Haikou devkit (DT)
> [  805.770407] pstate: 204000c9 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [  805.778186] pc : regmap_mmio_read32le+0x8/0x20
> [  805.783155] lr : regmap_mmio_read+0x44/0x70
> [  805.787828] sp : ffff80008293b830
> [  805.791516] x29: ffff80008293b830 x28: ffff80008293bce8 x27: ffff0001f20ab080
> [  805.799495] x26: ffff800081139500 x25: 0000000000000000 x24: 0000000000000010
> [  805.807472] x23: 0000000000000000 x22: ffff0001f5a4b400 x21: ffff80008293b8c4
> [  805.815450] x20: 0000000000000968 x19: ffff0001f5a27a80 x18: 0000000000000070
> [  805.823428] x17: 0002441400000005 x16: 000004650441043c x15: 0438000008980804
> [  805.831406] x14: 07d8089807800780 x13: 0438000008980804 x12: ffff800081133630
> [  805.839384] x11: 0002441400000005 x10: 000004650441043c x9 : ffff800081a59000
> [  805.847361] x8 : 07d8089807800780 x7 : 0000000000000000 x6 : ffff0001f5b453c0
> [  805.855339] x5 : ffff800080750dc0 x4 : 0000000000000968 x3 : 0000000000000968
> [  805.863316] x2 : ffff800080751520 x1 : 0000000000000968 x0 : ffff800083b20968
> [  805.871294] Call trace:
> [  805.874012]  regmap_mmio_read32le+0x8/0x20
> [  805.878588]  _regmap_bus_reg_read+0x6c/0xac
> [  805.883262]  _regmap_read+0x60/0xd8
> [  805.887159]  _regmap_update_bits+0xf4/0x140
> [  805.891832]  regmap_update_bits_base+0x64/0xa0
> [  805.896797]  dw_hdmi_qp_bridge_atomic_enable+0x134/0x220
> [  805.902734]  drm_atomic_bridge_chain_enable+0x54/0xc8
> [  805.908380]  drm_atomic_helper_commit_modeset_enables+0x194/0x280
> [  805.915190]  drm_atomic_helper_commit_tail_rpm+0x50/0xa0
> [  805.921125]  commit_tail+0xa0/0x1a0
> [  805.925021]  drm_atomic_helper_commit+0x17c/0x1b0
> [  805.930276]  drm_atomic_commit+0xb8/0x100
> [  805.934754]  drm_atomic_connector_commit_dpms+0xe0/0x110
> [  805.940690]  drm_mode_obj_set_property_ioctl+0x1c0/0x420
> [  805.946626]  drm_connector_property_set_ioctl+0x3c/0x68
> [  805.952465]  drm_ioctl_kernel+0xc0/0x130
> [  805.956846]  drm_ioctl+0x214/0x4a0
> [  805.960643]  __arm64_sys_ioctl+0xac/0xf8
> [  805.965025]  invoke_syscall+0x48/0x104
> [  805.969214]  el0_svc_common.constprop.0+0x40/0xe0
> [  805.974470]  do_el0_svc+0x1c/0x28
> [  805.978171]  el0_svc+0x34/0xe0
> [  805.981582]  el0t_64_sync_handler+0x120/0x12c
> [  805.986449]  el0t_64_sync+0x190/0x194
> [  805.990540] Code: d503201f d503201f f9400000 8b214000 (b9400000)
> 
> I guess that might be some clocking issue?

Forgot to add, this happens when the display has blanked and then is
supposed to unblank again.

Heiko
Cristian Ciocaltea Sept. 10, 2024, 3:41 p.m. UTC | #6
On 9/10/24 6:21 PM, Heiko Stübner wrote:
> Am Dienstag, 10. September 2024, 17:07:57 CEST schrieb Heiko Stübner:
>> Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
>>> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
>>> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
>>> Samsung IP block.
>>>
>>> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
>>> without audio, CEC or any of the HDMI 2.1 specific features.
>>>
>>> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
>>> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
>>> Tested-by: Heiko Stuebner <heiko@sntech.de>
>>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
>>
>> I had switched from the v3 to this v6 in my playground-kernel today,
>> with v3 I've never seen those, but now with v6 I have gotten multiple
>> times:
>>
>> [  805.730608] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP
>> [  805.739764] Modules linked in: snd_soc_simple_card crct10dif_ce snd_soc_simple_card_utils panthor drm_gpuvm drm_exec fuse
>> [  805.752031] CPU: 3 UID: 0 PID: 775 Comm: Xorg Not tainted 6.11.0-rc7-00099-g459302f1f908-dirty #934
>> [  805.762143] Hardware name: Theobroma Systems RK3588-Q7 SoM on Haikou devkit (DT)
>> [  805.770407] pstate: 204000c9 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>> [  805.778186] pc : regmap_mmio_read32le+0x8/0x20
>> [  805.783155] lr : regmap_mmio_read+0x44/0x70
>> [  805.787828] sp : ffff80008293b830
>> [  805.791516] x29: ffff80008293b830 x28: ffff80008293bce8 x27: ffff0001f20ab080
>> [  805.799495] x26: ffff800081139500 x25: 0000000000000000 x24: 0000000000000010
>> [  805.807472] x23: 0000000000000000 x22: ffff0001f5a4b400 x21: ffff80008293b8c4
>> [  805.815450] x20: 0000000000000968 x19: ffff0001f5a27a80 x18: 0000000000000070
>> [  805.823428] x17: 0002441400000005 x16: 000004650441043c x15: 0438000008980804
>> [  805.831406] x14: 07d8089807800780 x13: 0438000008980804 x12: ffff800081133630
>> [  805.839384] x11: 0002441400000005 x10: 000004650441043c x9 : ffff800081a59000
>> [  805.847361] x8 : 07d8089807800780 x7 : 0000000000000000 x6 : ffff0001f5b453c0
>> [  805.855339] x5 : ffff800080750dc0 x4 : 0000000000000968 x3 : 0000000000000968
>> [  805.863316] x2 : ffff800080751520 x1 : 0000000000000968 x0 : ffff800083b20968
>> [  805.871294] Call trace:
>> [  805.874012]  regmap_mmio_read32le+0x8/0x20
>> [  805.878588]  _regmap_bus_reg_read+0x6c/0xac
>> [  805.883262]  _regmap_read+0x60/0xd8
>> [  805.887159]  _regmap_update_bits+0xf4/0x140
>> [  805.891832]  regmap_update_bits_base+0x64/0xa0
>> [  805.896797]  dw_hdmi_qp_bridge_atomic_enable+0x134/0x220
>> [  805.902734]  drm_atomic_bridge_chain_enable+0x54/0xc8
>> [  805.908380]  drm_atomic_helper_commit_modeset_enables+0x194/0x280
>> [  805.915190]  drm_atomic_helper_commit_tail_rpm+0x50/0xa0
>> [  805.921125]  commit_tail+0xa0/0x1a0
>> [  805.925021]  drm_atomic_helper_commit+0x17c/0x1b0
>> [  805.930276]  drm_atomic_commit+0xb8/0x100
>> [  805.934754]  drm_atomic_connector_commit_dpms+0xe0/0x110
>> [  805.940690]  drm_mode_obj_set_property_ioctl+0x1c0/0x420
>> [  805.946626]  drm_connector_property_set_ioctl+0x3c/0x68
>> [  805.952465]  drm_ioctl_kernel+0xc0/0x130
>> [  805.956846]  drm_ioctl+0x214/0x4a0
>> [  805.960643]  __arm64_sys_ioctl+0xac/0xf8
>> [  805.965025]  invoke_syscall+0x48/0x104
>> [  805.969214]  el0_svc_common.constprop.0+0x40/0xe0
>> [  805.974470]  do_el0_svc+0x1c/0x28
>> [  805.978171]  el0_svc+0x34/0xe0
>> [  805.981582]  el0t_64_sync_handler+0x120/0x12c
>> [  805.986449]  el0t_64_sync+0x190/0x194
>> [  805.990540] Code: d503201f d503201f f9400000 8b214000 (b9400000)
>>
>> I guess that might be some clocking issue?
> 
> Forgot to add, this happens when the display has blanked and then is
> supposed to unblank again.

Hmm, I've never encountered this while testing with my v6.11-rc1 based
tree.  What is your current kernel base?  Did you change it while
switching from v3 to v6?

I'll rebase my tree onto latest linux-next and see if I can reproduce.

Thanks for reporting this!

Regards,
Cristian
Heiko Stübner Sept. 10, 2024, 4:39 p.m. UTC | #7
Am Dienstag, 10. September 2024, 17:41:42 CEST schrieb Cristian Ciocaltea:
> On 9/10/24 6:21 PM, Heiko Stübner wrote:
> > Am Dienstag, 10. September 2024, 17:07:57 CEST schrieb Heiko Stübner:
> >> Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
> >>> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
> >>> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
> >>> Samsung IP block.
> >>>
> >>> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
> >>> without audio, CEC or any of the HDMI 2.1 specific features.
> >>>
> >>> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
> >>> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> >>> Tested-by: Heiko Stuebner <heiko@sntech.de>
> >>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> >>
> >> I had switched from the v3 to this v6 in my playground-kernel today,
> >> with v3 I've never seen those, but now with v6 I have gotten multiple
> >> times:
> >>
> >> [  805.730608] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP
> >> [  805.739764] Modules linked in: snd_soc_simple_card crct10dif_ce snd_soc_simple_card_utils panthor drm_gpuvm drm_exec fuse
> >> [  805.752031] CPU: 3 UID: 0 PID: 775 Comm: Xorg Not tainted 6.11.0-rc7-00099-g459302f1f908-dirty #934
> >> [  805.762143] Hardware name: Theobroma Systems RK3588-Q7 SoM on Haikou devkit (DT)
> >> [  805.770407] pstate: 204000c9 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> >> [  805.778186] pc : regmap_mmio_read32le+0x8/0x20
> >> [  805.783155] lr : regmap_mmio_read+0x44/0x70
> >> [  805.787828] sp : ffff80008293b830
> >> [  805.791516] x29: ffff80008293b830 x28: ffff80008293bce8 x27: ffff0001f20ab080
> >> [  805.799495] x26: ffff800081139500 x25: 0000000000000000 x24: 0000000000000010
> >> [  805.807472] x23: 0000000000000000 x22: ffff0001f5a4b400 x21: ffff80008293b8c4
> >> [  805.815450] x20: 0000000000000968 x19: ffff0001f5a27a80 x18: 0000000000000070
> >> [  805.823428] x17: 0002441400000005 x16: 000004650441043c x15: 0438000008980804
> >> [  805.831406] x14: 07d8089807800780 x13: 0438000008980804 x12: ffff800081133630
> >> [  805.839384] x11: 0002441400000005 x10: 000004650441043c x9 : ffff800081a59000
> >> [  805.847361] x8 : 07d8089807800780 x7 : 0000000000000000 x6 : ffff0001f5b453c0
> >> [  805.855339] x5 : ffff800080750dc0 x4 : 0000000000000968 x3 : 0000000000000968
> >> [  805.863316] x2 : ffff800080751520 x1 : 0000000000000968 x0 : ffff800083b20968
> >> [  805.871294] Call trace:
> >> [  805.874012]  regmap_mmio_read32le+0x8/0x20
> >> [  805.878588]  _regmap_bus_reg_read+0x6c/0xac
> >> [  805.883262]  _regmap_read+0x60/0xd8
> >> [  805.887159]  _regmap_update_bits+0xf4/0x140
> >> [  805.891832]  regmap_update_bits_base+0x64/0xa0
> >> [  805.896797]  dw_hdmi_qp_bridge_atomic_enable+0x134/0x220
> >> [  805.902734]  drm_atomic_bridge_chain_enable+0x54/0xc8
> >> [  805.908380]  drm_atomic_helper_commit_modeset_enables+0x194/0x280
> >> [  805.915190]  drm_atomic_helper_commit_tail_rpm+0x50/0xa0
> >> [  805.921125]  commit_tail+0xa0/0x1a0
> >> [  805.925021]  drm_atomic_helper_commit+0x17c/0x1b0
> >> [  805.930276]  drm_atomic_commit+0xb8/0x100
> >> [  805.934754]  drm_atomic_connector_commit_dpms+0xe0/0x110
> >> [  805.940690]  drm_mode_obj_set_property_ioctl+0x1c0/0x420
> >> [  805.946626]  drm_connector_property_set_ioctl+0x3c/0x68
> >> [  805.952465]  drm_ioctl_kernel+0xc0/0x130
> >> [  805.956846]  drm_ioctl+0x214/0x4a0
> >> [  805.960643]  __arm64_sys_ioctl+0xac/0xf8
> >> [  805.965025]  invoke_syscall+0x48/0x104
> >> [  805.969214]  el0_svc_common.constprop.0+0x40/0xe0
> >> [  805.974470]  do_el0_svc+0x1c/0x28
> >> [  805.978171]  el0_svc+0x34/0xe0
> >> [  805.981582]  el0t_64_sync_handler+0x120/0x12c
> >> [  805.986449]  el0t_64_sync+0x190/0x194
> >> [  805.990540] Code: d503201f d503201f f9400000 8b214000 (b9400000)
> >>
> >> I guess that might be some clocking issue?
> > 
> > Forgot to add, this happens when the display has blanked and then is
> > supposed to unblank again.
> 
> Hmm, I've never encountered this while testing with my v6.11-rc1 based
> tree.  What is your current kernel base?  Did you change it while
> switching from v3 to v6?
> 
> I'll rebase my tree onto latest linux-next and see if I can reproduce.

The setup is 6.11-rc7 with your hdmi series + my wip dsi + X11 running
on top.

At some point after being idle a while this blanks the display, which will
probably turn off clocks and such. After moving the mouse or just
doing anything else that unblanks the display, that splat happens.

Apart from updating mesa from 24.2.0 to 24.2.2 I haven't changed
anything in my test-setup so far.
Heiko Stübner Sept. 10, 2024, 7:08 p.m. UTC | #8
Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
> Samsung IP block.
> 
> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
> without audio, CEC or any of the HDMI 2.1 specific features.
> 
> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>

[...]

> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index 3ff7b21c0414..3eab662a5a1d 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -11,6 +11,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o

> +static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
> +				    void *data)
> +{
> +	static const char * const clk_names[] = {
> +		"pclk", "earc", "aud", "hdp", "hclk_vo1",
> +		"ref" /* keep "ref" last */
> +	};

[...]

> +	for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
> +		clk = devm_clk_get_enabled(hdmi->dev, clk_names[i]);
> +
> +		if (IS_ERR(clk)) {
> +			ret = PTR_ERR(clk);
> +			if (ret != -EPROBE_DEFER)
> +				drm_err(hdmi, "Failed to get %s clock: %d\n",
> +					clk_names[i], ret);
> +			return ret;
> +		}
> +	}
> +	hdmi->ref_clk = clk;

How about using devm_clk_bulk_get_all_enable() for everything except the
refclk and a separate call to devm_clk_get_enabled() for that refclk .

That hdmi->ref_clk just accidentially falls out of that loop at the end
looks somewhat strange, so getting and keeping that refclk
separately would make this look cleaner.
Heiko Stübner Sept. 10, 2024, 8:49 p.m. UTC | #9
Am Dienstag, 10. September 2024, 18:39:54 CEST schrieb Heiko Stübner:
> Am Dienstag, 10. September 2024, 17:41:42 CEST schrieb Cristian Ciocaltea:
> > On 9/10/24 6:21 PM, Heiko Stübner wrote:
> > > Am Dienstag, 10. September 2024, 17:07:57 CEST schrieb Heiko Stübner:
> > >> Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
> > >>> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
> > >>> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
> > >>> Samsung IP block.
> > >>>
> > >>> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
> > >>> without audio, CEC or any of the HDMI 2.1 specific features.
> > >>>
> > >>> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
> > >>> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> > >>> Tested-by: Heiko Stuebner <heiko@sntech.de>
> > >>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> > >>
> > >> I had switched from the v3 to this v6 in my playground-kernel today,
> > >> with v3 I've never seen those, but now with v6 I have gotten multiple
> > >> times:
> > >>
> > >> [  805.730608] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP
> > >> [  805.739764] Modules linked in: snd_soc_simple_card crct10dif_ce snd_soc_simple_card_utils panthor drm_gpuvm drm_exec fuse
> > >> [  805.752031] CPU: 3 UID: 0 PID: 775 Comm: Xorg Not tainted 6.11.0-rc7-00099-g459302f1f908-dirty #934
> > >> [  805.762143] Hardware name: Theobroma Systems RK3588-Q7 SoM on Haikou devkit (DT)
> > >> [  805.770407] pstate: 204000c9 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> > >> [  805.778186] pc : regmap_mmio_read32le+0x8/0x20
> > >> [  805.783155] lr : regmap_mmio_read+0x44/0x70
> > >> [  805.787828] sp : ffff80008293b830
> > >> [  805.791516] x29: ffff80008293b830 x28: ffff80008293bce8 x27: ffff0001f20ab080
> > >> [  805.799495] x26: ffff800081139500 x25: 0000000000000000 x24: 0000000000000010
> > >> [  805.807472] x23: 0000000000000000 x22: ffff0001f5a4b400 x21: ffff80008293b8c4
> > >> [  805.815450] x20: 0000000000000968 x19: ffff0001f5a27a80 x18: 0000000000000070
> > >> [  805.823428] x17: 0002441400000005 x16: 000004650441043c x15: 0438000008980804
> > >> [  805.831406] x14: 07d8089807800780 x13: 0438000008980804 x12: ffff800081133630
> > >> [  805.839384] x11: 0002441400000005 x10: 000004650441043c x9 : ffff800081a59000
> > >> [  805.847361] x8 : 07d8089807800780 x7 : 0000000000000000 x6 : ffff0001f5b453c0
> > >> [  805.855339] x5 : ffff800080750dc0 x4 : 0000000000000968 x3 : 0000000000000968
> > >> [  805.863316] x2 : ffff800080751520 x1 : 0000000000000968 x0 : ffff800083b20968
> > >> [  805.871294] Call trace:
> > >> [  805.874012]  regmap_mmio_read32le+0x8/0x20
> > >> [  805.878588]  _regmap_bus_reg_read+0x6c/0xac
> > >> [  805.883262]  _regmap_read+0x60/0xd8
> > >> [  805.887159]  _regmap_update_bits+0xf4/0x140
> > >> [  805.891832]  regmap_update_bits_base+0x64/0xa0
> > >> [  805.896797]  dw_hdmi_qp_bridge_atomic_enable+0x134/0x220
> > >> [  805.902734]  drm_atomic_bridge_chain_enable+0x54/0xc8
> > >> [  805.908380]  drm_atomic_helper_commit_modeset_enables+0x194/0x280
> > >> [  805.915190]  drm_atomic_helper_commit_tail_rpm+0x50/0xa0
> > >> [  805.921125]  commit_tail+0xa0/0x1a0
> > >> [  805.925021]  drm_atomic_helper_commit+0x17c/0x1b0
> > >> [  805.930276]  drm_atomic_commit+0xb8/0x100
> > >> [  805.934754]  drm_atomic_connector_commit_dpms+0xe0/0x110
> > >> [  805.940690]  drm_mode_obj_set_property_ioctl+0x1c0/0x420
> > >> [  805.946626]  drm_connector_property_set_ioctl+0x3c/0x68
> > >> [  805.952465]  drm_ioctl_kernel+0xc0/0x130
> > >> [  805.956846]  drm_ioctl+0x214/0x4a0
> > >> [  805.960643]  __arm64_sys_ioctl+0xac/0xf8
> > >> [  805.965025]  invoke_syscall+0x48/0x104
> > >> [  805.969214]  el0_svc_common.constprop.0+0x40/0xe0
> > >> [  805.974470]  do_el0_svc+0x1c/0x28
> > >> [  805.978171]  el0_svc+0x34/0xe0
> > >> [  805.981582]  el0t_64_sync_handler+0x120/0x12c
> > >> [  805.986449]  el0t_64_sync+0x190/0x194
> > >> [  805.990540] Code: d503201f d503201f f9400000 8b214000 (b9400000)
> > >>
> > >> I guess that might be some clocking issue?
> > > 
> > > Forgot to add, this happens when the display has blanked and then is
> > > supposed to unblank again.
> > 
> > Hmm, I've never encountered this while testing with my v6.11-rc1 based
> > tree.  What is your current kernel base?  Did you change it while
> > switching from v3 to v6?
> > 
> > I'll rebase my tree onto latest linux-next and see if I can reproduce.
> 
> The setup is 6.11-rc7 with your hdmi series + my wip dsi + X11 running
> on top.
> 
> At some point after being idle a while this blanks the display, which will
> probably turn off clocks and such. After moving the mouse or just
> doing anything else that unblanks the display, that splat happens.
> 
> Apart from updating mesa from 24.2.0 to 24.2.2 I haven't changed
> anything in my test-setup so far.

So now I've re-tested all :-) ... test scenario was that I reverted the v6
patches and then applied the older versions (and fixed up the dts if
needed wrt the vo{1}-grf thing). So now really only the hdmi driver
changed. So I booted, waited for the display to blank and hit reboot
on the serial console:

- v3 console output turned back on and rebooted fine
- v4 console output turned back on and rebooted fine
- v5 hit the error from above
- v6 hit the error from above

So something between v4 and v5 seems to cause the hickup.
Cristian Ciocaltea Sept. 11, 2024, 1:51 a.m. UTC | #10
On 9/10/24 11:49 PM, Heiko Stübner wrote:
> Am Dienstag, 10. September 2024, 18:39:54 CEST schrieb Heiko Stübner:
>> Am Dienstag, 10. September 2024, 17:41:42 CEST schrieb Cristian Ciocaltea:
>>> On 9/10/24 6:21 PM, Heiko Stübner wrote:
>>>> Am Dienstag, 10. September 2024, 17:07:57 CEST schrieb Heiko Stübner:
>>>>> Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
>>>>>> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
>>>>>> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
>>>>>> Samsung IP block.
>>>>>>
>>>>>> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
>>>>>> without audio, CEC or any of the HDMI 2.1 specific features.
>>>>>>
>>>>>> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
>>>>>> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
>>>>>> Tested-by: Heiko Stuebner <heiko@sntech.de>
>>>>>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
>>>>>
>>>>> I had switched from the v3 to this v6 in my playground-kernel today,
>>>>> with v3 I've never seen those, but now with v6 I have gotten multiple
>>>>> times:
>>>>>
>>>>> [  805.730608] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP
>>>>> [  805.739764] Modules linked in: snd_soc_simple_card crct10dif_ce snd_soc_simple_card_utils panthor drm_gpuvm drm_exec fuse
>>>>> [  805.752031] CPU: 3 UID: 0 PID: 775 Comm: Xorg Not tainted 6.11.0-rc7-00099-g459302f1f908-dirty #934
>>>>> [  805.762143] Hardware name: Theobroma Systems RK3588-Q7 SoM on Haikou devkit (DT)
>>>>> [  805.770407] pstate: 204000c9 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>>> [  805.778186] pc : regmap_mmio_read32le+0x8/0x20
>>>>> [  805.783155] lr : regmap_mmio_read+0x44/0x70
>>>>> [  805.787828] sp : ffff80008293b830
>>>>> [  805.791516] x29: ffff80008293b830 x28: ffff80008293bce8 x27: ffff0001f20ab080
>>>>> [  805.799495] x26: ffff800081139500 x25: 0000000000000000 x24: 0000000000000010
>>>>> [  805.807472] x23: 0000000000000000 x22: ffff0001f5a4b400 x21: ffff80008293b8c4
>>>>> [  805.815450] x20: 0000000000000968 x19: ffff0001f5a27a80 x18: 0000000000000070
>>>>> [  805.823428] x17: 0002441400000005 x16: 000004650441043c x15: 0438000008980804
>>>>> [  805.831406] x14: 07d8089807800780 x13: 0438000008980804 x12: ffff800081133630
>>>>> [  805.839384] x11: 0002441400000005 x10: 000004650441043c x9 : ffff800081a59000
>>>>> [  805.847361] x8 : 07d8089807800780 x7 : 0000000000000000 x6 : ffff0001f5b453c0
>>>>> [  805.855339] x5 : ffff800080750dc0 x4 : 0000000000000968 x3 : 0000000000000968
>>>>> [  805.863316] x2 : ffff800080751520 x1 : 0000000000000968 x0 : ffff800083b20968
>>>>> [  805.871294] Call trace:
>>>>> [  805.874012]  regmap_mmio_read32le+0x8/0x20
>>>>> [  805.878588]  _regmap_bus_reg_read+0x6c/0xac
>>>>> [  805.883262]  _regmap_read+0x60/0xd8
>>>>> [  805.887159]  _regmap_update_bits+0xf4/0x140
>>>>> [  805.891832]  regmap_update_bits_base+0x64/0xa0
>>>>> [  805.896797]  dw_hdmi_qp_bridge_atomic_enable+0x134/0x220
>>>>> [  805.902734]  drm_atomic_bridge_chain_enable+0x54/0xc8
>>>>> [  805.908380]  drm_atomic_helper_commit_modeset_enables+0x194/0x280
>>>>> [  805.915190]  drm_atomic_helper_commit_tail_rpm+0x50/0xa0
>>>>> [  805.921125]  commit_tail+0xa0/0x1a0
>>>>> [  805.925021]  drm_atomic_helper_commit+0x17c/0x1b0
>>>>> [  805.930276]  drm_atomic_commit+0xb8/0x100
>>>>> [  805.934754]  drm_atomic_connector_commit_dpms+0xe0/0x110
>>>>> [  805.940690]  drm_mode_obj_set_property_ioctl+0x1c0/0x420
>>>>> [  805.946626]  drm_connector_property_set_ioctl+0x3c/0x68
>>>>> [  805.952465]  drm_ioctl_kernel+0xc0/0x130
>>>>> [  805.956846]  drm_ioctl+0x214/0x4a0
>>>>> [  805.960643]  __arm64_sys_ioctl+0xac/0xf8
>>>>> [  805.965025]  invoke_syscall+0x48/0x104
>>>>> [  805.969214]  el0_svc_common.constprop.0+0x40/0xe0
>>>>> [  805.974470]  do_el0_svc+0x1c/0x28
>>>>> [  805.978171]  el0_svc+0x34/0xe0
>>>>> [  805.981582]  el0t_64_sync_handler+0x120/0x12c
>>>>> [  805.986449]  el0t_64_sync+0x190/0x194
>>>>> [  805.990540] Code: d503201f d503201f f9400000 8b214000 (b9400000)
>>>>>
>>>>> I guess that might be some clocking issue?
>>>>
>>>> Forgot to add, this happens when the display has blanked and then is
>>>> supposed to unblank again.
>>>
>>> Hmm, I've never encountered this while testing with my v6.11-rc1 based
>>> tree.  What is your current kernel base?  Did you change it while
>>> switching from v3 to v6?
>>>
>>> I'll rebase my tree onto latest linux-next and see if I can reproduce.
>>
>> The setup is 6.11-rc7 with your hdmi series + my wip dsi + X11 running
>> on top.
>>
>> At some point after being idle a while this blanks the display, which will
>> probably turn off clocks and such. After moving the mouse or just
>> doing anything else that unblanks the display, that splat happens.
>>
>> Apart from updating mesa from 24.2.0 to 24.2.2 I haven't changed
>> anything in my test-setup so far.
> 
> So now I've re-tested all :-) ... test scenario was that I reverted the v6
> patches and then applied the older versions (and fixed up the dts if
> needed wrt the vo{1}-grf thing). So now really only the hdmi driver
> changed. So I booted, waited for the display to blank and hit reboot
> on the serial console:
> 
> - v3 console output turned back on and rebooted fine
> - v4 console output turned back on and rebooted fine
> - v5 hit the error from above
> - v6 hit the error from above
> 
> So something between v4 and v5 seems to cause the hickup.

Thanks a lot for taking the time to bisect it!  This is indeed a clock
related regression introduced by the recent changes around scrambling.

I couldn't initially reproduce because I had the HDMI0 PHY clock provider
enabled, required to verify the high TMDS clock ratio and scrambling setup
in 4K@60Hz display mode.  Without that clock provider enabled, the PHY
eventually enters runtime PM suspend state, which for some reason causes
the splat when trying to access the LINK_CONFIG0 register.

To unblock the series, I would consider dropping the scrambling support for
now, as it turned to be far more complicated to have it properly handled
than I initially assumed.  Will move this to a separate WIP patch in my dev
tree, along the vop2 improvements for display modes handling, and resubmit
as soon as I get this work in a better shape.
Cristian Ciocaltea Sept. 14, 2024, 6:28 p.m. UTC | #11
On 9/10/24 10:08 PM, Heiko Stübner wrote:
> Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:
>> The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
>> Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
>> Samsung IP block.
>>
>> Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
>> without audio, CEC or any of the HDMI 2.1 specific features.
>>
>> Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
>> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
>> Tested-by: Heiko Stuebner <heiko@sntech.de>
>> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> 
> [...]
> 
>> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
>> index 3ff7b21c0414..3eab662a5a1d 100644
>> --- a/drivers/gpu/drm/rockchip/Makefile
>> +++ b/drivers/gpu/drm/rockchip/Makefile
>> @@ -11,6 +11,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
> 
>> +static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
>> +				    void *data)
>> +{
>> +	static const char * const clk_names[] = {
>> +		"pclk", "earc", "aud", "hdp", "hclk_vo1",
>> +		"ref" /* keep "ref" last */
>> +	};
> 
> [...]
> 
>> +	for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
>> +		clk = devm_clk_get_enabled(hdmi->dev, clk_names[i]);
>> +
>> +		if (IS_ERR(clk)) {
>> +			ret = PTR_ERR(clk);
>> +			if (ret != -EPROBE_DEFER)
>> +				drm_err(hdmi, "Failed to get %s clock: %d\n",
>> +					clk_names[i], ret);
>> +			return ret;
>> +		}
>> +	}
>> +	hdmi->ref_clk = clk;
> 
> How about using devm_clk_bulk_get_all_enable() for everything except the
> refclk and a separate call to devm_clk_get_enabled() for that refclk .

This helper seems to be partially broken as it doesn't return the number of
clocks stored in the clk_bulk_data table referenced by the clks argument,
meaning it's not possible to iterate these clocks.  I provided a new helper
[1] as a possible fix.

If that gets accepted, we could rewrite this as:

	ret = devm_clk_bulk_get_all_enabled(hdmi->dev, &clks);
	if (ret < 0) {
		drm_err(hdmi, "Failed to get clocks: %d\n", ret);
		return ret;
	}

	for (i = 0; i < ret; i++) {
		if (!strcmp(clks[i].id, "ref")) {
			hdmi->ref_clk = clks[1].clk;
			break;
		}
	}
	if (!hdmi->ref_clk) {
		drm_err(hdmi, "Missing ref clock\n");
		return -EINVAL;
	}

> That hdmi->ref_clk just accidentially falls out of that loop at the end
> looks somewhat strange, so getting and keeping that refclk
> separately would make this look cleaner.

I've added /* keep "ref" last */ comment above, but I agree it's not really
the best approach.

I'm going to submit v7 in the meantime, as this was the last remaining open
topic on my list.  I guess we can figure this out afterwards.

Thanks,
Cristian

[1] https://lore.kernel.org/lkml/20240914-clk_bulk_ena_fix-v1-0-ce3537585c06@collabora.com/
Heiko Stübner Sept. 15, 2024, 6:13 a.m. UTC | #12
Am Samstag, 14. September 2024, 20:28:59 CEST schrieb Cristian Ciocaltea:
> On 9/10/24 10:08 PM, Heiko Stübner wrote:
> > Am Freitag, 6. September 2024, 03:17:42 CEST schrieb Cristian Ciocaltea:

> > That hdmi->ref_clk just accidentially falls out of that loop at the end
> > looks somewhat strange, so getting and keeping that refclk
> > separately would make this look cleaner.
> 
> I've added /* keep "ref" last */ comment above, but I agree it's not really
> the best approach.
> 
> I'm going to submit v7 in the meantime, as this was the last remaining open
> topic on my list.  I guess we can figure this out afterwards.

yep, that is fine to figure out later, as it's mainly a style thing.
diff mbox series

Patch

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 7df875e38517..4da7cef24f57 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -8,6 +8,7 @@  config DRM_ROCKCHIP
 	select VIDEOMODE_HELPERS
 	select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
 	select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
+	select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
 	select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
 	select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
 	select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
@@ -63,6 +64,13 @@  config ROCKCHIP_DW_HDMI
 	  enable HDMI on RK3288 or RK3399 based SoC, you should select
 	  this option.
 
+config ROCKCHIP_DW_HDMI_QP
+	bool "Rockchip specific extensions for Synopsys DW HDMI QP"
+	help
+	  This selects support for Rockchip SoC specific extensions
+	  for the Synopsys DesignWare HDMI QP driver. If you want to
+	  enable HDMI on RK3588 based SoC, you should select this option.
+
 config ROCKCHIP_DW_MIPI_DSI
 	bool "Rockchip specific extensions for Synopsys DW MIPI DSI"
 	select GENERIC_PHY_MIPI_DPHY
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 3ff7b21c0414..3eab662a5a1d 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -11,6 +11,7 @@  rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
+rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI_QP) += dw_hdmi_qp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
new file mode 100644
index 000000000000..a743ed3a2090
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -0,0 +1,437 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2024 Collabora Ltd.
+ *
+ * Author: Algea Cao <algea.cao@rock-chips.com>
+ * Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+
+#include <drm/bridge/dw_hdmi_qp.h>
+#include <drm/drm_bridge_connector.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "rockchip_drm_drv.h"
+
+#define RK3588_GRF_SOC_CON2		0x0308
+#define RK3588_HDMI0_HPD_INT_MSK	BIT(13)
+#define RK3588_HDMI0_HPD_INT_CLR	BIT(12)
+#define RK3588_GRF_SOC_CON7		0x031c
+#define RK3588_SET_HPD_PATH_MASK	GENMASK(13, 12)
+#define RK3588_GRF_SOC_STATUS1		0x0384
+#define RK3588_HDMI0_LEVEL_INT		BIT(16)
+#define RK3588_GRF_VO1_CON3		0x000c
+#define RK3588_SCLIN_MASK		BIT(9)
+#define RK3588_SDAIN_MASK		BIT(10)
+#define RK3588_MODE_MASK		BIT(11)
+#define RK3588_I2S_SEL_MASK		BIT(13)
+#define RK3588_GRF_VO1_CON9		0x0024
+#define RK3588_HDMI0_GRANT_SEL		BIT(10)
+
+#define HIWORD_UPDATE(val, mask)	((val) | (mask) << 16)
+
+struct rockchip_hdmi_qp {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regmap *vo_regmap;
+	struct rockchip_encoder encoder;
+	struct clk *ref_clk;
+	struct dw_hdmi_qp *hdmi;
+	struct phy *phy;
+	struct gpio_desc *enable_gpio;
+	struct delayed_work hpd_work;
+};
+
+static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder)
+{
+	struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
+
+	return container_of(rkencoder, struct rockchip_hdmi_qp, encoder);
+}
+
+static void
+dw_hdmi_qp_rockchip_encoder_mode_set(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adj_mode)
+{
+	struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
+
+	clk_set_rate(hdmi->ref_clk, adj_mode->clock * 1000);
+}
+
+static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
+{
+	struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
+	struct drm_crtc *crtc = encoder->crtc;
+	int rate;
+
+	/* Unconditionally switch to TMDS as FRL is not yet supported */
+	gpiod_set_value(hdmi->enable_gpio, 1);
+
+	if (crtc && crtc->state) {
+		clk_set_rate(hdmi->ref_clk,
+			     crtc->state->adjusted_mode.crtc_clock * 1000);
+		/*
+		 * FIXME: Temporary workaround to pass pixel clock rate
+		 * to the PHY driver until phy_configure_opts_hdmi
+		 * becomes available in the PHY API. See also the related
+		 * comment in rk_hdptx_phy_power_on() from
+		 * drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+		 */
+		rate = crtc->state->mode.clock * 10;
+		phy_set_bus_width(hdmi->phy, rate);
+		drm_dbg(hdmi, "%s set bus_width=%u\n", __func__, rate);
+	}
+}
+
+static int
+dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
+					 struct drm_crtc_state *crtc_state,
+					 struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+
+	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+	s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+
+	return 0;
+}
+
+static const struct
+drm_encoder_helper_funcs dw_hdmi_qp_rockchip_encoder_helper_funcs = {
+	.mode_set	= dw_hdmi_qp_rockchip_encoder_mode_set,
+	.enable		= dw_hdmi_qp_rockchip_encoder_enable,
+	.atomic_check	= dw_hdmi_qp_rockchip_encoder_atomic_check,
+};
+
+static int dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp *dw_hdmi, void *data,
+				      const struct drm_display_info *display)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+	return phy_power_on(hdmi->phy);
+}
+
+static void dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp *dw_hdmi,
+					  void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+	phy_power_off(hdmi->phy);
+}
+
+static enum drm_connector_status
+dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+	u32 val;
+
+	regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val);
+
+	return val & RK3588_HDMI0_LEVEL_INT ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static void dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+	regmap_write(hdmi->regmap,
+		     RK3588_GRF_SOC_CON2,
+		     HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
+				   RK3588_HDMI0_HPD_INT_CLR |
+				   RK3588_HDMI0_HPD_INT_MSK));
+}
+
+static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
+	.init		= dw_hdmi_qp_rk3588_phy_init,
+	.disable	= dw_hdmi_qp_rk3588_phy_disable,
+	.read_hpd	= dw_hdmi_qp_rk3588_read_hpd,
+	.setup_hpd	= dw_hdmi_qp_rk3588_setup_hpd,
+};
+
+static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work)
+{
+	struct rockchip_hdmi_qp *hdmi = container_of(work,
+						     struct rockchip_hdmi_qp,
+						     hpd_work.work);
+	struct drm_device *drm = hdmi->encoder.encoder.dev;
+	bool changed;
+
+	if (drm) {
+		changed = drm_helper_hpd_irq_event(drm);
+		if (changed)
+			drm_dbg(hdmi, "connector status changed\n");
+	}
+}
+
+static irqreturn_t dw_hdmi_qp_rk3588_hardirq(int irq, void *dev_id)
+{
+	struct rockchip_hdmi_qp *hdmi = dev_id;
+	u32 intr_stat, val;
+
+	regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
+
+	if (intr_stat) {
+		val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK,
+				    RK3588_HDMI0_HPD_INT_MSK);
+		regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+		return IRQ_WAKE_THREAD;
+	}
+
+	return IRQ_NONE;
+}
+
+static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id)
+{
+	struct rockchip_hdmi_qp *hdmi = dev_id;
+	u32 intr_stat, val;
+	int debounce_ms;
+
+	regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
+	if (!intr_stat)
+		return IRQ_NONE;
+
+	val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
+			    RK3588_HDMI0_HPD_INT_CLR);
+	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+
+	debounce_ms = intr_stat & RK3588_HDMI0_LEVEL_INT ? 150 : 20;
+	mod_delayed_work(system_wq, &hdmi->hpd_work,
+			 msecs_to_jiffies(debounce_ms));
+
+	val |= HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK);
+	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+
+	return IRQ_HANDLED;
+}
+
+static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = {
+	{ .compatible = "rockchip,rk3588-dw-hdmi-qp",
+	  .data = &rk3588_hdmi_phy_ops },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids);
+
+static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
+				    void *data)
+{
+	static const char * const clk_names[] = {
+		"pclk", "earc", "aud", "hdp", "hclk_vo1",
+		"ref" /* keep "ref" last */
+	};
+	struct platform_device *pdev = to_platform_device(dev);
+	struct dw_hdmi_qp_plat_data plat_data;
+	struct drm_device *drm = data;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct rockchip_hdmi_qp *hdmi;
+	struct clk *clk;
+	int ret, irq, i;
+	u32 val;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+	if (!hdmi)
+		return -ENOMEM;
+
+	plat_data.phy_ops = of_device_get_match_data(dev);
+	if (!plat_data.phy_ops)
+		return -ENODEV;
+
+	plat_data.phy_data = hdmi;
+	hdmi->dev = &pdev->dev;
+
+	encoder = &hdmi->encoder.encoder;
+	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+
+	rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder,
+						  dev->of_node, 0, 0);
+	/*
+	 * If we failed to find the CRTC(s) which this encoder is
+	 * supposed to be connected to, it's because the CRTC has
+	 * not been registered yet.  Defer probing, and hope that
+	 * the required CRTC is added later.
+	 */
+	if (encoder->possible_crtcs == 0)
+		return -EPROBE_DEFER;
+
+	hdmi->regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+						       "rockchip,grf");
+	if (IS_ERR(hdmi->regmap)) {
+		drm_err(hdmi, "Unable to get rockchip,grf\n");
+		return PTR_ERR(hdmi->regmap);
+	}
+
+	hdmi->vo_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+							  "rockchip,vo-grf");
+	if (IS_ERR(hdmi->vo_regmap)) {
+		drm_err(hdmi, "Unable to get rockchip,vo-grf\n");
+		return PTR_ERR(hdmi->vo_regmap);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
+		clk = devm_clk_get_enabled(hdmi->dev, clk_names[i]);
+
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			if (ret != -EPROBE_DEFER)
+				drm_err(hdmi, "Failed to get %s clock: %d\n",
+					clk_names[i], ret);
+			return ret;
+		}
+	}
+	hdmi->ref_clk = clk;
+
+	hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable",
+						    GPIOD_OUT_HIGH);
+	if (IS_ERR(hdmi->enable_gpio)) {
+		ret = PTR_ERR(hdmi->enable_gpio);
+		drm_err(hdmi, "Failed to request enable GPIO: %d\n", ret);
+		return ret;
+	}
+
+	hdmi->phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
+	if (IS_ERR(hdmi->phy)) {
+		ret = PTR_ERR(hdmi->phy);
+		if (ret != -EPROBE_DEFER)
+			drm_err(hdmi, "failed to get phy: %d\n", ret);
+		return ret;
+	}
+
+	val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
+	      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
+	      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
+	      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
+	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON3, val);
+
+	val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
+			    RK3588_SET_HPD_PATH_MASK);
+	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
+
+	val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
+			    RK3588_HDMI0_GRANT_SEL);
+	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
+
+	val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK);
+	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+
+	INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_qp_rk3588_hpd_work);
+
+	plat_data.main_irq = platform_get_irq_byname(pdev, "main");
+	if (plat_data.main_irq < 0)
+		return plat_data.main_irq;
+
+	irq = platform_get_irq_byname(pdev, "hpd");
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_threaded_irq(hdmi->dev, irq,
+					dw_hdmi_qp_rk3588_hardirq,
+					dw_hdmi_qp_rk3588_irq,
+					IRQF_SHARED, "dw-hdmi-qp-hpd",
+					hdmi);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(encoder, &dw_hdmi_qp_rockchip_encoder_helper_funcs);
+	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+
+	platform_set_drvdata(pdev, hdmi);
+
+	hdmi->hdmi = dw_hdmi_qp_bind(pdev, encoder, &plat_data);
+	if (IS_ERR(hdmi->hdmi)) {
+		ret = PTR_ERR(hdmi->hdmi);
+		drm_encoder_cleanup(encoder);
+		return ret;
+	}
+
+	connector = drm_bridge_connector_init(drm, encoder);
+	if (IS_ERR(connector)) {
+		ret = PTR_ERR(connector);
+		drm_err(hdmi, "failed to init bridge connector: %d\n", ret);
+		return ret;
+	}
+
+	return drm_connector_attach_encoder(connector, encoder);
+}
+
+static void dw_hdmi_qp_rockchip_unbind(struct device *dev,
+				       struct device *master,
+				       void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
+
+	cancel_delayed_work_sync(&hdmi->hpd_work);
+
+	drm_encoder_cleanup(&hdmi->encoder.encoder);
+}
+
+static const struct component_ops dw_hdmi_qp_rockchip_ops = {
+	.bind	= dw_hdmi_qp_rockchip_bind,
+	.unbind	= dw_hdmi_qp_rockchip_unbind,
+};
+
+static int dw_hdmi_qp_rockchip_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
+}
+
+static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
+}
+
+static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
+{
+	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
+	u32 val;
+
+	val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
+	      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
+	      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
+	      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
+	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON3, val);
+
+	val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
+			    RK3588_SET_HPD_PATH_MASK);
+	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
+
+	val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
+			    RK3588_HDMI0_GRANT_SEL);
+	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
+
+	dw_hdmi_qp_resume(dev, hdmi->hdmi);
+
+	if (hdmi->encoder.encoder.dev)
+		drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume)
+};
+
+struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
+	.probe  = dw_hdmi_qp_rockchip_probe,
+	.remove_new = dw_hdmi_qp_rockchip_remove,
+	.driver = {
+		.name = "dwhdmiqp-rockchip",
+		.pm = &dw_hdmi_qp_rockchip_pm,
+		.of_match_table = dw_hdmi_qp_rockchip_dt_ids,
+	},
+};
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 44d769d9234d..04ef7a2c3833 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -503,6 +503,8 @@  static int __init rockchip_drm_init(void)
 	ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
 	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
 				CONFIG_ROCKCHIP_DW_HDMI);
+	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver,
+				CONFIG_ROCKCHIP_DW_HDMI_QP);
 	ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver,
 				CONFIG_ROCKCHIP_DW_MIPI_DSI);
 	ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index bbb9e0bf6804..d7f2f0fd02e6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -87,6 +87,7 @@  int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rencoder,
 int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
 extern struct platform_driver cdn_dp_driver;
 extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
+extern struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver;
 extern struct platform_driver dw_mipi_dsi_rockchip_driver;
 extern struct platform_driver inno_hdmi_driver;
 extern struct platform_driver rockchip_dp_driver;