From 351c999ebf62fdf09a9d393436c5db73bb3457e0 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 30 Jun 2020 11:09:59 +0100 Subject: arm64: dts: sm8250: add slimbus with bam dma node Signed-off-by: Srinivas Kandagatla --- arch/arm64/boot/dts/qcom/sm8250.dtsi | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi index a5b62cadb129..4644a4828d14 100644 --- a/arch/arm64/boot/dts/qcom/sm8250.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi @@ -2522,6 +2522,41 @@ }; }; + slimbam: dma@3a84000 { + compatible = "qcom,bam-v1.7.0"; + qcom,controlled-remotely; + reg = <0 0x3a84000 0 0x2a000>; + num-channels = <31>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <1>; + qcom,num-ees = <2>; + iommus = <&apps_smmu 0x1826 0x0>; + }; + + slim: slim@3ac0000 { + compatible = "qcom,slim-ngd-v2.2.0"; + reg = <0 0x3ac0000 0 0x2c000>; + interrupts = ; + + qcom,apps-ch-pipes = <0x780000>; + qcom,ea-pc = <0x270>; + status = "okay"; + dmas = <&slimbam 3>, <&slimbam 4>, + <&slimbam 5>, <&slimbam 6>; + dma-names = "rx", "tx", "tx2", "rx2"; + + iommus = <&apps_smmu 0x1826 0x0>; + #address-cells = <1>; + #size-cells = <0>; + + ngd@1 { + reg = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + }; + gpu: gpu@3d00000 { compatible = "qcom,adreno-650.2", "qcom,adreno"; -- cgit v1.2.3 From db944e2ea157ccba9f6844f111f7f3fb99d48e04 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 15 Jan 2021 06:29:15 +0300 Subject: arm64: dts: qcom: qrb5165-rb5: add slpi remoteproc entry Add remoteproc nodes definin sensor core on qrb5165-rb5. Provide proper firmware image names. For now the slpi device is disabled, it generates tons of 'firmware crashed' messages in log. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index bf8077a1cf9a..f11d07f2d74c 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -907,6 +907,11 @@ no-emmc; }; +&slpi { + /* status = "okay"; */ + firmware-name = "qcom/sm8250/slpi.mbn"; +}; + &sound { compatible = "qcom,qrb5165-rb5-sndcard"; pinctrl-0 = <&tert_mi2s_active>; -- cgit v1.2.3 From 12eca8dfc4eafff7e78b718a90ceb87308ff8503 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 24 Sep 2020 12:11:44 +0300 Subject: arm64: dts: qcom: support both DVT and PVT boards for RB5 There are minor differences between DVT (development) and PVT (production) series of RB5 platform. The major difference is the setup of WSA codecs. These two editions use different codecs and different uniq IDs. Provide a separate dts file for DVT board revision. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d7669a7cee9f..6d1f635d8881 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -149,6 +149,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8150-sony-xperia-kumano-bahamut.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8150-sony-xperia-kumano-griffin.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8250-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8250-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8250-rb5-dvt.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8250-sony-xperia-edo-pdx203.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8250-sony-xperia-edo-pdx206.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8350-hdk.dtb diff --git a/arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts b/arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts new file mode 100644 index 000000000000..47e14bb0f288 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020, Linaro Ltd. + */ + +/dts-v1/; + +#include "qrb5165-rb5.dts" + +&left_spkr { + compatible = "sdw10217201000"; + reg = <0 1>; +}; + +&right_spkr { + compatible = "sdw10217201000"; + reg = <0 2>; +}; -- cgit v1.2.3 From bd736d7b7a91223d5ef7da3c6f25ec1dd986b187 Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Wed, 7 Oct 2020 00:10:12 +0000 Subject: drm/msm/dsi: save PLL registers across first PHY reset Take advantage of previously-added support for persisting PLL registers across DSI PHY disable/enable cycles (see 328e1a6 'drm/msm/dsi: Save/Restore PLL status across PHY reset') to support persisting across the very first DSI PHY enable at boot. The bootloader may have left the PLL registers in a non-default state. For example, for dsi_pll_28nm.c on 8x16/8x39, the byte clock mux's power-on reset configuration is to bypass DIV1, but depending on bandwidth requirements[1] the bootloader may have set the DIV1 path. When the byte clock mux is registered with the generic clock framework at probe time, the framework reads & caches the value of the mux bit field (the initial clock parent). After PHY enable, when clk_set_rate is called on the byte clock, the framework assumes there is no need to reparent, and doesn't re-write the mux bit field. But PHY enable resets PLL registers, so the mux bit field actually silently reverted to the DIV1 bypass path. This causes the byte clock to be off by a factor of e.g. 2 for our tested WXGA panel. The above issue manifests as the display not working and a constant stream of FIFO/LP0 contention errors. [1] The specific requirement for triggering the DIV1 path (and thus this issue) on 28nm is a panel with pixel clock <116.7MHz (one-third the minimum VCO setting). FHD/1080p (~145MHz) is fine, WXGA/1280x800 (~75MHz) is not. Signed-off-by: Benjamin Li --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 7fc0975cb869..6663fc63f789 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -691,6 +691,22 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to register clk provider\n"); + /* + * As explained in msm_dsi_phy_enable, resetting the DSI PHY (as done + * in dsi_mgr_phy_enable) silently changes its PLL registers to power-on + * defaults, but the generic clock framework manages and caches several + * of the PLL registers. It initializes these caches at registration + * time via register read. + * + * As a result, we need to save DSI PLL registers once at probe in order + * for the first call to msm_dsi_phy_enable to successfully bring PLL + * registers back in line with what the generic clock framework expects. + * + * Subsequent PLL restores during msm_dsi_phy_enable will always be + * paired with PLL saves in msm_dsi_phy_disable. + */ + msm_dsi_phy_pll_save_state(phy); + dsi_phy_disable_resource(phy); platform_set_drvdata(pdev, phy); -- cgit v1.2.3 From d5031496895b729edad8718417bfec480538a389 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 14 Mar 2021 04:35:16 +0300 Subject: drm/bridge/lontium-lt9611uxc: add proper support for dual-DSI mode Program DSI registers depending on the ports enabled in the device tree. A, B and A+B setups are supported. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 80 +++++++++++++++++++----------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index fa1ee6264d92..b75b70f30b4e 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -87,6 +87,7 @@ struct lt9611uxc_mode { u16 hdisplay; u16 vdisplay; u8 vrefresh; + bool dual_dsi; }; /* @@ -94,22 +95,24 @@ struct lt9611uxc_mode { * Enumerate them here to check whether the mode is supported. */ static struct lt9611uxc_mode lt9611uxc_modes[] = { - { 1920, 1080, 60 }, - { 1920, 1080, 30 }, - { 1920, 1080, 25 }, - { 1366, 768, 60 }, - { 1360, 768, 60 }, - { 1280, 1024, 60 }, - { 1280, 800, 60 }, - { 1280, 720, 60 }, - { 1280, 720, 50 }, - { 1280, 720, 30 }, - { 1152, 864, 60 }, - { 1024, 768, 60 }, - { 800, 600, 60 }, - { 720, 576, 50 }, - { 720, 480, 60 }, - { 640, 480, 60 }, + { 3840, 2160, 60, true }, + { 3840, 2160, 30, true }, + { 1920, 1080, 60, false }, + { 1920, 1080, 30, false }, + { 1920, 1080, 25, false }, + { 1366, 768, 60, false }, + { 1360, 768, 60, false }, + { 1280, 1024, 60, false }, + { 1280, 800, 60, false }, + { 1280, 720, 60, false }, + { 1280, 720, 50, false }, + { 1280, 720, 30, false }, + { 1152, 864, 60, false }, + { 1024, 768, 60, false }, + { 800, 600, 60, false }, + { 720, 576, 50, false }, + { 720, 480, 60, false }, + { 640, 480, 60, false }, }; static struct lt9611uxc *bridge_to_lt9611uxc(struct drm_bridge *bridge) @@ -314,8 +317,15 @@ static enum drm_mode_status lt9611uxc_connector_mode_valid(struct drm_connector struct drm_display_mode *mode) { struct lt9611uxc_mode *lt9611uxc_mode = lt9611uxc_find_mode(mode); + struct lt9611uxc *lt9611uxc = connector_to_lt9611uxc(connector); + + if (!lt9611uxc_mode) + return MODE_BAD; - return lt9611uxc_mode ? MODE_OK : MODE_BAD; + if (lt9611uxc_mode->dual_dsi && (!lt9611uxc->dsi0 || !lt9611uxc->dsi1)) + return MODE_BAD; + + return MODE_OK; } static const struct drm_connector_helper_funcs lt9611uxc_bridge_connector_helper_funcs = { @@ -376,11 +386,16 @@ lt9611uxc_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode) { - struct lt9611uxc_mode *lt9611uxc_mode; + struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge); + struct lt9611uxc_mode *lt9611uxc_mode = lt9611uxc_find_mode(mode); + + if (!lt9611uxc_mode) + return MODE_BAD; - lt9611uxc_mode = lt9611uxc_find_mode(mode); + if (lt9611uxc_mode->dual_dsi && (!lt9611uxc->dsi0 || !lt9611uxc->dsi1)) + return MODE_BAD; - return lt9611uxc_mode ? MODE_OK : MODE_BAD; + return MODE_OK; } static void lt9611uxc_video_setup(struct lt9611uxc *lt9611uxc, @@ -400,6 +415,13 @@ static void lt9611uxc_video_setup(struct lt9611uxc *lt9611uxc, vsync_len = mode->vsync_end - mode->vsync_start; vfront_porch = mode->vsync_start - mode->vdisplay; + if (lt9611uxc->dsi0 && lt9611uxc->dsi1) + regmap_write(lt9611uxc->regmap, 0xb025, 0x03); + else if (lt9611uxc->dsi0) + regmap_write(lt9611uxc->regmap, 0xb025, 0x01); + else + regmap_write(lt9611uxc->regmap, 0xb025, 0x02); + regmap_write(lt9611uxc->regmap, 0xd00d, (u8)(v_total / 256)); regmap_write(lt9611uxc->regmap, 0xd00e, (u8)(v_total % 256)); @@ -522,13 +544,13 @@ static int lt9611uxc_parse_dt(struct device *dev, struct lt9611uxc *lt9611uxc) { lt9611uxc->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); - if (!lt9611uxc->dsi0_node) { + lt9611uxc->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); + + if (!lt9611uxc->dsi0_node && !lt9611uxc->dsi1_node) { dev_err(lt9611uxc->dev, "failed to get remote node for primary dsi\n"); return -ENODEV; } - lt9611uxc->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); - return 0; } @@ -947,11 +969,13 @@ retry: drm_bridge_add(<9611uxc->bridge); - /* Attach primary DSI */ - lt9611uxc->dsi0 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi0_node); - if (IS_ERR(lt9611uxc->dsi0)) { - ret = PTR_ERR(lt9611uxc->dsi0); - goto err_remove_bridge; + /* Attach primary DSI, if specified */ + if (lt9611uxc->dsi0_node) { + lt9611uxc->dsi0 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi0_node); + if (IS_ERR(lt9611uxc->dsi0)) { + ret = PTR_ERR(lt9611uxc->dsi0); + goto err_remove_bridge; + } } /* Attach secondary DSI, if specified */ -- cgit v1.2.3 From ef59b6290b42ea6ceb4443a4b70cbcb07263ecb4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 14 Mar 2021 04:42:28 +0300 Subject: arm64: dts: qcom: add qrb5165-rb5 DTS with dual DSI enabled Add a variant of the RB5 platform's device tree having both DSI channels connected to the lt9611uxc bridge in the dual DSI mode. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/qrb5165-rb5-dual-dsi.dts | 46 +++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qrb5165-rb5-dual-dsi.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6d1f635d8881..4d23090432e3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -52,6 +52,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-dual-dsi.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5-dual-dsi.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5-dual-dsi.dts new file mode 100644 index 000000000000..1178bb85f7f4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5-dual-dsi.dts @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020, Linaro Ltd. + */ + +/dts-v1/; + +#include "qrb5165-rb5.dts" + +&dsi0 { + qcom,dual-dsi-mode; + qcom,master-dsi; +}; + +&dsi1 { + status = "okay"; + vdda-supply = <&vreg_l9a_1p2>; + + qcom,dual-dsi-mode; + + ports { + port@1 { + endpoint { + remote-endpoint = <<9611_b>; + data-lanes = <0 1 2 3>; + }; + }; + }; +}; + +&dsi1_phy { + status = "okay"; + vdds-supply = <&vreg_l5a_0p88>; +}; + +<9611_codec { + ports { + port@1 { + reg = <1>; + + lt9611_b: endpoint { + remote-endpoint = <&dsi1_out>; + }; + }; + }; +}; -- cgit v1.2.3 From aea34773254483e176c73947b0d78562481a946b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 14 Mar 2021 04:52:34 +0300 Subject: drm/msm/dpu1: improve support for active CTLs - Support setting master interface if several INTFs are to be handled by a single CTL - Support setting handling several MERGE_3D instances using a single CTL. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 15 +++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index a35ecb6676c8..55f6474ea1f3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -519,6 +519,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, u32 intf_active = 0; u32 wb_active = 0; u32 mode_sel = 0; + u32 merge_3d_active = 0; /* CTL_TOP[31:28] carries group_id to collate CTL paths * per VM. Explicitly disable it until VM support is @@ -542,10 +543,17 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, if (cfg->wb) wb_active |= BIT(cfg->wb - WB_0); + merge_3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE); + if (cfg->merge_3d) + merge_3d_active |= BIT(cfg->merge_3d - MERGE_3D_0); + DPU_REG_WRITE(c, CTL_TOP, mode_sel); DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); + if (cfg->intf_master) + DPU_REG_WRITE(c, CTL_INTF_MASTER, BIT(cfg->intf_master - INTF_0)); + if (cfg->merge_3d) DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, BIT(cfg->merge_3d - MERGE_3D_0)); @@ -553,6 +561,13 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX); DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc); } + if (cfg->merge_3d) + DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); + + if (cfg->intf_master) + DPU_DEBUG_DRIVER("ACTIVE: %x %x %lx\n", intf_active, merge_3d_active, BIT(cfg->intf_master - INTF_0)); + else + DPU_DEBUG_DRIVER("ACTIVE: %x %x\n", intf_active, merge_3d_active); } static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 96c012ec8467..e801a6daf927 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -36,6 +36,7 @@ struct dpu_hw_stage_cfg { /** * struct dpu_hw_intf_cfg :Describes how the DPU writes data to output interface * @intf : Interface id + * @intf_master: Master interface id in the dual pipe topology * @mode_3d: 3d mux configuration * @merge_3d: 3d merge block used * @intf_mode_sel: Interface mode, cmd / vid @@ -44,6 +45,7 @@ struct dpu_hw_stage_cfg { */ struct dpu_hw_intf_cfg { enum dpu_intf intf; + enum dpu_intf intf_master; enum dpu_wb wb; enum dpu_3d_blend_mode mode_3d; enum dpu_merge_3d merge_3d; -- cgit v1.2.3 From 65e1b101544cce9d1fd81b04f47bba32769814b2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 14 Mar 2021 04:58:32 +0300 Subject: drm/msm/dpu1: use one active CTL if it is available Unlike previous generation, with newer ("active") CTLs it is possible to use just one CTL to handle both interfaces. And one has to use single CTL to support master/slave DSI config. So use one active CTL if it is available. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 8 ++++++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 14 ++++++++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 1 + 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 9c6817b5a194..e939535ae0d0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1102,14 +1102,18 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, return; } - if (!hw_ctl[i]) { + /* Use first (and only) CTL if active CTLs are supported */ + if (dpu_kms->catalog->caps->has_active_ctls) + phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[0]); + else + phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]); + if (!phys->hw_ctl) { DPU_ERROR_ENC(dpu_enc, "no ctl block assigned at idx: %d\n", i); return; } phys->hw_pp = dpu_enc->hw_pp[i]; - phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]); phys->cached_mode = crtc_state->adjusted_mode; if (phys->ops.atomic_mode_set) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 27f029fdc682..59dee2aede5b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -328,6 +328,7 @@ static const struct dpu_caps sm8150_dpu_caps = { .has_dim_layer = true, .has_idle_pc = true, .has_3d_merge = true, + .has_active_ctls = true, .max_linewidth = 4096, .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, .max_hdeci_exp = MAX_HORZ_DECIMATION, @@ -360,6 +361,7 @@ static const struct dpu_caps sm8250_dpu_caps = { .has_dim_layer = true, .has_idle_pc = true, .has_3d_merge = true, + .has_active_ctls = true, .max_linewidth = 4096, .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 38aa38ab1568..36010f9a5848 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -395,6 +395,7 @@ struct dpu_caps { bool has_dim_layer; bool has_idle_pc; bool has_3d_merge; + bool has_active_ctls; /* SSPP limits */ u32 max_linewidth; u32 pixel_ram_size; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 73b3442e7467..8a3411edacd3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -224,6 +224,7 @@ int dpu_rm_init(struct dpu_rm *rm, } rm->ctl_blks[ctl->id - CTL_0] = &hw->base; } + rm->has_active_ctls = cat->caps->has_active_ctls; for (i = 0; i < cat->dspp_count; i++) { struct dpu_hw_dspp *hw; @@ -443,10 +444,15 @@ static int _dpu_rm_reserve_ctls( int i = 0, j, num_ctls; bool needs_split_display; - /* each hw_intf needs its own hw_ctrl to program its control path */ - num_ctls = top->num_intf; + if (rm->has_active_ctls) { + num_ctls = 1; + needs_split_display = false; + } else { + /* each hw_intf needs its own hw_ctrl to program its control path */ + num_ctls = top->num_intf; - needs_split_display = _dpu_rm_needs_split_display(top); + needs_split_display = _dpu_rm_needs_split_display(top); + } for (j = 0; j < ARRAY_SIZE(rm->ctl_blks); j++) { const struct dpu_hw_ctl *ctl; @@ -464,7 +470,7 @@ static int _dpu_rm_reserve_ctls( DPU_DEBUG("ctl %d caps 0x%lX\n", j + CTL_0, features); - if (needs_split_display != has_split_display) + if (!rm->has_active_ctls && needs_split_display != has_split_display) continue; ctl_idx[i] = j; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 59de72b381f9..2b9f7557dd70 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -31,6 +31,7 @@ struct dpu_rm { struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0]; struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0]; + bool has_active_ctls; }; /** -- cgit v1.2.3 From 2a0785cf1207a927891ceb879778fa82f1f2a185 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 14 Mar 2021 05:03:35 +0300 Subject: drm/msm/dpu1: dpu_encoder_phys_*: proper suppor for active CTLs Adapt dpu_encoder_phys_* to properly support active CTLs and their features. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 2 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index ae28b2b93e69..ed89011e36a7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -58,6 +58,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( return; intf_cfg.intf = phys_enc->intf_idx; + if (phys_enc->split_role == ENC_ROLE_MASTER) + intf_cfg.intf_master = phys_enc->hw_intf->idx; intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD; intf_cfg.stream_sel = cmd_enc->stream_sel; intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 2c14646661b7..2c1dbfce20b5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -270,6 +270,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine( DPU_DEBUG_VIDENC(phys_enc, "fmt_fourcc 0x%X\n", fmt_fourcc); intf_cfg.intf = phys_enc->hw_intf->idx; + if (phys_enc->split_role == ENC_ROLE_MASTER) + intf_cfg.intf_master = phys_enc->hw_intf->idx; intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID; intf_cfg.stream_sel = 0; /* Don't care value for video mode */ intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); @@ -347,7 +349,8 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg, int irq_idx) static bool dpu_encoder_phys_vid_needs_single_flush( struct dpu_encoder_phys *phys_enc) { - return phys_enc->split_role != ENC_ROLE_SOLO; + return !(phys_enc->hw_ctl->caps->features & BIT(DPU_CTL_ACTIVE_CFG)) && + phys_enc->split_role != ENC_ROLE_SOLO; } static void dpu_encoder_phys_vid_atomic_mode_set( -- cgit v1.2.3 From d48e81e7ae9a16ecbe7462d504a5de7b7e5e81d3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 27 Sep 2021 17:15:26 +0300 Subject: Revert "of: property: fw_devlink: Add support for remote-endpoint" This reverts commit f7514a6630166a7b566dee9b1af2e87e431959be. Signed-off-by: Dmitry Baryshkov --- drivers/of/property.c | 60 ++++++++++++++------------------------------------- 1 file changed, 16 insertions(+), 44 deletions(-) diff --git a/drivers/of/property.c b/drivers/of/property.c index 967f79b59016..969ff859bffa 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1074,36 +1074,6 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor, return false; } -static struct device_node *of_get_compat_node(struct device_node *np) -{ - of_node_get(np); - - while (np) { - if (!of_device_is_available(np)) { - of_node_put(np); - np = NULL; - } - - if (of_find_property(np, "compatible", NULL)) - break; - - np = of_get_next_parent(np); - } - - return np; -} - -static struct device_node *of_get_compat_node_parent(struct device_node *np) -{ - struct device_node *parent, *node; - - parent = of_get_parent(np); - node = of_get_compat_node(parent); - of_node_put(parent); - - return node; -} - /** * of_link_to_phandle - Add fwnode link to supplier from supplier phandle * @con_np: consumer device tree node @@ -1127,11 +1097,25 @@ static int of_link_to_phandle(struct device_node *con_np, struct device *sup_dev; struct device_node *tmp_np = sup_np; + of_node_get(sup_np); /* * Find the device node that contains the supplier phandle. It may be * @sup_np or it may be an ancestor of @sup_np. */ - sup_np = of_get_compat_node(sup_np); + while (sup_np) { + + /* Don't allow linking to a disabled supplier */ + if (!of_device_is_available(sup_np)) { + of_node_put(sup_np); + sup_np = NULL; + } + + if (of_find_property(sup_np, "compatible", NULL)) + break; + + sup_np = of_get_next_parent(sup_np); + } + if (!sup_np) { pr_debug("Not linking %pOFP to %pOFP - No device\n", con_np, tmp_np); @@ -1277,10 +1261,6 @@ static struct device_node *parse_##fname(struct device_node *np, \ * @parse_prop.prop_name: Name of property holding a phandle value * @parse_prop.index: For properties holding a list of phandles, this is the * index into the list - * @optional: Describes whether a supplier is mandatory or not - * @node_not_dev: The consumer node containing the property is never converted - * to a struct device. Instead, parse ancestor nodes for the - * compatible property to find a node corresponding to a device. * * Returns: * parse_prop() return values are @@ -1292,7 +1272,6 @@ struct supplier_bindings { struct device_node *(*parse_prop)(struct device_node *np, const char *prop_name, int index); bool optional; - bool node_not_dev; }; DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells") @@ -1405,7 +1384,6 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_pinctrl6, }, { .parse_prop = parse_pinctrl7, }, { .parse_prop = parse_pinctrl8, }, - { .parse_prop = parse_remote_endpoint, .node_not_dev = true, }, { .parse_prop = parse_pwms, }, { .parse_prop = parse_resets, }, { .parse_prop = parse_leds, }, @@ -1452,16 +1430,10 @@ static int of_link_property(struct device_node *con_np, const char *prop_name) } while ((phandle = s->parse_prop(con_np, prop_name, i))) { - struct device_node *con_dev_np; - - con_dev_np = s->node_not_dev - ? of_get_compat_node_parent(con_np) - : of_node_get(con_np); matched = true; i++; - of_link_to_phandle(con_dev_np, phandle); + of_link_to_phandle(con_np, phandle); of_node_put(phandle); - of_node_put(con_dev_np); } s++; } -- cgit v1.2.3 From 5c00ba1aa359b744b5a2163b9870498a265b2073 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 25 Nov 2021 21:27:07 +0300 Subject: of: property: do not create clocks device link for clock controllers Do not create device link for clock controllers. Some of the clocks provided to the device via OF can be the clocks that are just parents to the clocks provided by this clock controller. Clock subsystem already has support for handling missing clock parents correctly (clock orphans). Later when the parent clock is registered, clocks get populated properly. An example of the system where this matters is the SDM8450 MTP board (see arch/arm64/boot/dts/qcom/sdm845-mtp.dts). Here the dispcc uses clocks provided by dsi0_phy and dsi1_phy device tree nodes. However the dispcc itself provides clocks to both PHYs, to the PHY parent device, etc. With just dsi0_phy in place devlink is able to break the dependency, but with two PHYs, dispcc doesn't get probed at all, thus breaking display support. Cc: Bjorn Andersson Cc: Stephen Boyd Cc: Saravana Kannan Signed-off-by: Dmitry Baryshkov --- drivers/of/property.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/of/property.c b/drivers/of/property.c index 969ff859bffa..5f1606a95676 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1274,7 +1274,6 @@ struct supplier_bindings { bool optional; }; -DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells") DEFINE_SIMPLE_PROP(interconnects, "interconnects", "#interconnect-cells") DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells") DEFINE_SIMPLE_PROP(mboxes, "mboxes", "#mbox-cells") @@ -1304,6 +1303,21 @@ DEFINE_SIMPLE_PROP(backlight, "backlight", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") +static struct device_node *parse_clocks(struct device_node *np, + const char *prop_name, int index) +{ + /* + * Do not create clock-related device links for clocks controllers, + * clock orphans will handle missing clock parents automatically. + */ + if (!strcmp(prop_name, "clocks") && + of_find_property(np, "#clock-cells", NULL)) + return NULL; + + return parse_prop_cells(np, prop_name, index, "clocks", + "#clock-cells"); +} + static struct device_node *parse_gpios(struct device_node *np, const char *prop_name, int index) { -- cgit v1.2.3