aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/msm/dp-controller.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml219
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml214
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml36
-rw-r--r--drivers/gpu/drm/msm/Kconfig9
-rw-r--r--drivers/gpu/drm/msm/Makefile3
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c20
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c1
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c41
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c23
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c22
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c100
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h28
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h19
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c39
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c36
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c610
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h21
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h11
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c68
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c28
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c107
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h19
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c2
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c19
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c8
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c9
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h5
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c4
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c21
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.c12
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_clk_util.c (renamed from drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c)69
-rw-r--r--drivers/gpu/drm/msm/dp/dp_clk_util.h (renamed from drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h)8
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c102
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.h8
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c28
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c196
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.c21
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.c5
-rw-r--r--drivers/gpu/drm/msm/dp/dp_parser.c38
-rw-r--r--drivers/gpu/drm/msm/dp/dp_parser.h4
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.c23
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.h3
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c8
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c65
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c14
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h4
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c122
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c26
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c7
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c11
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c7
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c2
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c15
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.c6
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c160
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h46
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c41
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h3
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c14
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h8
-rw-r--r--drivers/gpu/drm/msm/msm_io_utils.c126
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c8
82 files changed, 2045 insertions, 990 deletions
diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index 5457612ab136..cd05cfd76536 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -21,6 +21,7 @@ properties:
- qcom,sc7280-edp
- qcom,sc8180x-dp
- qcom,sc8180x-edp
+ - qcom,sm8350-dp
reg:
items:
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml b/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml
new file mode 100644
index 000000000000..167bc48748d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml
@@ -0,0 +1,219 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/dpu-msm8998.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for MSM8998 target
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
+
+description: |
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
+ bindings of MDSS and DPU are mentioned for MSM8998 target.
+
+properties:
+ compatible:
+ items:
+ - const: qcom,msm8998-mdss
+
+ reg:
+ maxItems: 1
+
+ reg-names:
+ const: mdss
+
+ power-domains:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Display AHB clock
+ - description: Display AXI clock
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: core
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#address-cells": true
+
+ "#size-cells": true
+
+ "#interrupt-cells":
+ const: 1
+
+ iommus:
+ items:
+ - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
+
+ ranges: true
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ description: Node containing the properties of DPU.
+
+ properties:
+ compatible:
+ items:
+ - const: qcom,msm8998-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for regdma register set
+ - description: Address offset and size for vbif register set
+ - description: Address offset and size for non-realtime vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: regdma
+ - const: vbif
+ - const: vbif_nrt
+
+ clocks:
+ items:
+ - description: Display ahb clock
+ - description: Display axi clock
+ - description: Display mem-noc clock
+ - description: Display core clock
+ - description: Display vsync clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: mnoc
+ - const: core
+ - const: vsync
+
+ interrupts:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ operating-points-v2: true
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description: |
+ Contains the list of output ports from DPU device. These ports
+ connect to interfaces that are external to the DPU hardware,
+ such as DSI, DP etc. Each output port contains an endpoint that
+ describes how it is connected to an external interface.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: DPU_INTF1 (DSI1)
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: DPU_INTF2 (DSI2)
+
+ required:
+ - port@0
+ - port@1
+
+ required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - interrupts
+ - power-domains
+ - operating-points-v2
+ - ports
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - power-domains
+ - clocks
+ - interrupts
+ - interrupt-controller
+ - iommus
+ - ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,mmcc-msm8998.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-subsystem@c900000 {
+ compatible = "qcom,msm8998-mdss";
+ reg = <0x0c900000 0x1000>;
+ reg-names = "mdss";
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MDSS_MDP_CLK>;
+ clock-names = "iface", "bus", "core";
+
+ #address-cells = <1>;
+ #interrupt-cells = <1>;
+ #size-cells = <1>;
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ iommus = <&mmss_smmu 0>;
+
+ power-domains = <&mmcc MDSS_GDSC>;
+ ranges;
+
+ display-controller@c901000 {
+ compatible = "qcom,msm8998-dpu";
+ reg = <0x0c901000 0x8f000>,
+ <0x0c9a8e00 0xf0>,
+ <0x0c9b0000 0x2008>,
+ <0x0c9b8000 0x1040>;
+ reg-names = "mdp", "regdma", "vbif", "vbif_nrt";
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MNOC_AHB_CLK>,
+ <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_VSYNC_CLK>;
+ clock-names = "iface", "bus", "mnoc", "core", "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd MSM8998_VDDMX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dpu_intf2_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
new file mode 100644
index 000000000000..8766b13f0c46
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
@@ -0,0 +1,214 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/dpu-qcm2290.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for QCM2290 target
+
+maintainers:
+ - Loic Poulain <loic.poulain@linaro.org>
+
+description: |
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS
+ and DPU are mentioned for QCM2290 target.
+
+properties:
+ compatible:
+ items:
+ - const: qcom,qcm2290-mdss
+
+ reg:
+ maxItems: 1
+
+ reg-names:
+ const: mdss
+
+ power-domains:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Display AHB clock from gcc
+ - description: Display AXI clock
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: core
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#address-cells": true
+
+ "#size-cells": true
+
+ "#interrupt-cells":
+ const: 1
+
+ iommus:
+ items:
+ - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
+ - description: Phandle to apps_smmu node with SID mask for Hard-Fail port1
+
+ ranges: true
+
+ interconnects:
+ items:
+ - description: Interconnect path specifying the port ids for data bus
+
+ interconnect-names:
+ const: mdp0-mem
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ description: Node containing the properties of DPU.
+
+ properties:
+ compatible:
+ items:
+ - const: qcom,qcm2290-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: vbif
+
+ clocks:
+ items:
+ - description: Display AXI clock from gcc
+ - description: Display AHB clock from dispcc
+ - description: Display core clock from dispcc
+ - description: Display lut clock from dispcc
+ - description: Display vsync clock from dispcc
+
+ clock-names:
+ items:
+ - const: bus
+ - const: iface
+ - const: core
+ - const: lut
+ - const: vsync
+
+ interrupts:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ operating-points-v2: true
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description: |
+ Contains the list of output ports from DPU device. These ports
+ connect to interfaces that are external to the DPU hardware,
+ such as DSI. Each output port contains an endpoint that
+ describes how it is connected to an external interface.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: DPU_INTF1 (DSI1)
+
+ required:
+ - port@0
+
+ required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - interrupts
+ - power-domains
+ - operating-points-v2
+ - ports
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - power-domains
+ - clocks
+ - interrupts
+ - interrupt-controller
+ - iommus
+ - ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-qcm2290.h>
+ #include <dt-bindings/clock/qcom,gcc-qcm2290.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interconnect/qcom,qcm2290.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ mdss: mdss@5e00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qcm2290-mdss", "qcom,mdss";
+ reg = <0x05e00000 0x1000>;
+ reg-names = "mdss";
+ power-domains = <&dispcc MDSS_GDSC>;
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface", "bus", "core";
+
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interconnects = <&mmrt_virt MASTER_MDP0 &bimc SLAVE_EBI1>;
+ interconnect-names = "mdp0-mem";
+
+ iommus = <&apps_smmu 0x420 0x2>,
+ <&apps_smmu 0x421 0x0>;
+ ranges;
+
+ mdss_mdp: mdp@5e01000 {
+ compatible = "qcom,qcm2290-dpu";
+ reg = <0x05e01000 0x8f000>,
+ <0x05eb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus", "iface", "core", "lut", "vsync";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0 IRQ_TYPE_NONE>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index 35426fde8610..7095ec3c890d 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -14,8 +14,9 @@ allOf:
properties:
compatible:
- items:
- - const: qcom,mdss-dsi-ctrl
+ enum:
+ - qcom,mdss-dsi-ctrl
+ - qcom,dsi-ctrl-6g-qcm2290
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
index 4399715953e1..2d5a766d028f 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
@@ -35,6 +35,38 @@ properties:
Connected to DSI0_MIPI_DSI_PLL_VDDA0P9 pin for sc7180 target and
connected to VDDA_MIPI_DSI_0_PLL_0P9 pin for sdm845 target
+ qcom,phy-rescode-offset-top:
+ $ref: /schemas/types.yaml#/definitions/int8-array
+ minItems: 5
+ maxItems: 5
+ description:
+ Integer array of offset for pull-up legs rescode for all five lanes.
+ To offset the drive strength from the calibrated value in an increasing
+ manner, -32 is the weakest and +31 is the strongest.
+ items:
+ minimum: -32
+ maximum: 31
+
+ qcom,phy-rescode-offset-bot:
+ $ref: /schemas/types.yaml#/definitions/int8-array
+ minItems: 5
+ maxItems: 5
+ description:
+ Integer array of offset for pull-down legs rescode for all five lanes.
+ To offset the drive strength from the calibrated value in a decreasing
+ manner, -32 is the weakest and +31 is the strongest.
+ items:
+ minimum: -32
+ maximum: 31
+
+ qcom,phy-drive-ldo-level:
+ $ref: "/schemas/types.yaml#/definitions/uint32"
+ description:
+ The PHY LDO has an amplitude tuning feature to adjust the LDO output
+ for the HSTX drive. Use supported levels (mV) to offset the drive level
+ from the default value.
+ enum: [ 375, 400, 425, 450, 475, 500 ]
+
required:
- compatible
- reg
@@ -64,5 +96,9 @@ examples:
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&rpmhcc RPMH_CXO_CLK>;
clock-names = "iface", "ref";
+
+ qcom,phy-rescode-offset-top = /bits/ 8 <0 0 0 0 0>;
+ qcom,phy-rescode-offset-bot = /bits/ 8 <0 0 0 0 0>;
+ qcom,phy-drive-ldo-level = <400>;
};
...
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 4fd931413705..c79502525963 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -34,15 +34,6 @@ config DRM_MSM_GPU_STATE
depends on DRM_MSM && (DEBUG_FS || DEV_COREDUMP)
default y
-config DRM_MSM_REGISTER_LOGGING
- bool "MSM DRM register logging"
- depends on DRM_MSM
- default n
- help
- Compile in support for logging register reads/writes in a format
- that can be parsed by envytools demsm tool. If enabled, register
- logging can be switched on via msm.reglog=y module param.
-
config DRM_MSM_GPU_SUDO
bool "Enable SUDO flag on submits"
depends on DRM_MSM && EXPERT
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 03ab55c37beb..e9cc7d8ac301 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -66,7 +66,6 @@ msm-y := \
disp/dpu1/dpu_hw_top.o \
disp/dpu1/dpu_hw_util.o \
disp/dpu1/dpu_hw_vbif.o \
- disp/dpu1/dpu_io_util.o \
disp/dpu1/dpu_kms.o \
disp/dpu1/dpu_mdss.o \
disp/dpu1/dpu_plane.o \
@@ -87,6 +86,7 @@ msm-y := \
msm_gem_vma.o \
msm_gpu.o \
msm_gpu_devfreq.o \
+ msm_io_utils.o \
msm_iommu.o \
msm_perf.o \
msm_rd.o \
@@ -102,6 +102,7 @@ msm-$(CONFIG_DRM_MSM_GPU_STATE) += adreno/a6xx_gpu_state.o
msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
dp/dp_catalog.o \
+ dp/dp_clk_util.o \
dp/dp_ctrl.o \
dp/dp_display.o \
dp/dp_drm.o \
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 17cfad6424db..7d23c741db4a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -10,7 +10,6 @@
#include <linux/bitfield.h>
#include <linux/devfreq.h>
-#include <linux/nvmem-consumer.h>
#include <linux/soc/qcom/llcc-qcom.h>
#define GPU_PAS_ID 13
@@ -1506,7 +1505,7 @@ static void a6xx_llc_slices_init(struct platform_device *pdev,
if (a6xx_gpu->have_mmu500)
a6xx_gpu->llc_mmio = NULL;
else
- a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem", "gpu_cx");
+ a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem");
a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU);
a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW);
@@ -1736,6 +1735,18 @@ static u32 a618_get_speed_bin(u32 fuse)
return UINT_MAX;
}
+static u32 adreno_7c3_get_speed_bin(u32 fuse)
+{
+ if (fuse == 0)
+ return 0;
+ else if (fuse == 117)
+ return 0;
+ else if (fuse == 190)
+ return 1;
+
+ return UINT_MAX;
+}
+
static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse)
{
u32 val = UINT_MAX;
@@ -1743,6 +1754,9 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse)
if (adreno_cmp_rev(ADRENO_REV(6, 1, 8, ANY_ID), rev))
val = a618_get_speed_bin(fuse);
+ if (adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), rev))
+ val = adreno_7c3_get_speed_bin(fuse);
+
if (val == UINT_MAX) {
DRM_DEV_ERROR(dev,
"missing support for speed-bin: %u. Some OPPs may not be supported by hardware",
@@ -1759,7 +1773,7 @@ static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev)
u32 speedbin;
int ret;
- ret = nvmem_cell_read_variable_le_u32(dev, "speed_bin", &speedbin);
+ ret = adreno_read_speedbin(dev, &speedbin);
/*
* -ENOENT means that the platform doesn't support speedbin which is
* fine
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index fb261930ad1c..89cfd84760d7 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -318,7 +318,6 @@ static const struct adreno_info gpulist[] = {
.hwcg = a660_hwcg,
}, {
.rev = ADRENO_REV(6, 3, 5, ANY_ID),
- .name = "Adreno 7c Gen 3",
.fw = {
[ADRENO_FW_SQE] = "a660_sqe.fw",
[ADRENO_FW_GMU] = "a660_gmu.bin",
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index f33cfa4ef1c8..15c8997b7251 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -14,6 +14,7 @@
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/soc/qcom/mdt_loader.h>
+#include <linux/nvmem-consumer.h>
#include <soc/qcom/ocmem.h>
#include "adreno_gpu.h"
#include "a6xx_gpu.h"
@@ -227,7 +228,8 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu,
return aspace;
}
-int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
+int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
+ uint32_t param, uint64_t *value)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -242,10 +244,12 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
*value = !adreno_is_a650_family(adreno_gpu) ? 0x100000 : 0;
return 0;
case MSM_PARAM_CHIP_ID:
- *value = adreno_gpu->rev.patchid |
- (adreno_gpu->rev.minor << 8) |
- (adreno_gpu->rev.major << 16) |
- (adreno_gpu->rev.core << 24);
+ *value = (uint64_t) adreno_gpu->rev.patchid |
+ (uint64_t) (adreno_gpu->rev.minor << 8) |
+ (uint64_t) (adreno_gpu->rev.major << 16) |
+ (uint64_t) (adreno_gpu->rev.core << 24);
+ if (!adreno_gpu->info->revn)
+ *value |= ((uint64_t) adreno_gpu->speedbin) << 32;
return 0;
case MSM_PARAM_MAX_FREQ:
*value = adreno_gpu->base.fast_rate;
@@ -268,7 +272,7 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
*value = 0;
return 0;
case MSM_PARAM_FAULTS:
- *value = gpu->global_faults;
+ *value = gpu->global_faults + ctx->aspace->faults;
return 0;
case MSM_PARAM_SUSPENDS:
*value = gpu->suspend_count;
@@ -921,6 +925,11 @@ void adreno_gpu_ocmem_cleanup(struct adreno_ocmem *adreno_ocmem)
adreno_ocmem->hdl);
}
+int adreno_read_speedbin(struct device *dev, u32 *speedbin)
+{
+ return nvmem_cell_read_variable_le_u32(dev, "speed_bin", speedbin);
+}
+
int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct adreno_gpu *adreno_gpu,
const struct adreno_gpu_funcs *funcs, int nr_rings)
@@ -929,12 +938,28 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct adreno_platform_config *config = dev->platform_data;
struct msm_gpu_config adreno_gpu_config = { 0 };
struct msm_gpu *gpu = &adreno_gpu->base;
+ struct adreno_rev *rev = &config->rev;
+ const char *gpu_name;
+ u32 speedbin;
adreno_gpu->funcs = funcs;
adreno_gpu->info = adreno_info(config->rev);
adreno_gpu->gmem = adreno_gpu->info->gmem;
adreno_gpu->revn = adreno_gpu->info->revn;
- adreno_gpu->rev = config->rev;
+ adreno_gpu->rev = *rev;
+
+ if (adreno_read_speedbin(dev, &speedbin) || !speedbin)
+ speedbin = 0xffff;
+ adreno_gpu->speedbin = (uint16_t) (0xffff & speedbin);
+
+ gpu_name = adreno_gpu->info->name;
+ if (!gpu_name) {
+ gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%d.%d.%d.%d",
+ rev->core, rev->major, rev->minor,
+ rev->patchid);
+ if (!gpu_name)
+ return -ENOMEM;
+ }
adreno_gpu_config.ioname = "kgsl_3d0_reg_memory";
@@ -948,7 +973,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
pm_runtime_enable(dev);
return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
- adreno_gpu->info->name, &adreno_gpu_config);
+ gpu_name, &adreno_gpu_config);
}
void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index cffabe7d33c1..b1ee453d627d 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -80,6 +80,7 @@ struct adreno_gpu {
const struct adreno_info *info;
uint32_t gmem; /* actual gmem size */
uint32_t revn; /* numeric revision name */
+ uint16_t speedbin;
const struct adreno_gpu_funcs *funcs;
/* interesting register offsets to dump: */
@@ -279,7 +280,8 @@ static inline int adreno_is_a650_family(struct adreno_gpu *gpu)
adreno_is_a660_family(gpu);
}
-int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
+int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
+ uint32_t param, uint64_t *value);
const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu,
const char *fwname);
struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu,
@@ -324,6 +326,8 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu,
void adreno_set_llc_attributes(struct iommu_domain *iommu);
+int adreno_read_speedbin(struct device *dev, u32 *speedbin);
+
/*
* For a5xx and a6xx targets load the zap shader that is used to pull the GPU
* out of secure mode
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index 60fe06018581..a7492dd6ed65 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -284,17 +284,6 @@ void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc)
}
}
-static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate)
-{
- struct dss_clk *core_clk = kms->perf.core_clk;
-
- if (core_clk->max_rate && (rate > core_clk->max_rate))
- rate = core_clk->max_rate;
-
- core_clk->rate = rate;
- return dev_pm_opp_set_rate(&kms->pdev->dev, core_clk->rate);
-}
-
static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms)
{
u64 clk_rate = kms->perf.perf_tune.min_core_clk;
@@ -306,7 +295,7 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms)
dpu_cstate = to_dpu_crtc_state(crtc->state);
clk_rate = max(dpu_cstate->new_perf.core_clk_rate,
clk_rate);
- clk_rate = clk_round_rate(kms->perf.core_clk->clk,
+ clk_rate = clk_round_rate(kms->perf.core_clk,
clk_rate);
}
}
@@ -405,10 +394,10 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
trace_dpu_core_perf_update_clk(kms->dev, stop_req, clk_rate);
- ret = _dpu_core_perf_set_core_clk_rate(kms, clk_rate);
+ clk_rate = min(clk_rate, kms->perf.max_core_clk_rate);
+ ret = dev_pm_opp_set_rate(&kms->pdev->dev, clk_rate);
if (ret) {
- DPU_ERROR("failed to set %s clock rate %llu\n",
- kms->perf.core_clk->clk_name, clk_rate);
+ DPU_ERROR("failed to set core clock rate %llu\n", clk_rate);
return ret;
}
@@ -529,13 +518,13 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf)
int dpu_core_perf_init(struct dpu_core_perf *perf,
struct drm_device *dev,
struct dpu_mdss_cfg *catalog,
- struct dss_clk *core_clk)
+ struct clk *core_clk)
{
perf->dev = dev;
perf->catalog = catalog;
perf->core_clk = core_clk;
- perf->max_core_clk_rate = core_clk->max_rate;
+ perf->max_core_clk_rate = clk_get_rate(core_clk);
if (!perf->max_core_clk_rate) {
DPU_DEBUG("optional max core clk rate, use default\n");
perf->max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index cf4b9b5964c6..8dfcc6db7176 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -56,7 +56,7 @@ struct dpu_core_perf_tune {
* @dev: Pointer to drm device
* @debugfs_root: top level debug folder
* @catalog: Pointer to catalog configuration
- * @core_clk: Pointer to core clock structure
+ * @core_clk: Pointer to the core clock
* @core_clk_rate: current core clock rate
* @max_core_clk_rate: maximum allowable core clock rate
* @perf_tune: debug control for performance tuning
@@ -69,7 +69,7 @@ struct dpu_core_perf {
struct drm_device *dev;
struct dentry *debugfs_root;
struct dpu_mdss_cfg *catalog;
- struct dss_clk *core_clk;
+ struct clk *core_clk;
u64 core_clk_rate;
u64 max_core_clk_rate;
struct dpu_core_perf_tune perf_tune;
@@ -120,7 +120,7 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf);
int dpu_core_perf_init(struct dpu_core_perf *perf,
struct drm_device *dev,
struct dpu_mdss_cfg *catalog,
- struct dss_clk *core_clk);
+ struct clk *core_clk);
struct dpu_kms;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index e7c9fe1a250f..7763558ef566 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -408,7 +408,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
if (ctl->ops.set_active_pipes)
ctl->ops.set_active_pipes(ctl, fetch_active);
- _dpu_crtc_program_lm_output_roi(crtc);
+ _dpu_crtc_program_lm_output_roi(crtc);
}
/**
@@ -1046,6 +1046,20 @@ struct plane_state {
u32 pipe_id;
};
+static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
+{
+ struct drm_crtc *crtc = cstate->crtc;
+ struct drm_encoder *encoder;
+
+ drm_for_each_encoder_mask (encoder, crtc->dev, cstate->encoder_mask) {
+ if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -1066,6 +1080,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
const struct drm_plane_state *pipe_staged[SSPP_MAX];
int left_zpos_cnt = 0, right_zpos_cnt = 0;
struct drm_rect crtc_rect = { 0 };
+ bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL);
@@ -1097,6 +1112,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
/* get plane state for all drm planes associated with crtc state */
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
+ struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate);
struct drm_rect dst, clip = crtc_rect;
if (IS_ERR_OR_NULL(pstate)) {
@@ -1108,11 +1124,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
if (cnt >= DPU_STAGE_MAX * 4)
continue;
- pstates[cnt].dpu_pstate = to_dpu_plane_state(pstate);
+ pstates[cnt].dpu_pstate = dpu_pstate;
pstates[cnt].drm_pstate = pstate;
pstates[cnt].stage = pstate->normalized_zpos;
pstates[cnt].pipe_id = dpu_plane_pipe(plane);
+ dpu_pstate->needs_dirtyfb = needs_dirtyfb;
+
if (pipe_staged[pstates[cnt].pipe_id]) {
multirect_plane[multirect_count].r0 =
pipe_staged[pstates[cnt].pipe_id];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1e648db439f9..3940b9c6323b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -127,7 +127,6 @@ enum dpu_enc_rc_states {
* Virtual encoder registers itself with the DRM Framework as the encoder.
* @base: drm_encoder base class for registration with DRM
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
- * @bus_scaling_client: Client handle to the bus scaling interface
* @enabled: True if the encoder is active, protected by enc_lock
* @num_phys_encs: Actual number of physical encoders contained.
* @phys_encs: Container of physical encoders managed.
@@ -144,6 +143,7 @@ enum dpu_enc_rc_states {
* link between encoder/crtc. However in this case we need
* to track crtc in the disable() hook which is called
* _after_ encoder_mask is cleared.
+ * @connector: If a mode is set, cached pointer to the active connector
* @crtc_kickoff_cb: Callback into CRTC that will flush & start
* all CTL paths
* @crtc_kickoff_cb_data: Opaque user data given to crtc_kickoff_cb
@@ -168,12 +168,10 @@ enum dpu_enc_rc_states {
* @vsync_event_work: worker to handle vsync event for autorefresh
* @topology: topology of the display
* @idle_timeout: idle timeout duration in milliseconds
- * @dp: msm_dp pointer, for DP encoders
*/
struct dpu_encoder_virt {
struct drm_encoder base;
spinlock_t enc_spinlock;
- uint32_t bus_scaling_client;
bool enabled;
@@ -186,6 +184,7 @@ struct dpu_encoder_virt {
bool intfs_swapped;
struct drm_crtc *crtc;
+ struct drm_connector *connector;
struct dentry *debugfs_root;
struct mutex enc_lock;
@@ -207,8 +206,6 @@ struct dpu_encoder_virt {
struct msm_display_topology topology;
u32 idle_timeout;
-
- struct msm_dp *dp;
};
#define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base)
@@ -420,26 +417,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc)
return linecount;
}
-void dpu_encoder_get_hw_resources(struct drm_encoder *drm_enc,
- struct dpu_encoder_hw_resources *hw_res)
-{
- struct dpu_encoder_virt *dpu_enc = NULL;
- int i = 0;
-
- dpu_enc = to_dpu_encoder_virt(drm_enc);
- DPU_DEBUG_ENC(dpu_enc, "\n");
-
- /* Query resources used by phys encs, expected to be without overlap */
- memset(hw_res, 0, sizeof(*hw_res));
-
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
-
- if (phys->ops.get_hw_resources)
- phys->ops.get_hw_resources(phys, hw_res);
- }
-}
-
static void dpu_encoder_destroy(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = NULL;
@@ -607,10 +584,6 @@ static int dpu_encoder_virt_atomic_check(
if (phys->ops.atomic_check)
ret = phys->ops.atomic_check(phys, crtc_state,
conn_state);
- else if (phys->ops.mode_fixup)
- if (!phys->ops.mode_fixup(phys, mode, adj_mode))
- ret = -EINVAL;
-
if (ret) {
DPU_ERROR_ENC(dpu_enc,
"mode unsupported, phys idx %d\n", i);
@@ -956,16 +929,13 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc,
return 0;
}
-static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
+static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct dpu_encoder_virt *dpu_enc;
struct msm_drm_private *priv;
struct dpu_kms *dpu_kms;
- struct list_head *connector_list;
- struct drm_connector *conn = NULL, *conn_iter;
- struct drm_crtc *drm_crtc;
struct dpu_crtc_state *cstate;
struct dpu_global_state *global_state;
struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
@@ -973,7 +943,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
int num_lm, num_ctl, num_pp;
- int i, j;
+ int i;
if (!drm_enc) {
DPU_ERROR("invalid encoder\n");
@@ -985,7 +955,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
priv = drm_enc->dev->dev_private;
dpu_kms = to_dpu_kms(priv->kms);
- connector_list = &dpu_kms->dev->mode_config.connector_list;
global_state = dpu_kms_get_existing_global_state(dpu_kms);
if (IS_ERR_OR_NULL(global_state)) {
@@ -995,22 +964,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
trace_dpu_enc_mode_set(DRMID(drm_enc));
- list_for_each_entry(conn_iter, connector_list, head)
- if (conn_iter->encoder == drm_enc)
- conn = conn_iter;
-
- if (!conn) {
- DPU_ERROR_ENC(dpu_enc, "failed to find attached connector\n");
- return;
- } else if (!conn->state) {
- DPU_ERROR_ENC(dpu_enc, "invalid connector state\n");
- return;
- }
-
- drm_for_each_crtc(drm_crtc, drm_enc->dev)
- if (drm_crtc->state->encoder_mask & drm_encoder_mask(drm_enc))
- break;
-
/* Query resource that have been reserved in atomic check step. */
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
@@ -1027,7 +980,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
: NULL;
- cstate = to_dpu_crtc_state(drm_crtc->state);
+ cstate = to_dpu_crtc_state(crtc_state);
for (i = 0; i < num_lm; i++) {
int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
@@ -1039,9 +992,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
cstate->num_mixers = num_lm;
+ dpu_enc->connector = conn_state->connector;
+
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- int num_blk;
- struct dpu_hw_blk *hw_blk[MAX_CHANNELS_PER_ENC];
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
if (!dpu_enc->hw_pp[i]) {
@@ -1059,16 +1012,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
phys->hw_pp = dpu_enc->hw_pp[i];
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
- num_blk = dpu_rm_get_assigned_resources(&dpu_kms->rm,
- global_state, drm_enc->base.id, DPU_HW_BLK_INTF,
- hw_blk, ARRAY_SIZE(hw_blk));
- for (j = 0; j < num_blk; j++) {
- struct dpu_hw_intf *hw_intf;
-
- hw_intf = to_dpu_hw_intf(hw_blk[i]);
- if (hw_intf->idx == phys->intf_idx)
- phys->hw_intf = hw_intf;
- }
+ if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX)
+ phys->hw_intf = dpu_rm_get_intf(&dpu_kms->rm, phys->intf_idx);
if (!phys->hw_intf) {
DPU_ERROR_ENC(dpu_enc,
@@ -1076,9 +1021,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
return;
}
- phys->connector = conn->state->connector;
- if (phys->ops.mode_set)
- phys->ops.mode_set(phys, mode, adj_mode);
+ phys->cached_mode = crtc_state->adjusted_mode;
+ if (phys->ops.atomic_mode_set)
+ phys->ops.atomic_mode_set(phys, crtc_state, conn_state);
}
}
@@ -1099,7 +1044,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
}
- if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort &&
+ if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_TMDS &&
dpu_enc->cur_master->hw_mdptop &&
dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select)
dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select(
@@ -1109,7 +1054,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI &&
!WARN_ON(dpu_enc->num_phys_encs == 0)) {
- unsigned bpc = dpu_enc->phys_encs[0]->connector->display_info.bpc;
+ unsigned bpc = dpu_enc->connector->display_info.bpc;
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
if (!dpu_enc->hw_pp[i])
continue;
@@ -1142,14 +1087,12 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = NULL;
int ret = 0;
- struct msm_drm_private *priv;
struct drm_display_mode *cur_mode = NULL;
dpu_enc = to_dpu_encoder_virt(drm_enc);
mutex_lock(&dpu_enc->enc_lock);
cur_mode = &dpu_enc->base.crtc->state->adjusted_mode;
- priv = drm_enc->dev->dev_private;
trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay,
cur_mode->vdisplay);
@@ -1179,7 +1122,6 @@ out:
static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = NULL;
- struct msm_drm_private *priv;
int i = 0;
dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -1188,8 +1130,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
mutex_lock(&dpu_enc->enc_lock);
dpu_enc->enabled = false;
- priv = drm_enc->dev->dev_private;
-
trace_dpu_enc_disable(DRMID(drm_enc));
/* wait for idle */
@@ -1213,9 +1153,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_STOP);
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- dpu_enc->phys_encs[i]->connector = NULL;
- }
+ dpu_enc->connector = NULL;
DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
@@ -2093,7 +2031,7 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t)
}
static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
- .mode_set = dpu_encoder_virt_mode_set,
+ .atomic_mode_set = dpu_encoder_virt_atomic_mode_set,
.disable = dpu_encoder_virt_disable,
.enable = dpu_encoder_virt_enable,
.atomic_check = dpu_encoder_virt_atomic_check,
@@ -2128,8 +2066,6 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
timer_setup(&dpu_enc->vsync_event_timer,
dpu_encoder_vsync_event_handler,
0);
- else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS)
- dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]];
INIT_DELAYED_WORK(&dpu_enc->delayed_off_work,
dpu_encoder_off_work);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index e241914a9677..42db6ce12caf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -19,22 +19,24 @@
#define IDLE_TIMEOUT (66 - 16/2)
/**
- * Encoder functions and data types
- * @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
- */
-struct dpu_encoder_hw_resources {
- enum dpu_intf_mode intfs[INTF_MAX];
+ * struct msm_display_info - defines display properties
+ * @intf_type: DRM_MODE_ENCODER_ type
+ * @capabilities: Bitmask of display flags
+ * @num_of_h_tiles: Number of horizontal tiles in case of split interface
+ * @h_tile_instance: Controller instance used per tile. Number of elements is
+ * based on num_of_h_tiles
+ * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is
+ * used instead of panel TE in cmd mode panels
+ */
+struct msm_display_info {
+ int intf_type;
+ uint32_t capabilities;
+ uint32_t num_of_h_tiles;
+ uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];
+ bool is_te_using_watchdog_timer;
};
/**
- * dpu_encoder_get_hw_resources - Populate table of required hardware resources
- * @encoder: encoder pointer
- * @hw_res: resource table to populate with encoder required resources
- */
-void dpu_encoder_get_hw_resources(struct drm_encoder *encoder,
- struct dpu_encoder_hw_resources *hw_res);
-
-/**
* dpu_encoder_assign_crtc - Link the encoder to the crtc it's assigned to
* @encoder: encoder pointer
* @crtc: crtc pointer
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index e7270eb6b84b..fa8493ac0340 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -84,16 +84,12 @@ struct dpu_encoder_virt_ops {
* @is_master: Whether this phys_enc is the current master
* encoder. Can be switched at enable time. Based
* on split_role and current mode (CMD/VID).
- * @mode_fixup: DRM Call. Fixup a DRM mode.
- * @mode_set: DRM Call. Set a DRM mode.
+ * @atomic_mode_set: DRM Call. Set a DRM mode.
* This likely caches the mode, for use at enable.
* @enable: DRM Call. Enable a DRM mode.
* @disable: DRM Call. Disable mode.
* @atomic_check: DRM Call. Atomic check new DRM state.
* @destroy: DRM Call. Destroy and release resources.
- * @get_hw_resources: Populate the structure with the hardware
- * resources that this phys_enc is using.
- * Expect no overlap between phys_encs.
* @control_vblank_irq Register/Deregister for VBLANK IRQ
* @wait_for_commit_done: Wait for hardware to have flushed the
* current pending frames to hardware
@@ -117,20 +113,15 @@ struct dpu_encoder_phys_ops {
struct dentry *debugfs_root);
void (*prepare_commit)(struct dpu_encoder_phys *encoder);
bool (*is_master)(struct dpu_encoder_phys *encoder);
- bool (*mode_fixup)(struct dpu_encoder_phys *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
- void (*mode_set)(struct dpu_encoder_phys *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
+ void (*atomic_mode_set)(struct dpu_encoder_phys *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
void (*enable)(struct dpu_encoder_phys *encoder);
void (*disable)(struct dpu_encoder_phys *encoder);
int (*atomic_check)(struct dpu_encoder_phys *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
void (*destroy)(struct dpu_encoder_phys *encoder);
- void (*get_hw_resources)(struct dpu_encoder_phys *encoder,
- struct dpu_encoder_hw_resources *hw_res);
int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable);
int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc);
int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc);
@@ -182,7 +173,6 @@ struct dpu_encoder_irq {
* tied to a specific panel / sub-panel. Abstract type, sub-classed by
* phys_vid or phys_cmd for video mode or command mode encs respectively.
* @parent: Pointer to the containing virtual encoder
- * @connector: If a mode is set, cached pointer to the active connector
* @ops: Operations exposed to the virtual encoder
* @parent_ops: Callbacks exposed by the parent to the phys_enc
* @hw_mdptop: Hardware interface to the top registers
@@ -211,7 +201,6 @@ struct dpu_encoder_irq {
*/
struct dpu_encoder_phys {
struct drm_encoder *parent;
- struct drm_connector *connector;
struct dpu_encoder_phys_ops ops;
const struct dpu_encoder_virt_ops *parent_ops;
struct dpu_hw_mdp *hw_mdptop;
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 34a6940d12c5..d59802b67d15 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
@@ -45,15 +45,6 @@ static bool dpu_encoder_phys_cmd_is_master(struct dpu_encoder_phys *phys_enc)
return (phys_enc->split_role != ENC_ROLE_SLAVE);
}
-static bool dpu_encoder_phys_cmd_mode_fixup(
- struct dpu_encoder_phys *phys_enc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
-{
- DPU_DEBUG_CMDENC(to_dpu_encoder_phys_cmd(phys_enc), "\n");
- return true;
-}
-
static void _dpu_encoder_phys_cmd_update_intf_cfg(
struct dpu_encoder_phys *phys_enc)
{
@@ -144,23 +135,13 @@ static void dpu_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx)
phys_enc);
}
-static void dpu_encoder_phys_cmd_mode_set(
+static void dpu_encoder_phys_cmd_atomic_mode_set(
struct dpu_encoder_phys *phys_enc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
- struct dpu_encoder_phys_cmd *cmd_enc =
- to_dpu_encoder_phys_cmd(phys_enc);
struct dpu_encoder_irq *irq;
- if (!mode || !adj_mode) {
- DPU_ERROR("invalid args\n");
- return;
- }
- phys_enc->cached_mode = *adj_mode;
- DPU_DEBUG_CMDENC(cmd_enc, "caching mode:\n");
- drm_mode_debug_printmodeline(adj_mode);
-
irq = &phys_enc->irq[INTR_IDX_CTL_START];
irq->irq_idx = phys_enc->hw_ctl->caps->intr_start;
@@ -534,13 +515,6 @@ static void dpu_encoder_phys_cmd_destroy(struct dpu_encoder_phys *phys_enc)
kfree(cmd_enc);
}
-static void dpu_encoder_phys_cmd_get_hw_resources(
- struct dpu_encoder_phys *phys_enc,
- struct dpu_encoder_hw_resources *hw_res)
-{
- hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD;
-}
-
static void dpu_encoder_phys_cmd_prepare_for_kickoff(
struct dpu_encoder_phys *phys_enc)
{
@@ -682,6 +656,9 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done(
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
return 0;
+ if (phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl))
+ return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc);
+
return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc);
}
@@ -731,12 +708,10 @@ static void dpu_encoder_phys_cmd_init_ops(
{
ops->prepare_commit = dpu_encoder_phys_cmd_prepare_commit;
ops->is_master = dpu_encoder_phys_cmd_is_master;
- ops->mode_set = dpu_encoder_phys_cmd_mode_set;
- ops->mode_fixup = dpu_encoder_phys_cmd_mode_fixup;
+ ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set;
ops->enable = dpu_encoder_phys_cmd_enable;
ops->disable = dpu_encoder_phys_cmd_disable;
ops->destroy = dpu_encoder_phys_cmd_destroy;
- ops->get_hw_resources = dpu_encoder_phys_cmd_get_hw_resources;
ops->control_vblank_irq = dpu_encoder_phys_cmd_control_vblank_irq;
ops->wait_for_commit_done = dpu_encoder_phys_cmd_wait_for_commit_done;
ops->prepare_for_kickoff = dpu_encoder_phys_cmd_prepare_for_kickoff;
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 ddd9d89cd456..f49f42e70b29 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
@@ -225,19 +225,6 @@ static void programmable_fetch_config(struct dpu_encoder_phys *phys_enc,
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
}
-static bool dpu_encoder_phys_vid_mode_fixup(
- struct dpu_encoder_phys *phys_enc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
-{
- DPU_DEBUG_VIDENC(phys_enc, "\n");
-
- /*
- * Modifying mode has consequences when the mode comes back to us
- */
- return true;
-}
-
static void dpu_encoder_phys_vid_setup_timing_engine(
struct dpu_encoder_phys *phys_enc)
{
@@ -361,19 +348,13 @@ static bool dpu_encoder_phys_vid_needs_single_flush(
return phys_enc->split_role != ENC_ROLE_SOLO;
}
-static void dpu_encoder_phys_vid_mode_set(
+static void dpu_encoder_phys_vid_atomic_mode_set(
struct dpu_encoder_phys *phys_enc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct dpu_encoder_irq *irq;
- if (adj_mode) {
- phys_enc->cached_mode = *adj_mode;
- drm_mode_debug_printmodeline(adj_mode);
- DPU_DEBUG_VIDENC(phys_enc, "caching mode:\n");
- }
-
irq = &phys_enc->irq[INTR_IDX_VSYNC];
irq->irq_idx = phys_enc->hw_intf->cap->intr_vsync;
@@ -465,13 +446,6 @@ static void dpu_encoder_phys_vid_destroy(struct dpu_encoder_phys *phys_enc)
kfree(phys_enc);
}
-static void dpu_encoder_phys_vid_get_hw_resources(
- struct dpu_encoder_phys *phys_enc,
- struct dpu_encoder_hw_resources *hw_res)
-{
- hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_VIDEO;
-}
-
static int dpu_encoder_phys_vid_wait_for_vblank(
struct dpu_encoder_phys *phys_enc)
{
@@ -675,12 +649,10 @@ static int dpu_encoder_phys_vid_get_frame_count(
static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops)
{
ops->is_master = dpu_encoder_phys_vid_is_master;
- ops->mode_set = dpu_encoder_phys_vid_mode_set;
- ops->mode_fixup = dpu_encoder_phys_vid_mode_fixup;
+ ops->atomic_mode_set = dpu_encoder_phys_vid_atomic_mode_set;
ops->enable = dpu_encoder_phys_vid_enable;
ops->disable = dpu_encoder_phys_vid_disable;
ops->destroy = dpu_encoder_phys_vid_destroy;
- ops->get_hw_resources = dpu_encoder_phys_vid_get_hw_resources;
ops->control_vblank_irq = dpu_encoder_phys_vid_control_vblank_irq;
ops->wait_for_commit_done = dpu_encoder_phys_vid_wait_for_commit_done;
ops->wait_for_vblank = dpu_encoder_phys_vid_wait_for_vblank;
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 aa75991903a6..a4fe77cddfea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -16,6 +16,9 @@
BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT))
+#define VIG_MSM8998_MASK \
+ (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3))
+
#define VIG_SDM845_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3))
@@ -25,6 +28,13 @@
#define VIG_SM8250_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE))
+#define VIG_QCM2290_MASK (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL))
+
+#define DMA_MSM8998_MASK \
+ (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\
+ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
+ BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT))
+
#define DMA_SDM845_MASK \
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
@@ -33,6 +43,9 @@
#define DMA_CURSOR_SDM845_MASK \
(DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR))
+#define DMA_CURSOR_MSM8998_MASK \
+ (DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
+
#define MIXER_SDM845_MASK \
(BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER))
@@ -49,6 +62,8 @@
#define MERGE_3D_SM8150_MASK (0)
+#define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC)
+
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
#define INTF_SDM845_MASK (0)
@@ -90,6 +105,17 @@
BIT(MDP_INTF3_INTR) | \
BIT(MDP_INTF4_INTR))
+#define IRQ_SC8180X_MASK (BIT(MDP_SSPP_TOP0_INTR) | \
+ BIT(MDP_SSPP_TOP0_INTR2) | \
+ BIT(MDP_SSPP_TOP0_HIST_INTR) | \
+ BIT(MDP_INTF0_INTR) | \
+ BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF2_INTR) | \
+ BIT(MDP_INTF3_INTR) | \
+ BIT(MDP_INTF4_INTR) | \
+ BIT(MDP_INTF5_INTR) | \
+ BIT(MDP_AD4_0_INTR) | \
+ BIT(MDP_AD4_1_INTR))
#define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)
#define DEFAULT_DPU_LINE_WIDTH 2048
@@ -181,6 +207,22 @@ static const uint32_t plane_formats_yuv[] = {
* DPU sub blocks config
*************************************************************/
/* DPU top level caps */
+static const struct dpu_caps msm8998_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0x7,
+ .qseed_type = DPU_SSPP_SCALER_QSEED3,
+ .smart_dma_rev = DPU_SSPP_SMART_DMA_V1,
+ .ubwc_version = DPU_HW_UBWC_VER_10,
+ .has_src_split = true,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .has_3d_merge = true,
+ .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
static const struct dpu_caps sdm845_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
@@ -225,6 +267,22 @@ static const struct dpu_caps sm8150_dpu_caps = {
.max_vdeci_exp = MAX_VERT_DECIMATION,
};
+static const struct dpu_caps sc8180x_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0xb,
+ .qseed_type = DPU_SSPP_SCALER_QSEED3,
+ .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
+ .ubwc_version = DPU_HW_UBWC_VER_30,
+ .has_src_split = true,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .has_3d_merge = true,
+ .max_linewidth = 4096,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
static const struct dpu_caps sm8250_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
@@ -251,11 +309,51 @@ static const struct dpu_caps sc7280_dpu_caps = {
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
};
+static const struct dpu_mdp_cfg msm8998_mdp[] = {
+ {
+ .name = "top_0", .id = MDP_TOP,
+ .base = 0x0, .len = 0x458,
+ .features = 0,
+ .highest_bank_bit = 0x2,
+ .clk_ctrls[DPU_CLK_CTRL_VIG0] = {
+ .reg_off = 0x2AC, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG1] = {
+ .reg_off = 0x2B4, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG2] = {
+ .reg_off = 0x2BC, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG3] = {
+ .reg_off = 0x2C4, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_DMA0] = {
+ .reg_off = 0x2AC, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_DMA1] = {
+ .reg_off = 0x2B4, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_DMA2] = {
+ .reg_off = 0x2C4, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_DMA3] = {
+ .reg_off = 0x2C4, .bit_off = 12},
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = {
+ .reg_off = 0x3A8, .bit_off = 15},
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = {
+ .reg_off = 0x3B0, .bit_off = 15},
+ },
+};
+
+static const struct dpu_caps qcm2290_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0x4,
+ .smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
+ .ubwc_version = DPU_HW_UBWC_VER_20,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .max_linewidth = 2160,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
static const struct dpu_mdp_cfg sdm845_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
.base = 0x0, .len = 0x45C,
- .features = 0,
+ .features = BIT(DPU_MDP_AUDIO_SELECT),
.highest_bank_bit = 0x2,
.clk_ctrls[DPU_CLK_CTRL_VIG0] = {
.reg_off = 0x2AC, .bit_off = 0},
@@ -293,6 +391,31 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = {
},
};
+static const struct dpu_mdp_cfg sc8180x_mdp[] = {
+ {
+ .name = "top_0", .id = MDP_TOP,
+ .base = 0x0, .len = 0x45C,
+ .features = 0,
+ .highest_bank_bit = 0x3,
+ .clk_ctrls[DPU_CLK_CTRL_VIG0] = {
+ .reg_off = 0x2AC, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG1] = {
+ .reg_off = 0x2B4, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG2] = {
+ .reg_off = 0x2BC, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG3] = {
+ .reg_off = 0x2C4, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_DMA0] = {
+ .reg_off = 0x2AC, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_DMA1] = {
+ .reg_off = 0x2B4, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = {
+ .reg_off = 0x2BC, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = {
+ .reg_off = 0x2C4, .bit_off = 8},
+ },
+};
+
static const struct dpu_mdp_cfg sm8250_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
@@ -336,9 +459,55 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = {
},
};
+static const struct dpu_mdp_cfg qcm2290_mdp[] = {
+ {
+ .name = "top_0", .id = MDP_TOP,
+ .base = 0x0, .len = 0x494,
+ .features = 0,
+ .highest_bank_bit = 0x2,
+ .clk_ctrls[DPU_CLK_CTRL_VIG0] = {
+ .reg_off = 0x2AC, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_DMA0] = {
+ .reg_off = 0x2AC, .bit_off = 8},
+ },
+};
+
/*************************************************************
* CTL sub blocks config
*************************************************************/
+static const struct dpu_ctl_cfg msm8998_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x94,
+ .features = BIT(DPU_CTL_SPLIT_DISPLAY),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+ },
+ {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x94,
+ .features = 0,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+ },
+ {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x94,
+ .features = BIT(DPU_CTL_SPLIT_DISPLAY),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+ },
+ {
+ .name = "ctl_3", .id = CTL_3,
+ .base = 0x1600, .len = 0x94,
+ .features = 0,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+ },
+ {
+ .name = "ctl_4", .id = CTL_4,
+ .base = 0x1800, .len = 0x94,
+ .features = 0,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
+ },
+};
+
static const struct dpu_ctl_cfg sdm845_ctl[] = {
{
.name = "ctl_0", .id = CTL_0,
@@ -459,6 +628,15 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = {
},
};
+static const struct dpu_ctl_cfg qcm2290_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x1dc,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+ },
+};
+
/*************************************************************
* SSPP sub blocks config
*************************************************************/
@@ -497,6 +675,15 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = {
.virt_num_formats = ARRAY_SIZE(plane_formats), \
}
+static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 =
+ _VIG_SBLK("0", 0, DPU_SSPP_SCALER_QSEED3);
+static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 =
+ _VIG_SBLK("1", 0, DPU_SSPP_SCALER_QSEED3);
+static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 =
+ _VIG_SBLK("2", 0, DPU_SSPP_SCALER_QSEED3);
+static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 =
+ _VIG_SBLK("3", 0, DPU_SSPP_SCALER_QSEED3);
+
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 =
_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3);
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 =
@@ -523,6 +710,25 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4);
.clk_ctrl = _clkctrl \
}
+static const struct dpu_sspp_cfg msm8998_sspp[] = {
+ SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_MSM8998_MASK,
+ msm8998_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
+ SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_MSM8998_MASK,
+ msm8998_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
+ SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_MSM8998_MASK,
+ msm8998_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
+ SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_MSM8998_MASK,
+ msm8998_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
+ SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_MSM8998_MASK,
+ sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
+ SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_MSM8998_MASK,
+ sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
+ SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_MSM8998_MASK,
+ sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
+ SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_MSM8998_MASK,
+ sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
+};
+
static const struct dpu_sspp_cfg sdm845_sspp[] = {
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK,
sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
@@ -595,21 +801,34 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = {
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
};
-/*************************************************************
- * MIXER sub blocks config
- *************************************************************/
-/* SDM845 */
+#define _VIG_SBLK_NOSCALE(num, sdma_pri) \
+ { \
+ .maxdwnscale = SSPP_UNITY_SCALE, \
+ .maxupscale = SSPP_UNITY_SCALE, \
+ .smart_dma_priority = sdma_pri, \
+ .src_blk = {.name = STRCAT("sspp_src_", num), \
+ .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
+ .format_list = plane_formats_yuv, \
+ .num_formats = ARRAY_SIZE(plane_formats_yuv), \
+ .virt_format_list = plane_formats, \
+ .virt_num_formats = ARRAY_SIZE(plane_formats), \
+ }
-static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
- .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
- .maxblendstages = 11, /* excluding base layer */
- .blendstage_base = { /* offsets relative to mixer base */
- 0x20, 0x38, 0x50, 0x68, 0x80, 0x98,
- 0xb0, 0xc8, 0xe0, 0xf8, 0x110
- },
+static const struct dpu_sspp_sub_blks qcm2290_vig_sblk_0 = _VIG_SBLK_NOSCALE("0", 2);
+static const struct dpu_sspp_sub_blks qcm2290_dma_sblk_0 = _DMA_SBLK("8", 1);
+
+static const struct dpu_sspp_cfg qcm2290_sspp[] = {
+ SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_QCM2290_MASK,
+ qcm2290_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
+ SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
+ qcm2290_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
};
+/*************************************************************
+ * MIXER sub blocks config
+ *************************************************************/
+
#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \
{ \
.name = _name, .id = _id, \
@@ -621,6 +840,43 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
.dspp = _dspp \
}
+/* MSM8998 */
+
+static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
+ .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .maxblendstages = 7, /* excluding base layer */
+ .blendstage_base = { /* offsets relative to mixer base */
+ 0x20, 0x50, 0x80, 0xb0, 0x230,
+ 0x260, 0x290
+ },
+};
+
+static const struct dpu_lm_cfg msm8998_lm[] = {
+ LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
+ &msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0),
+ LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
+ &msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1),
+ LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
+ &msm8998_lm_sblk, PINGPONG_2, LM_0, 0),
+ LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
+ &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
+ LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK,
+ &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
+ LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
+ &msm8998_lm_sblk, PINGPONG_3, LM_1, 0),
+};
+
+/* SDM845 */
+
+static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
+ .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .maxblendstages = 11, /* excluding base layer */
+ .blendstage_base = { /* offsets relative to mixer base */
+ 0x20, 0x38, 0x50, 0x68, 0x80, 0x98,
+ 0xb0, 0xc8, 0xe0, 0xf8, 0x110
+ },
+};
+
static const struct dpu_lm_cfg sdm845_lm[] = {
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
&sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
@@ -679,9 +935,31 @@ static const struct dpu_lm_cfg sc7280_lm[] = {
&sc7180_lm_sblk, PINGPONG_3, LM_2, 0),
};
+/* QCM2290 */
+
+static const struct dpu_lm_sub_blks qcm2290_lm_sblk = {
+ .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .maxblendstages = 4, /* excluding base layer */
+ .blendstage_base = { /* offsets relative to mixer base */
+ 0x20, 0x38, 0x50, 0x68
+ },
+};
+
+static const struct dpu_lm_cfg qcm2290_lm[] = {
+ LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK,
+ &qcm2290_lm_sblk, PINGPONG_0, 0, DSPP_0),
+};
+
/*************************************************************
* DSPP sub blocks config
*************************************************************/
+static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = {
+ .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
+ .len = 0x90, .version = 0x10007},
+ .gc = { .id = DPU_DSPP_GC, .base = 0x17c0,
+ .len = 0x90, .version = 0x10007},
+};
+
static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
.len = 0x90, .version = 0x10000},
@@ -700,6 +978,13 @@ static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = {
.sblk = _sblk \
}
+static const struct dpu_dspp_cfg msm8998_dspp[] = {
+ DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_MSM8998_MASK,
+ &msm8998_dspp_sblk),
+ DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_MSM8998_MASK,
+ &msm8998_dspp_sblk),
+};
+
static const struct dpu_dspp_cfg sc7180_dspp[] = {
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
&sc7180_dspp_sblk),
@@ -716,6 +1001,11 @@ static const struct dpu_dspp_cfg sm8150_dspp[] = {
&sm8150_dspp_sblk),
};
+static const struct dpu_dspp_cfg qcm2290_dspp[] = {
+ DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+};
+
/*************************************************************
* PINGPONG sub blocks config
*************************************************************/
@@ -798,6 +1088,12 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = {
-1),
};
+static struct dpu_pingpong_cfg qcm2290_pp[] = {
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
+};
+
/*************************************************************
* MERGE_3D sub blocks config
*************************************************************/
@@ -836,6 +1132,13 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
.intr_vsync = DPU_IRQ_IDX(_reg, _vsync_bit), \
}
+static const struct dpu_intf_cfg msm8998_intf[] = {
+ INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
+ INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
+ INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
+ INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_HDMI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+};
+
static const struct dpu_intf_cfg sdm845_intf[] = {
INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
@@ -861,13 +1164,74 @@ static const struct dpu_intf_cfg sc7280_intf[] = {
INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23),
};
+static const struct dpu_intf_cfg sc8180x_intf[] = {
+ INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
+ INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
+ INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
+ /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this is supported */
+ INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 20, 21),
+ INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 22, 23),
+};
+
+static const struct dpu_intf_cfg qcm2290_intf[] = {
+ INTF_BLK("intf_0", INTF_0, 0x00000, INTF_NONE, 0, 0, 0, 0, 0, 0),
+ INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
+};
+
/*************************************************************
* VBIF sub blocks config
*************************************************************/
/* VBIF QOS remap */
+static const u32 msm8998_rt_pri_lvl[] = {1, 2, 2, 2};
+static const u32 msm8998_nrt_pri_lvl[] = {1, 1, 1, 1};
static const u32 sdm845_rt_pri_lvl[] = {3, 3, 4, 4, 5, 5, 6, 6};
static const u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3};
+static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
+ {
+ .pps = 1088 * 1920 * 30,
+ .ot_limit = 2,
+ },
+ {
+ .pps = 1088 * 1920 * 60,
+ .ot_limit = 6,
+ },
+ {
+ .pps = 3840 * 2160 * 30,
+ .ot_limit = 16,
+ },
+};
+
+static const struct dpu_vbif_cfg msm8998_vbif[] = {
+ {
+ .name = "vbif_0", .id = VBIF_0,
+ .base = 0, .len = 0x1040,
+ .default_ot_rd_limit = 32,
+ .default_ot_wr_limit = 32,
+ .features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
+ .xin_halt_timeout = 0x4000,
+ .dynamic_ot_rd_tbl = {
+ .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
+ .cfg = msm8998_ot_rdwr_cfg,
+ },
+ .dynamic_ot_wr_tbl = {
+ .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
+ .cfg = msm8998_ot_rdwr_cfg,
+ },
+ .qos_rt_tbl = {
+ .npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl),
+ .priority_lvl = msm8998_rt_pri_lvl,
+ },
+ .qos_nrt_tbl = {
+ .npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl),
+ .priority_lvl = msm8998_nrt_pri_lvl,
+ },
+ .memtype_count = 14,
+ .memtype = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+ },
+};
+
static const struct dpu_vbif_cfg sdm845_vbif[] = {
{
.name = "vbif_0", .id = VBIF_0,
@@ -908,6 +1272,22 @@ static const struct dpu_reg_dma_cfg sm8250_regdma = {
*************************************************************/
/* SSPP QOS LUTs */
+static const struct dpu_qos_lut_entry msm8998_qos_linear[] = {
+ {.fl = 4, .lut = 0x1b},
+ {.fl = 5, .lut = 0x5b},
+ {.fl = 6, .lut = 0x15b},
+ {.fl = 7, .lut = 0x55b},
+ {.fl = 8, .lut = 0x155b},
+ {.fl = 9, .lut = 0x555b},
+ {.fl = 10, .lut = 0x1555b},
+ {.fl = 11, .lut = 0x5555b},
+ {.fl = 12, .lut = 0x15555b},
+ {.fl = 13, .lut = 0x55555b},
+ {.fl = 14, .lut = 0},
+ {.fl = 1, .lut = 0x1b},
+ {.fl = 0, .lut = 0}
+};
+
static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
{.fl = 4, .lut = 0x357},
{.fl = 5, .lut = 0x3357},
@@ -923,6 +1303,15 @@ static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
{.fl = 0, .lut = 0x11222222223357}
};
+static const struct dpu_qos_lut_entry msm8998_qos_macrotile[] = {
+ {.fl = 10, .lut = 0x1aaff},
+ {.fl = 11, .lut = 0x5aaff},
+ {.fl = 12, .lut = 0x15aaff},
+ {.fl = 13, .lut = 0x55aaff},
+ {.fl = 1, .lut = 0x1aaff},
+ {.fl = 0, .lut = 0},
+};
+
static const struct dpu_qos_lut_entry sc7180_qos_linear[] = {
{.fl = 0, .lut = 0x0011222222335777},
};
@@ -931,6 +1320,14 @@ static const struct dpu_qos_lut_entry sm8150_qos_linear[] = {
{.fl = 0, .lut = 0x0011222222223357 },
};
+static const struct dpu_qos_lut_entry sc8180x_qos_linear[] = {
+ {.fl = 4, .lut = 0x0000000000000357 },
+};
+
+static const struct dpu_qos_lut_entry qcm2290_qos_linear[] = {
+ {.fl = 0, .lut = 0x0011222222335777},
+};
+
static const struct dpu_qos_lut_entry sdm845_qos_macrotile[] = {
{.fl = 10, .lut = 0x344556677},
{.fl = 11, .lut = 0x3344556677},
@@ -944,6 +1341,14 @@ static const struct dpu_qos_lut_entry sc7180_qos_macrotile[] = {
{.fl = 0, .lut = 0x0011223344556677},
};
+static const struct dpu_qos_lut_entry sc8180x_qos_macrotile[] = {
+ {.fl = 10, .lut = 0x0000000344556677},
+};
+
+static const struct dpu_qos_lut_entry msm8998_qos_nrt[] = {
+ {.fl = 0, .lut = 0x0},
+};
+
static const struct dpu_qos_lut_entry sdm845_qos_nrt[] = {
{.fl = 0, .lut = 0x0},
};
@@ -952,6 +1357,42 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
{.fl = 0, .lut = 0x0},
};
+static const struct dpu_perf_cfg msm8998_perf_data = {
+ .max_bw_low = 6700000,
+ .max_bw_high = 6700000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 800000,
+ .min_dram_ib = 800000,
+ .undersized_prefill_lines = 2,
+ .xtra_prefill_lines = 2,
+ .dest_scale_prefill_lines = 3,
+ .macrotile_prefill_lines = 4,
+ .yuv_nv12_prefill_lines = 8,
+ .linear_prefill_lines = 1,
+ .downscaling_prefill_lines = 1,
+ .amortizable_threshold = 25,
+ .min_prefill_lines = 25,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(msm8998_qos_linear),
+ .entries = msm8998_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
+ .entries = msm8998_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_nrt),
+ .entries = msm8998_qos_nrt
+ },
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+ .clk_inefficiency_factor = 200,
+ .bw_inefficiency_factor = 120,
+};
+
static const struct dpu_perf_cfg sdm845_perf_data = {
.max_bw_low = 6800000,
.max_bw_high = 6800000,
@@ -1045,6 +1486,33 @@ static const struct dpu_perf_cfg sm8150_perf_data = {
.bw_inefficiency_factor = 120,
};
+static const struct dpu_perf_cfg sc8180x_perf_data = {
+ .max_bw_low = 9600000,
+ .max_bw_high = 9600000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 800000,
+ .min_dram_ib = 800000,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(sc8180x_qos_linear),
+ .entries = sc8180x_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(sc8180x_qos_macrotile),
+ .entries = sc8180x_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ /* TODO: macrotile-qseed is different from macrotile */
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+ .clk_inefficiency_factor = 105,
+ .bw_inefficiency_factor = 120,
+};
+
static const struct dpu_perf_cfg sm8250_perf_data = {
.max_bw_low = 13700000,
.max_bw_high = 16600000,
@@ -1102,11 +1570,62 @@ static const struct dpu_perf_cfg sc7280_perf_data = {
.bw_inefficiency_factor = 120,
};
+static const struct dpu_perf_cfg qcm2290_perf_data = {
+ .max_bw_low = 2700000,
+ .max_bw_high = 2700000,
+ .min_core_ib = 1300000,
+ .min_llcc_ib = 0,
+ .min_dram_ib = 1600000,
+ .min_prefill_lines = 24,
+ .danger_lut_tbl = {0xff, 0x0, 0x0},
+ .safe_lut_tbl = {0xfff0, 0x0, 0x0},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(qcm2290_qos_linear),
+ .entries = qcm2290_qos_linear
+ },
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+ .clk_inefficiency_factor = 105,
+ .bw_inefficiency_factor = 120,
+};
/*************************************************************
* Hardware catalog init
*************************************************************/
/*
+ * msm8998_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
+ * and instance counts.
+ */
+static void msm8998_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
+{
+ *dpu_cfg = (struct dpu_mdss_cfg){
+ .caps = &msm8998_dpu_caps,
+ .mdp_count = ARRAY_SIZE(msm8998_mdp),
+ .mdp = msm8998_mdp,
+ .ctl_count = ARRAY_SIZE(msm8998_ctl),
+ .ctl = msm8998_ctl,
+ .sspp_count = ARRAY_SIZE(msm8998_sspp),
+ .sspp = msm8998_sspp,
+ .mixer_count = ARRAY_SIZE(msm8998_lm),
+ .mixer = msm8998_lm,
+ .dspp_count = ARRAY_SIZE(msm8998_dspp),
+ .dspp = msm8998_dspp,
+ .pingpong_count = ARRAY_SIZE(sdm845_pp),
+ .pingpong = sdm845_pp,
+ .intf_count = ARRAY_SIZE(msm8998_intf),
+ .intf = msm8998_intf,
+ .vbif_count = ARRAY_SIZE(msm8998_vbif),
+ .vbif = msm8998_vbif,
+ .reg_dma_count = 0,
+ .perf = msm8998_perf_data,
+ .mdss_irqs = IRQ_SM8250_MASK,
+ };
+}
+
+/*
* sdm845_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
* and instance counts.
*/
@@ -1200,6 +1719,37 @@ static void sm8150_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
}
/*
+ * sc8180x_cfg_init(): populate sc8180 dpu sub-blocks reg offsets
+ * and instance counts.
+ */
+static void sc8180x_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
+{
+ *dpu_cfg = (struct dpu_mdss_cfg){
+ .caps = &sc8180x_dpu_caps,
+ .mdp_count = ARRAY_SIZE(sc8180x_mdp),
+ .mdp = sc8180x_mdp,
+ .ctl_count = ARRAY_SIZE(sm8150_ctl),
+ .ctl = sm8150_ctl,
+ .sspp_count = ARRAY_SIZE(sdm845_sspp),
+ .sspp = sdm845_sspp,
+ .mixer_count = ARRAY_SIZE(sm8150_lm),
+ .mixer = sm8150_lm,
+ .pingpong_count = ARRAY_SIZE(sm8150_pp),
+ .pingpong = sm8150_pp,
+ .merge_3d_count = ARRAY_SIZE(sm8150_merge_3d),
+ .merge_3d = sm8150_merge_3d,
+ .intf_count = ARRAY_SIZE(sc8180x_intf),
+ .intf = sc8180x_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .reg_dma_count = 1,
+ .dma_cfg = sm8150_regdma,
+ .perf = sc8180x_perf_data,
+ .mdss_irqs = IRQ_SC8180X_MASK,
+ };
+}
+
+/*
* sm8250_cfg_init(): populate sm8250 dpu sub-blocks reg offsets
* and instance counts.
*/
@@ -1255,13 +1805,49 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
};
}
+
+/*
+ * qcm2290_cfg_init(): populate qcm2290 dpu sub-blocks reg offsets
+ * and instance counts.
+ */
+static void qcm2290_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
+{
+ *dpu_cfg = (struct dpu_mdss_cfg){
+ .caps = &qcm2290_dpu_caps,
+ .mdp_count = ARRAY_SIZE(qcm2290_mdp),
+ .mdp = qcm2290_mdp,
+ .ctl_count = ARRAY_SIZE(qcm2290_ctl),
+ .ctl = qcm2290_ctl,
+ .sspp_count = ARRAY_SIZE(qcm2290_sspp),
+ .sspp = qcm2290_sspp,
+ .mixer_count = ARRAY_SIZE(qcm2290_lm),
+ .mixer = qcm2290_lm,
+ .dspp_count = ARRAY_SIZE(qcm2290_dspp),
+ .dspp = qcm2290_dspp,
+ .pingpong_count = ARRAY_SIZE(qcm2290_pp),
+ .pingpong = qcm2290_pp,
+ .intf_count = ARRAY_SIZE(qcm2290_intf),
+ .intf = qcm2290_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .reg_dma_count = 1,
+ .dma_cfg = sdm845_regdma,
+ .perf = qcm2290_perf_data,
+ .mdss_irqs = IRQ_SC7180_MASK,
+ };
+}
+
static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = {
+ { .hw_rev = DPU_HW_VER_300, .cfg_init = msm8998_cfg_init},
+ { .hw_rev = DPU_HW_VER_301, .cfg_init = msm8998_cfg_init},
{ .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init},
{ .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init},
{ .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init},
{ .hw_rev = DPU_HW_VER_501, .cfg_init = sm8150_cfg_init},
+ { .hw_rev = DPU_HW_VER_510, .cfg_init = sc8180x_cfg_init},
{ .hw_rev = DPU_HW_VER_600, .cfg_init = sm8250_cfg_init},
{ .hw_rev = DPU_HW_VER_620, .cfg_init = sc7180_cfg_init},
+ { .hw_rev = DPU_HW_VER_650, .cfg_init = qcm2290_cfg_init},
{ .hw_rev = DPU_HW_VER_720, .cfg_init = sc7280_cfg_init},
};
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 31af04afda7d..b85b24bd3f53 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -39,8 +39,10 @@
#define DPU_HW_VER_410 DPU_HW_VER(4, 1, 0) /* sdm670 v1.0 */
#define DPU_HW_VER_500 DPU_HW_VER(5, 0, 0) /* sm8150 v1.0 */
#define DPU_HW_VER_501 DPU_HW_VER(5, 0, 1) /* sm8150 v2.0 */
+#define DPU_HW_VER_510 DPU_HW_VER(5, 1, 1) /* sc8180 */
#define DPU_HW_VER_600 DPU_HW_VER(6, 0, 0) /* sm8250 */
#define DPU_HW_VER_620 DPU_HW_VER(6, 2, 0) /* sc7180 v1.0 */
+#define DPU_HW_VER_650 DPU_HW_VER(6, 5, 0) /* qcm2290|sm4125 */
#define DPU_HW_VER_720 DPU_HW_VER(7, 2, 0) /* sc7280 */
#define IS_MSM8996_TARGET(rev) IS_DPU_MAJOR_MINOR_SAME((rev), DPU_HW_VER_170)
@@ -87,6 +89,7 @@ enum {
DPU_MDP_BWC,
DPU_MDP_UBWC_1_0,
DPU_MDP_UBWC_1_5,
+ DPU_MDP_AUDIO_SELECT,
DPU_MDP_MAX
};
@@ -435,6 +438,8 @@ enum dpu_clk_ctrl_type {
DPU_CLK_CTRL_RGB3,
DPU_CLK_CTRL_DMA0,
DPU_CLK_CTRL_DMA1,
+ DPU_CLK_CTRL_DMA2,
+ DPU_CLK_CTRL_DMA3,
DPU_CLK_CTRL_CURSOR0,
DPU_CLK_CTRL_CURSOR1,
DPU_CLK_CTRL_INLINE_ROT0_SSPP,
@@ -781,22 +786,6 @@ struct dpu_mdss_hw_cfg_handler {
void (*cfg_init)(struct dpu_mdss_cfg *dpu_cfg);
};
-/*
- * Access Macros
- */
-#define BLK_MDP(s) ((s)->mdp)
-#define BLK_CTL(s) ((s)->ctl)
-#define BLK_VIG(s) ((s)->vig)
-#define BLK_RGB(s) ((s)->rgb)
-#define BLK_DMA(s) ((s)->dma)
-#define BLK_CURSOR(s) ((s)->cursor)
-#define BLK_MIXER(s) ((s)->mixer)
-#define BLK_PINGPONG(s) ((s)->pingpong)
-#define BLK_INTF(s) ((s)->intf)
-#define BLK_AD(s) ((s)->ad)
-#define BLK_DSPP(s) ((s)->dspp)
-#define BLK_MERGE3d(s) ((s)->merge_3d)
-
/**
* dpu_hw_catalog_init - dpu hardware catalog init API retrieves
* hardcoded target specific catalog information in config structure
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 02da9ecf71f1..3584f5ee6bb3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -92,6 +92,11 @@ static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);
}
+static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
+{
+ return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
+}
+
static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)
{
trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,
@@ -587,6 +592,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->get_pending_flush = dpu_hw_ctl_get_pending_flush;
ops->get_flush_register = dpu_hw_ctl_get_flush_register;
ops->trigger_start = dpu_hw_ctl_trigger_start;
+ ops->is_started = dpu_hw_ctl_is_started;
ops->trigger_pending = dpu_hw_ctl_trigger_pending;
ops->reset = dpu_hw_ctl_reset_control;
ops->wait_reset_status = dpu_hw_ctl_wait_reset_status;
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 806c171e5df2..ac1544474022 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -62,6 +62,13 @@ struct dpu_hw_ctl_ops {
void (*trigger_start)(struct dpu_hw_ctl *ctx);
/**
+ * check if the ctl is started
+ * @ctx : ctl path ctx pointer
+ * @Return: true if started, false if stopped
+ */
+ bool (*is_started)(struct dpu_hw_ctl *ctx);
+
+ /**
* kickoff prepare is in progress hw operation for sw
* controlled interfaces: DSI cmd mode and WB interface
* are SW controlled
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index a77a5eaa78ad..c515b7cf922c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -13,7 +13,7 @@
#include "dpu_hw_mdss.h"
#include "dpu_trace.h"
-/**
+/*
* Register offsets in MDSS register file for the interrupt registers
* w.r.t. to the MDP base
*/
@@ -23,6 +23,7 @@
#define MDP_INTF_2_OFF 0x6B000
#define MDP_INTF_3_OFF 0x6B800
#define MDP_INTF_4_OFF 0x6C000
+#define MDP_INTF_5_OFF 0x6C800
#define MDP_AD4_0_OFF 0x7C000
#define MDP_AD4_1_OFF 0x7D000
#define MDP_AD4_INTR_EN_OFF 0x41c
@@ -94,6 +95,11 @@ static const struct dpu_intr_reg dpu_intr_set[] = {
MDP_INTF_4_OFF+INTF_INTR_STATUS
},
{
+ MDP_INTF_5_OFF+INTF_INTR_CLEAR,
+ MDP_INTF_5_OFF+INTF_INTR_EN,
+ MDP_INTF_5_OFF+INTF_INTR_STATUS
+ },
+ {
MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF,
MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF,
MDP_AD4_0_OFF + MDP_AD4_INTR_STATUS_OFF,
@@ -140,7 +146,7 @@ static const struct dpu_intr_reg dpu_intr_set[] = {
/**
* dpu_core_irq_callback_handler - dispatch core interrupts
- * @arg: private data of callback handler
+ * @dpu_kms: Pointer to DPU's KMS structure
* @irq_idx: interrupt index
*/
static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 1ab75cccd145..37379966d8ec 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -22,6 +22,7 @@ enum dpu_hw_intr_reg {
MDP_INTF2_INTR,
MDP_INTF3_INTR,
MDP_INTF4_INTR,
+ MDP_INTF5_INTR,
MDP_AD4_0_INTR,
MDP_AD4_1_INTR,
MDP_INTF0_7xxx_INTR,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index 3568be80dab5..230d122fa43b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -78,7 +78,6 @@ struct dpu_hw_intf_ops {
};
struct dpu_hw_intf {
- struct dpu_hw_blk base;
struct dpu_hw_blk_reg_map hw;
/* intf */
@@ -91,16 +90,6 @@ struct dpu_hw_intf {
};
/**
- * to_dpu_hw_intf - convert base object dpu_hw_base to container
- * @hw: Pointer to base hardware block
- * return: Pointer to hardware block container
- */
-static inline struct dpu_hw_intf *to_dpu_hw_intf(struct dpu_hw_blk *hw)
-{
- return container_of(hw, struct dpu_hw_intf, base);
-}
-
-/**
* dpu_hw_intf_init(): Initializes the intf driver for the passed
* interface idx.
* @idx: interface index for which driver object is required
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index 282e3c6c6d48..ab3ef162b666 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -268,7 +268,9 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
ops->get_danger_status = dpu_hw_get_danger_status;
ops->setup_vsync_source = dpu_hw_setup_vsync_source;
ops->get_safe_status = dpu_hw_get_safe_status;
- ops->intf_audio_select = dpu_hw_intf_audio_select;
+
+ if (cap & BIT(DPU_MDP_AUDIO_SELECT))
+ ops->intf_audio_select = dpu_hw_intf_audio_select;
}
static const struct dpu_mdp_cfg *_top_offset(enum dpu_mdp mdp,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 47fe11a84a77..e29796c4f27b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -271,6 +271,10 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
if (!p)
return -EINVAL;
+ /* Only create a set of debugfs for the primary node, ignore render nodes */
+ if (minor->type != DRM_MINOR_PRIMARY)
+ return 0;
+
dev = dpu_kms->dev;
priv = dev->dev_private;
@@ -774,12 +778,6 @@ fail:
return ret;
}
-static long dpu_kms_round_pixclk(struct msm_kms *kms, unsigned long rate,
- struct drm_encoder *encoder)
-{
- return rate;
-}
-
static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
{
int i;
@@ -948,7 +946,6 @@ static const struct msm_kms_funcs kms_funcs = {
.disable_vblank = dpu_kms_disable_vblank,
.check_modified_format = dpu_format_check_modified_format,
.get_format = dpu_get_msm_format,
- .round_pixclk = dpu_kms_round_pixclk,
.destroy = dpu_kms_destroy,
.snapshot = dpu_kms_mdp_snapshot,
#ifdef CONFIG_DEBUG_FS
@@ -998,29 +995,15 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
return 0;
}
-static struct dss_clk *_dpu_kms_get_clk(struct dpu_kms *dpu_kms,
- char *clock_name)
-{
- struct dss_module_power *mp = &dpu_kms->mp;
- int i;
-
- for (i = 0; i < mp->num_clk; i++) {
- if (!strcmp(mp->clk_config[i].clk_name, clock_name))
- return &mp->clk_config[i];
- }
-
- return NULL;
-}
-
u64 dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name)
{
- struct dss_clk *clk;
+ struct clk *clk;
- clk = _dpu_kms_get_clk(dpu_kms, clock_name);
+ clk = msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, clock_name);
if (!clk)
return -EINVAL;
- return clk_get_rate(clk->clk);
+ return clk_get_rate(clk);
}
static int dpu_kms_hw_init(struct msm_kms *kms)
@@ -1043,7 +1026,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
atomic_set(&dpu_kms->bandwidth_ref, 0);
- dpu_kms->mmio = msm_ioremap(dpu_kms->pdev, "mdp", "mdp");
+ dpu_kms->mmio = msm_ioremap(dpu_kms->pdev, "mdp");
if (IS_ERR(dpu_kms->mmio)) {
rc = PTR_ERR(dpu_kms->mmio);
DPU_ERROR("mdp register memory map failed: %d\n", rc);
@@ -1052,20 +1035,20 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
}
DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio);
- dpu_kms->vbif[VBIF_RT] = msm_ioremap(dpu_kms->pdev, "vbif", "vbif");
+ dpu_kms->vbif[VBIF_RT] = msm_ioremap(dpu_kms->pdev, "vbif");
if (IS_ERR(dpu_kms->vbif[VBIF_RT])) {
rc = PTR_ERR(dpu_kms->vbif[VBIF_RT]);
DPU_ERROR("vbif register memory map failed: %d\n", rc);
dpu_kms->vbif[VBIF_RT] = NULL;
goto error;
}
- dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(dpu_kms->pdev, "vbif_nrt", "vbif_nrt");
+ dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(dpu_kms->pdev, "vbif_nrt");
if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) {
dpu_kms->vbif[VBIF_NRT] = NULL;
DPU_DEBUG("VBIF NRT is not defined");
}
- dpu_kms->reg_dma = msm_ioremap_quiet(dpu_kms->pdev, "regdma", "regdma");
+ dpu_kms->reg_dma = msm_ioremap_quiet(dpu_kms->pdev, "regdma");
if (IS_ERR(dpu_kms->reg_dma)) {
dpu_kms->reg_dma = NULL;
DPU_DEBUG("REG_DMA is not defined");
@@ -1132,7 +1115,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
}
rc = dpu_core_perf_init(&dpu_kms->perf, dev, dpu_kms->catalog,
- _dpu_kms_get_clk(dpu_kms, "core"));
+ msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, "core"));
if (rc) {
DPU_ERROR("failed to init perf %d\n", rc);
goto perf_err;
@@ -1219,7 +1202,6 @@ static int dpu_bind(struct device *dev, struct device *master, void *data)
struct platform_device *pdev = to_platform_device(dev);
struct drm_device *ddev = priv->dev;
struct dpu_kms *dpu_kms;
- struct dss_module_power *mp;
int ret = 0;
dpu_kms = devm_kzalloc(&pdev->dev, sizeof(*dpu_kms), GFP_KERNEL);
@@ -1236,12 +1218,12 @@ static int dpu_bind(struct device *dev, struct device *master, void *data)
return ret;
}
- mp = &dpu_kms->mp;
- ret = msm_dss_parse_clock(pdev, mp);
- if (ret) {
+ ret = devm_clk_bulk_get_all(&pdev->dev, &dpu_kms->clocks);
+ if (ret < 0) {
DPU_ERROR("failed to parse clocks, ret=%d\n", ret);
return ret;
}
+ dpu_kms->num_clocks = ret;
platform_set_drvdata(pdev, dpu_kms);
@@ -1265,11 +1247,6 @@ static void dpu_unbind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
- struct dss_module_power *mp = &dpu_kms->mp;
-
- msm_dss_put_clk(mp->clk_config, mp->num_clk);
- devm_kfree(&pdev->dev, mp->clk_config);
- mp->num_clk = 0;
if (dpu_kms->rpm_enabled)
pm_runtime_disable(&pdev->dev);
@@ -1293,21 +1270,18 @@ static int dpu_dev_remove(struct platform_device *pdev)
static int __maybe_unused dpu_runtime_suspend(struct device *dev)
{
- int i, rc = -1;
+ int i;
struct platform_device *pdev = to_platform_device(dev);
struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
- struct dss_module_power *mp = &dpu_kms->mp;
/* Drop the performance state vote */
dev_pm_opp_set_rate(dev, 0);
- rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
- if (rc)
- DPU_ERROR("clock disable failed rc:%d\n", rc);
+ clk_bulk_disable_unprepare(dpu_kms->num_clocks, dpu_kms->clocks);
for (i = 0; i < dpu_kms->num_paths; i++)
icc_set_bw(dpu_kms->path[i], 0, 0);
- return rc;
+ return 0;
}
static int __maybe_unused dpu_runtime_resume(struct device *dev)
@@ -1317,7 +1291,6 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
struct drm_encoder *encoder;
struct drm_device *ddev;
- struct dss_module_power *mp = &dpu_kms->mp;
int i;
ddev = dpu_kms->dev;
@@ -1327,7 +1300,7 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
for (i = 0; i < dpu_kms->num_paths; i++)
icc_set_bw(dpu_kms->path[i], 0, Bps_to_icc(MIN_IB_BW));
- rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
+ rc = clk_bulk_prepare_enable(dpu_kms->num_clocks, dpu_kms->clocks);
if (rc) {
DPU_ERROR("clock enable failed rc:%d\n", rc);
return rc;
@@ -1348,9 +1321,12 @@ static const struct dev_pm_ops dpu_pm_ops = {
};
const struct of_device_id dpu_dt_match[] = {
+ { .compatible = "qcom,msm8998-dpu", },
+ { .compatible = "qcom,qcm2290-dpu", },
{ .compatible = "qcom,sdm845-dpu", },
{ .compatible = "qcom,sc7180-dpu", },
{ .compatible = "qcom,sc7280-dpu", },
+ { .compatible = "qcom,sc8180x-dpu", },
{ .compatible = "qcom,sm8150-dpu", },
{ .compatible = "qcom,sm8250-dpu", },
{}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 2d385b4b7f5e..779e7bd01efd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -21,7 +21,6 @@
#include "dpu_hw_lm.h"
#include "dpu_hw_interrupts.h"
#include "dpu_hw_top.h"
-#include "dpu_io_util.h"
#include "dpu_rm.h"
#include "dpu_core_perf.h"
@@ -113,7 +112,8 @@ struct dpu_kms {
struct platform_device *pdev;
bool rpm_enabled;
- struct dss_module_power mp;
+ struct clk_bulk_data *clocks;
+ size_t num_clocks;
/* reference count bandwidth requests, so we know when we can
* release bandwidth. Each atomic update increments, and frame-
@@ -144,7 +144,6 @@ struct dpu_global_state {
uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
- uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index 131c1f1a869c..b10ca505f9ac 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -29,7 +29,8 @@ struct dpu_irq_controller {
struct dpu_mdss {
struct msm_mdss base;
void __iomem *mmio;
- struct dss_module_power mp;
+ struct clk_bulk_data *clocks;
+ size_t num_clocks;
struct dpu_irq_controller irq_controller;
};
@@ -136,10 +137,9 @@ static void _dpu_mdss_irq_domain_fini(struct dpu_mdss *dpu_mdss)
static int dpu_mdss_enable(struct msm_mdss *mdss)
{
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
- struct dss_module_power *mp = &dpu_mdss->mp;
int ret;
- ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
+ ret = clk_bulk_prepare_enable(dpu_mdss->num_clocks, dpu_mdss->clocks);
if (ret) {
DPU_ERROR("clock enable failed, ret:%d\n", ret);
return ret;
@@ -174,21 +174,16 @@ static int dpu_mdss_enable(struct msm_mdss *mdss)
static int dpu_mdss_disable(struct msm_mdss *mdss)
{
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
- struct dss_module_power *mp = &dpu_mdss->mp;
- int ret;
- ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
- if (ret)
- DPU_ERROR("clock disable failed, ret:%d\n", ret);
+ clk_bulk_disable_unprepare(dpu_mdss->num_clocks, dpu_mdss->clocks);
- return ret;
+ return 0;
}
static void dpu_mdss_destroy(struct msm_mdss *mdss)
{
struct platform_device *pdev = to_platform_device(mdss->dev);
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
- struct dss_module_power *mp = &dpu_mdss->mp;
int irq;
pm_runtime_suspend(mdss->dev);
@@ -196,8 +191,6 @@ static void dpu_mdss_destroy(struct msm_mdss *mdss)
_dpu_mdss_irq_domain_fini(dpu_mdss);
irq = platform_get_irq(pdev, 0);
irq_set_chained_handler_and_data(irq, NULL, NULL);
- msm_dss_put_clk(mp->clk_config, mp->num_clk);
- devm_kfree(&pdev->dev, mp->clk_config);
if (dpu_mdss->mmio)
devm_iounmap(&pdev->dev, dpu_mdss->mmio);
@@ -214,7 +207,6 @@ int dpu_mdss_init(struct platform_device *pdev)
{
struct msm_drm_private *priv = platform_get_drvdata(pdev);
struct dpu_mdss *dpu_mdss;
- struct dss_module_power *mp;
int ret;
int irq;
@@ -222,18 +214,18 @@ int dpu_mdss_init(struct platform_device *pdev)
if (!dpu_mdss)
return -ENOMEM;
- dpu_mdss->mmio = msm_ioremap(pdev, "mdss", "mdss");
+ dpu_mdss->mmio = msm_ioremap(pdev, "mdss");
if (IS_ERR(dpu_mdss->mmio))
return PTR_ERR(dpu_mdss->mmio);
DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio);
- mp = &dpu_mdss->mp;
- ret = msm_dss_parse_clock(pdev, mp);
- if (ret) {
+ ret = devm_clk_bulk_get_all(&pdev->dev, &dpu_mdss->clocks);
+ if (ret < 0) {
DPU_ERROR("failed to parse clocks, ret=%d\n", ret);
goto clk_parse_err;
}
+ dpu_mdss->num_clocks = ret;
dpu_mdss->base.dev = &pdev->dev;
dpu_mdss->base.funcs = &mdss_funcs;
@@ -260,9 +252,7 @@ int dpu_mdss_init(struct platform_device *pdev)
irq_error:
_dpu_mdss_irq_domain_fini(dpu_mdss);
irq_domain_error:
- msm_dss_put_clk(mp->clk_config, mp->num_clk);
clk_parse_err:
- devm_kfree(&pdev->dev, mp->clk_config);
if (dpu_mdss->mmio)
devm_iounmap(&pdev->dev, dpu_mdss->mmio);
dpu_mdss->mmio = NULL;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index ca75089c9d61..6565682fe227 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -902,7 +902,7 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
if (pstate->aspace) {
ret = msm_framebuffer_prepare(new_state->fb,
- pstate->aspace);
+ pstate->aspace, pstate->needs_dirtyfb);
if (ret) {
DPU_ERROR("failed to prepare framebuffer\n");
return ret;
@@ -933,7 +933,8 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane,
DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", old_state->fb->base.id);
- msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
+ msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace,
+ old_pstate->needs_dirtyfb);
}
static bool dpu_plane_validate_src(struct drm_rect *src,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index 9d51dad5c6a5..50781e2d3577 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -25,6 +25,7 @@
* @pending: whether the current update is still pending
* @plane_fetch_bw: calculated BW per plane
* @plane_clk: calculated clk per plane
+ * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed
*/
struct dpu_plane_state {
struct drm_plane_state base;
@@ -37,6 +38,8 @@ struct dpu_plane_state {
u64 plane_fetch_bw;
u64 plane_clk;
+
+ bool needs_dirtyfb;
};
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f9c83d6e427a..7497538adae1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -28,13 +28,20 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
*/
struct dpu_rm_requirements {
struct msm_display_topology topology;
- struct dpu_encoder_hw_resources hw_res;
};
int dpu_rm_destroy(struct dpu_rm *rm)
{
int i;
+ for (i = 0; i < ARRAY_SIZE(rm->dspp_blks); i++) {
+ struct dpu_hw_dspp *hw;
+
+ if (rm->dspp_blks[i]) {
+ hw = to_dpu_hw_dspp(rm->dspp_blks[i]);
+ dpu_hw_dspp_destroy(hw);
+ }
+ }
for (i = 0; i < ARRAY_SIZE(rm->pingpong_blks); i++) {
struct dpu_hw_pingpong *hw;
@@ -67,14 +74,8 @@ int dpu_rm_destroy(struct dpu_rm *rm)
dpu_hw_ctl_destroy(hw);
}
}
- for (i = 0; i < ARRAY_SIZE(rm->intf_blks); i++) {
- struct dpu_hw_intf *hw;
-
- if (rm->intf_blks[i]) {
- hw = to_dpu_hw_intf(rm->intf_blks[i]);
- dpu_hw_intf_destroy(hw);
- }
- }
+ for (i = 0; i < ARRAY_SIZE(rm->hw_intf); i++)
+ dpu_hw_intf_destroy(rm->hw_intf[i]);
return 0;
}
@@ -108,24 +109,12 @@ int dpu_rm_init(struct dpu_rm *rm,
continue;
}
hw = dpu_hw_lm_init(lm->id, mmio, cat);
- if (IS_ERR_OR_NULL(hw)) {
+ if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed lm object creation: err %d\n", rc);
goto fail;
}
rm->mixer_blks[lm->id - LM_0] = &hw->base;
-
- if (!rm->lm_max_width) {
- rm->lm_max_width = lm->sblk->maxwidth;
- } else if (rm->lm_max_width != lm->sblk->maxwidth) {
- /*
- * Don't expect to have hw where lm max widths differ.
- * If found, take the min.
- */
- DPU_ERROR("unsupported: lm maxwidth differs\n");
- if (rm->lm_max_width > lm->sblk->maxwidth)
- rm->lm_max_width = lm->sblk->maxwidth;
- }
}
for (i = 0; i < cat->merge_3d_count; i++) {
@@ -137,7 +126,7 @@ int dpu_rm_init(struct dpu_rm *rm,
continue;
}
hw = dpu_hw_merge_3d_init(merge_3d->id, mmio, cat);
- if (IS_ERR_OR_NULL(hw)) {
+ if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed merge_3d object creation: err %d\n",
rc);
@@ -155,7 +144,7 @@ int dpu_rm_init(struct dpu_rm *rm,
continue;
}
hw = dpu_hw_pingpong_init(pp->id, mmio, cat);
- if (IS_ERR_OR_NULL(hw)) {
+ if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed pingpong object creation: err %d\n",
rc);
@@ -179,12 +168,12 @@ int dpu_rm_init(struct dpu_rm *rm,
continue;
}
hw = dpu_hw_intf_init(intf->id, mmio, cat);
- if (IS_ERR_OR_NULL(hw)) {
+ if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed intf object creation: err %d\n", rc);
goto fail;
}
- rm->intf_blks[intf->id - INTF_0] = &hw->base;
+ rm->hw_intf[intf->id - INTF_0] = hw;
}
for (i = 0; i < cat->ctl_count; i++) {
@@ -196,7 +185,7 @@ int dpu_rm_init(struct dpu_rm *rm,
continue;
}
hw = dpu_hw_ctl_init(ctl->id, mmio, cat);
- if (IS_ERR_OR_NULL(hw)) {
+ if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed ctl object creation: err %d\n", rc);
goto fail;
@@ -213,7 +202,7 @@ int dpu_rm_init(struct dpu_rm *rm,
continue;
}
hw = dpu_hw_dspp_init(dspp->id, mmio, cat);
- if (IS_ERR_OR_NULL(hw)) {
+ if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed dspp object creation: err %d\n", rc);
goto fail;
@@ -452,54 +441,6 @@ static int _dpu_rm_reserve_ctls(
return 0;
}
-static int _dpu_rm_reserve_intf(
- struct dpu_rm *rm,
- struct dpu_global_state *global_state,
- uint32_t enc_id,
- uint32_t id)
-{
- int idx = id - INTF_0;
-
- if (idx < 0 || idx >= ARRAY_SIZE(rm->intf_blks)) {
- DPU_ERROR("invalid intf id: %d", id);
- return -EINVAL;
- }
-
- if (!rm->intf_blks[idx]) {
- DPU_ERROR("couldn't find intf id %d\n", id);
- return -EINVAL;
- }
-
- if (reserved_by_other(global_state->intf_to_enc_id, idx, enc_id)) {
- DPU_ERROR("intf id %d already reserved\n", id);
- return -ENAVAIL;
- }
-
- global_state->intf_to_enc_id[idx] = enc_id;
- return 0;
-}
-
-static int _dpu_rm_reserve_intf_related_hw(
- struct dpu_rm *rm,
- struct dpu_global_state *global_state,
- uint32_t enc_id,
- struct dpu_encoder_hw_resources *hw_res)
-{
- int i, ret = 0;
- u32 id;
-
- for (i = 0; i < ARRAY_SIZE(hw_res->intfs); i++) {
- if (hw_res->intfs[i] == INTF_MODE_NONE)
- continue;
- id = i + INTF_0;
- ret = _dpu_rm_reserve_intf(rm, global_state, enc_id, id);
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
@@ -521,11 +462,6 @@ static int _dpu_rm_make_reservation(
return ret;
}
- ret = _dpu_rm_reserve_intf_related_hw(rm, global_state, enc->base.id,
- &reqs->hw_res);
- if (ret)
- return ret;
-
return ret;
}
@@ -534,8 +470,6 @@ static int _dpu_rm_populate_requirements(
struct dpu_rm_requirements *reqs,
struct msm_display_topology req_topology)
{
- dpu_encoder_get_hw_resources(enc, &reqs->hw_res);
-
reqs->topology = req_topology;
DRM_DEBUG_KMS("num_lm: %d num_enc: %d num_intf: %d\n",
@@ -565,8 +499,6 @@ void dpu_rm_release(struct dpu_global_state *global_state,
ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
_dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->intf_to_enc_id,
- ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
}
int dpu_rm_reserve(
@@ -630,11 +562,6 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
hw_to_enc_id = global_state->ctl_to_enc_id;
max_blks = ARRAY_SIZE(rm->ctl_blks);
break;
- case DPU_HW_BLK_INTF:
- hw_blks = rm->intf_blks;
- hw_to_enc_id = global_state->intf_to_enc_id;
- max_blks = ARRAY_SIZE(rm->intf_blks);
- break;
case DPU_HW_BLK_DSPP:
hw_blks = rm->dspp_blks;
hw_to_enc_id = global_state->dspp_to_enc_id;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 1f12c8d5b8aa..9b13200a050a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -18,20 +18,16 @@ struct dpu_global_state;
* @pingpong_blks: array of pingpong hardware resources
* @mixer_blks: array of layer mixer hardware resources
* @ctl_blks: array of ctl hardware resources
- * @intf_blks: array of intf hardware resources
+ * @hw_intf: array of intf hardware resources
* @dspp_blks: array of dspp hardware resources
- * @lm_max_width: cached layer mixer maximum width
- * @rm_lock: resource manager mutex
*/
struct dpu_rm {
struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0];
struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
- struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
+ struct dpu_hw_intf *hw_intf[INTF_MAX - INTF_0];
struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
-
- uint32_t lm_max_width;
};
/**
@@ -88,5 +84,16 @@ void dpu_rm_release(struct dpu_global_state *global_state,
int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
struct dpu_global_state *global_state, uint32_t enc_id,
enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
+
+/**
+ * dpu_rm_get_intf - Return a struct dpu_hw_intf instance given it's index.
+ * @rm: DPU Resource Manager handle
+ * @intf_idx: INTF's index
+ */
+static inline struct dpu_hw_intf *dpu_rm_get_intf(struct dpu_rm *rm, enum dpu_intf intf_idx)
+{
+ return rm->hw_intf[intf_idx - INTF_0];
+}
+
#endif /* __DPU_RM_H__ */
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 5a33bb148e9e..3cf476c55158 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -418,7 +418,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
mdp4_kms->dev = dev;
- mdp4_kms->mmio = msm_ioremap(pdev, NULL, "MDP4");
+ mdp4_kms->mmio = msm_ioremap(pdev, NULL);
if (IS_ERR(mdp4_kms->mmio)) {
ret = PTR_ERR(mdp4_kms->mmio);
goto fail;
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
index 49bdabea8ed5..3e20f72d75ef 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
@@ -7,6 +7,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_atomic_helper.h>
#include "mdp4_kms.h"
@@ -90,6 +91,20 @@ static const struct drm_plane_funcs mdp4_plane_funcs = {
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
+static int mdp4_plane_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
+{
+ struct msm_drm_private *priv = plane->dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+
+ if (!new_state->fb)
+ return 0;
+
+ drm_gem_plane_helper_prepare_fb(plane, new_state);
+
+ return msm_framebuffer_prepare(new_state->fb, kms->aspace, false);
+}
+
static void mdp4_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -102,7 +117,7 @@ static void mdp4_plane_cleanup_fb(struct drm_plane *plane,
return;
DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id);
- msm_framebuffer_cleanup(fb, kms->aspace);
+ msm_framebuffer_cleanup(fb, kms->aspace, false);
}
@@ -130,7 +145,7 @@ static void mdp4_plane_atomic_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs mdp4_plane_helper_funcs = {
- .prepare_fb = msm_atomic_prepare_fb,
+ .prepare_fb = mdp4_plane_prepare_fb,
.cleanup_fb = mdp4_plane_cleanup_fb,
.atomic_check = mdp4_plane_atomic_check,
.atomic_update = mdp4_plane_atomic_update,
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index bb7d066618e6..b966cd69f99d 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -690,6 +690,8 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
{
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
crtc);
+ struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc_state);
+ struct mdp5_interface *intf = mdp5_cstate->pipeline.intf;
struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct drm_plane *plane;
struct drm_device *dev = crtc->dev;
@@ -706,12 +708,18 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
DBG("%s: check", crtc->name);
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
+ struct mdp5_plane_state *mdp5_pstate =
+ to_mdp5_plane_state(pstate);
+
if (!pstate->visible)
continue;
pstates[cnt].plane = plane;
pstates[cnt].state = to_mdp5_plane_state(pstate);
+ mdp5_pstate->needs_dirtyfb =
+ intf->mode == MDP5_INTF_DSI_MODE_COMMAND;
+
/*
* if any plane on this crtc uses 2 hwpipes, then we need
* the crtc to have a right hwmixer.
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 12a5f81e402b..3b92372e7bdf 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -190,12 +190,6 @@ static void mdp5_complete_commit(struct msm_kms *kms, unsigned crtc_mask)
mdp5_smp_complete_commit(mdp5_kms->smp, &global_state->smp);
}
-static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
- struct drm_encoder *encoder)
-{
- return rate;
-}
-
static int mdp5_set_split_display(struct msm_kms *kms,
struct drm_encoder *encoder,
struct drm_encoder *slave_encoder,
@@ -278,7 +272,6 @@ static const struct mdp_kms_funcs kms_funcs = {
.wait_flush = mdp5_wait_flush,
.complete_commit = mdp5_complete_commit,
.get_format = mdp_get_format,
- .round_pixclk = mdp5_round_pixclk,
.set_split_display = mdp5_set_split_display,
.destroy = mdp5_kms_destroy,
#ifdef CONFIG_DEBUG_FS
@@ -827,7 +820,7 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
if (ret)
goto fail;
- mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5");
+ mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys");
if (IS_ERR(mdp5_kms->mmio)) {
ret = PTR_ERR(mdp5_kms->mmio);
goto fail;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h
index ac269a6802df..29bf11f08601 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h
@@ -100,6 +100,11 @@ struct mdp5_plane_state {
/* assigned by crtc blender */
enum mdp_mixer_stage_id stage;
+
+ /* whether attached CRTC needs pixel data explicitly flushed to
+ * display (ex. DSI command mode display)
+ */
+ bool needs_dirtyfb;
};
#define to_mdp5_plane_state(x) \
container_of(x, struct mdp5_plane_state, base)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
index b3f79c2277e9..049c6784a531 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
@@ -210,13 +210,13 @@ int mdp5_mdss_init(struct platform_device *pdev)
mdp5_mdss->base.dev = &pdev->dev;
- mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS");
+ mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys");
if (IS_ERR(mdp5_mdss->mmio)) {
ret = PTR_ERR(mdp5_mdss->mmio);
goto fail;
}
- mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF");
+ mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys");
if (IS_ERR(mdp5_mdss->vbif)) {
ret = PTR_ERR(mdp5_mdss->vbif);
goto fail;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index 5d8ac84c510b..1ee824600995 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -8,6 +8,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_print.h>
#include "mdp5_kms.h"
@@ -140,18 +141,34 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
.atomic_print_state = mdp5_plane_atomic_print_state,
};
+static int mdp5_plane_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
+{
+ struct msm_drm_private *priv = plane->dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+ bool needs_dirtyfb = to_mdp5_plane_state(new_state)->needs_dirtyfb;
+
+ if (!new_state->fb)
+ return 0;
+
+ drm_gem_plane_helper_prepare_fb(plane, new_state);
+
+ return msm_framebuffer_prepare(new_state->fb, kms->aspace, needs_dirtyfb);
+}
+
static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct msm_kms *kms = &mdp5_kms->base.base;
struct drm_framebuffer *fb = old_state->fb;
+ bool needed_dirtyfb = to_mdp5_plane_state(old_state)->needs_dirtyfb;
if (!fb)
return;
DBG("%s: cleanup: FB[%u]", plane->name, fb->base.id);
- msm_framebuffer_cleanup(fb, kms->aspace);
+ msm_framebuffer_cleanup(fb, kms->aspace, needed_dirtyfb);
}
static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
@@ -437,7 +454,7 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
- .prepare_fb = msm_atomic_prepare_fb,
+ .prepare_fb = mdp5_plane_prepare_fb,
.cleanup_fb = mdp5_plane_cleanup_fb,
.atomic_check = mdp5_plane_atomic_check,
.atomic_update = mdp5_plane_atomic_update,
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index d7fa2c49e741..56a3063545ec 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -68,7 +68,7 @@ static int smp_request_block(struct mdp5_smp *smp,
uint8_t reserved;
/* we shouldn't be requesting blocks for an in-use client: */
- WARN_ON(bitmap_weight(cs, cnt) > 0);
+ WARN_ON(!bitmap_empty(cs, cnt));
reserved = smp->reserved[cid];
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 8a6d3ead3440..fac815fb6d91 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -456,19 +456,19 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0);
}
-int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog,
- u32 pattern)
+int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
+ u32 state_bit)
{
int bit, ret;
u32 data;
struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog);
- bit = BIT(pattern - 1);
- DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, pattern);
+ bit = BIT(state_bit - 1);
+ DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, state_bit);
dp_catalog_ctrl_state_ctrl(dp_catalog, bit);
- bit = BIT(pattern - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;
+ bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;
/* Poll for mainlink ready status */
ret = readx_poll_timeout(readl, catalog->io->dp_controller.link.base +
@@ -476,7 +476,7 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog,
data, data & bit,
POLLING_SLEEP_US, POLLING_TIMEOUT_US);
if (ret < 0) {
- DRM_ERROR("set pattern for link_train=%d failed\n", pattern);
+ DRM_ERROR("set state_bit for link_train=%d failed\n", state_bit);
return ret;
}
return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 6965afa81aad..7dea1012ae66 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -94,7 +94,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
u32 stream_rate_khz, bool fixed_nvid);
-int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, u32 pattern);
+int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 pattern);
void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog);
void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c b/drivers/gpu/drm/msm/dp/dp_clk_util.c
index 078afc5f5882..44a4fc59ff31 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c
+++ b/drivers/gpu/drm/msm/dp/dp_clk_util.c
@@ -11,7 +11,7 @@
#include <drm/drm_print.h>
-#include "dpu_io_util.h"
+#include "dp_clk_util.h"
void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
{
@@ -118,70 +118,3 @@ int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
return rc;
}
-
-int msm_dss_parse_clock(struct platform_device *pdev,
- struct dss_module_power *mp)
-{
- u32 i, rc = 0;
- const char *clock_name;
- int num_clk = 0;
-
- if (!pdev || !mp)
- return -EINVAL;
-
- mp->num_clk = 0;
- num_clk = of_property_count_strings(pdev->dev.of_node, "clock-names");
- if (num_clk <= 0) {
- pr_debug("clocks are not defined\n");
- return 0;
- }
-
- mp->clk_config = devm_kcalloc(&pdev->dev,
- num_clk, sizeof(struct dss_clk),
- GFP_KERNEL);
- if (!mp->clk_config)
- return -ENOMEM;
-
- for (i = 0; i < num_clk; i++) {
- rc = of_property_read_string_index(pdev->dev.of_node,
- "clock-names", i,
- &clock_name);
- if (rc) {
- DRM_DEV_ERROR(&pdev->dev, "Failed to get clock name for %d\n",
- i);
- break;
- }
- strlcpy(mp->clk_config[i].clk_name, clock_name,
- sizeof(mp->clk_config[i].clk_name));
-
- mp->clk_config[i].type = DSS_CLK_AHB;
- }
-
- rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, num_clk);
- if (rc) {
- DRM_DEV_ERROR(&pdev->dev, "Failed to get clock refs %d\n", rc);
- goto err;
- }
-
- rc = of_clk_set_defaults(pdev->dev.of_node, false);
- if (rc) {
- DRM_DEV_ERROR(&pdev->dev, "Failed to set clock defaults %d\n", rc);
- goto err;
- }
-
- for (i = 0; i < num_clk; i++) {
- u32 rate = clk_get_rate(mp->clk_config[i].clk);
- if (!rate)
- continue;
- mp->clk_config[i].rate = rate;
- mp->clk_config[i].type = DSS_CLK_PCLK;
- mp->clk_config[i].max_rate = rate;
- }
-
- mp->num_clk = num_clk;
- return 0;
-
-err:
- msm_dss_put_clk(mp->clk_config, num_clk);
- return rc;
-}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h b/drivers/gpu/drm/msm/dp/dp_clk_util.h
index e6b5c772fa3b..067bf87f3d97 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h
+++ b/drivers/gpu/drm/msm/dp/dp_clk_util.h
@@ -2,8 +2,8 @@
/* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved.
*/
-#ifndef __DPU_IO_UTIL_H__
-#define __DPU_IO_UTIL_H__
+#ifndef __DP_CLK_UTIL_H__
+#define __DP_CLK_UTIL_H__
#include <linux/platform_device.h>
#include <linux/types.h>
@@ -35,6 +35,4 @@ int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk);
void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk);
int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk);
int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable);
-int msm_dss_parse_clock(struct platform_device *pdev,
- struct dss_module_power *mp);
-#endif /* __DPU_IO_UTIL_H__ */
+#endif /* __DP_CLK_UTIL_H__ */
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 88ca6c3aedd3..53568567e05b 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1083,7 +1083,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
*training_step = DP_TRAINING_1;
- ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, DP_TRAINING_PATTERN_1);
+ ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, 1);
if (ret)
return ret;
dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
@@ -1181,7 +1181,8 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
int *training_step)
{
int tries = 0, ret = 0;
- char pattern;
+ u8 pattern;
+ u32 state_ctrl_bit;
int const maximum_retries = 5;
u8 link_status[DP_LINK_STATUS_SIZE];
@@ -1189,12 +1190,18 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
*training_step = DP_TRAINING_2;
- if (drm_dp_tps3_supported(ctrl->panel->dpcd))
+ if (drm_dp_tps4_supported(ctrl->panel->dpcd)) {
+ pattern = DP_TRAINING_PATTERN_4;
+ state_ctrl_bit = 4;
+ } else if (drm_dp_tps3_supported(ctrl->panel->dpcd)) {
pattern = DP_TRAINING_PATTERN_3;
- else
+ state_ctrl_bit = 3;
+ } else {
pattern = DP_TRAINING_PATTERN_2;
+ state_ctrl_bit = 2;
+ }
- ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, pattern);
+ ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit);
if (ret)
return ret;
@@ -1365,60 +1372,48 @@ static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl)
return ret;
}
-int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset)
+void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable)
+{
+ struct dp_ctrl_private *ctrl;
+
+ ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+ dp_catalog_ctrl_reset(ctrl->catalog);
+
+ if (enable)
+ dp_catalog_ctrl_enable_irq(ctrl->catalog, enable);
+}
+
+void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl)
{
struct dp_ctrl_private *ctrl;
struct dp_io *dp_io;
struct phy *phy;
- if (!dp_ctrl) {
- DRM_ERROR("Invalid input data\n");
- return -EINVAL;
- }
-
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
dp_io = &ctrl->parser->io;
phy = dp_io->phy;
- ctrl->dp_ctrl.orientation = flip;
-
- if (reset)
- dp_catalog_ctrl_reset(ctrl->catalog);
-
- DRM_DEBUG_DP("flip=%d\n", flip);
dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_init(phy);
- dp_catalog_ctrl_enable_irq(ctrl->catalog, true);
-
- return 0;
+ DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n",
+ phy, phy->init_count, phy->power_count);
}
-/**
- * dp_ctrl_host_deinit() - Uninitialize DP controller
- * @dp_ctrl: Display Port Driver data
- *
- * Perform required steps to uninitialize DP controller
- * and its resources.
- */
-void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
+void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl)
{
struct dp_ctrl_private *ctrl;
struct dp_io *dp_io;
struct phy *phy;
- if (!dp_ctrl) {
- DRM_ERROR("Invalid input data\n");
- return;
- }
-
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
dp_io = &ctrl->parser->io;
phy = dp_io->phy;
- dp_catalog_ctrl_enable_irq(ctrl->catalog, false);
+ dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_exit(phy);
-
- DRM_DEBUG_DP("Host deinitialized successfully\n");
+ DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n",
+ phy, phy->init_count, phy->power_count);
}
static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl)
@@ -1488,8 +1483,13 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl)
}
phy_power_off(phy);
+
+ /* aux channel down, reinit phy */
phy_exit(phy);
+ phy_init(phy);
+ DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n",
+ phy, phy->init_count, phy->power_count);
return 0;
}
@@ -1761,6 +1761,9 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
/* end with failure */
break; /* lane == 1 already */
}
+
+ /* stop link training before start re training */
+ dp_ctrl_clear_training_pattern(ctrl);
}
}
@@ -1893,33 +1896,20 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
return ret;
}
+ DRM_DEBUG_DP("Before, phy=%x init_count=%d power_on=%d\n",
+ (u32)(uintptr_t)phy, phy->init_count, phy->power_count);
+
phy_power_off(phy);
/* aux channel down, reinit phy */
phy_exit(phy);
phy_init(phy);
- DRM_DEBUG_DP("DP off link/stream done\n");
+ DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n",
+ phy, phy->init_count, phy->power_count);
return ret;
}
-void dp_ctrl_off_phy(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
- struct dp_io *dp_io;
- struct phy *phy;
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
- dp_io = &ctrl->parser->io;
- phy = dp_io->phy;
-
- dp_catalog_ctrl_reset(ctrl->catalog);
-
- phy_exit(phy);
-
- DRM_DEBUG_DP("DP off phy done\n");
-}
-
int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
{
struct dp_ctrl_private *ctrl;
@@ -1948,9 +1938,9 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
}
phy_power_off(phy);
- phy_exit(phy);
+ DRM_DEBUG_DP("phy=%p init=%d power_on=%d\n",
+ phy, phy->init_count, phy->power_count);
- DRM_DEBUG_DP("DP off done\n");
return ret;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 2363a2df9597..2433edbc70a6 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -19,12 +19,9 @@ struct dp_ctrl {
u32 pixel_rate;
};
-int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
-void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl);
int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl);
int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl);
int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_off_phy(struct dp_ctrl *dp_ctrl);
int dp_ctrl_off(struct dp_ctrl *dp_ctrl);
void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl);
void dp_ctrl_isr(struct dp_ctrl *dp_ctrl);
@@ -34,4 +31,9 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link,
struct dp_power *power, struct dp_catalog *catalog,
struct dp_parser *parser);
+void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable);
+void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl);
+void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl);
+void dp_ctrl_irq_phy_exit(struct dp_ctrl *dp_ctrl);
+
#endif /* _DP_CTRL_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index da4323556ef3..2f9c943f12d5 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -207,39 +207,39 @@ static const struct file_operations test_active_fops = {
.write = dp_test_active_write
};
-static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor)
+static void dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor)
{
- int rc = 0;
+ char path[64];
struct dp_debug_private *debug = container_of(dp_debug,
struct dp_debug_private, dp_debug);
- debugfs_create_file("dp_debug", 0444, minor->debugfs_root,
+ snprintf(path, sizeof(path), "msm_dp-%s", debug->connector->name);
+
+ debug->root = debugfs_create_dir(path, minor->debugfs_root);
+
+ debugfs_create_file("dp_debug", 0444, debug->root,
debug, &dp_debug_fops);
debugfs_create_file("msm_dp_test_active", 0444,
- minor->debugfs_root,
+ debug->root,
debug, &test_active_fops);
debugfs_create_file("msm_dp_test_data", 0444,
- minor->debugfs_root,
+ debug->root,
debug, &dp_test_data_fops);
debugfs_create_file("msm_dp_test_type", 0444,
- minor->debugfs_root,
+ debug->root,
debug, &dp_test_type_fops);
-
- debug->root = minor->debugfs_root;
-
- return rc;
}
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
struct dp_usbpd *usbpd, struct dp_link *link,
struct drm_connector *connector, struct drm_minor *minor)
{
- int rc = 0;
struct dp_debug_private *debug;
struct dp_debug *dp_debug;
+ int rc;
if (!dev || !panel || !usbpd || !link) {
DRM_ERROR("invalid input\n");
@@ -266,11 +266,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
dp_debug->hdisplay = 0;
dp_debug->vrefresh = 0;
- rc = dp_debug_init(dp_debug, minor);
- if (rc) {
- devm_kfree(dev, debug);
- goto error;
- }
+ dp_debug_init(dp_debug, minor);
return dp_debug;
error:
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 7cc4d21f2091..178b774a5fbd 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -83,6 +83,7 @@ struct dp_display_private {
/* state variables */
bool core_initialized;
+ bool phy_initialized;
bool hpd_irq_on;
bool audio_supported;
@@ -143,10 +144,29 @@ static const struct msm_dp_config sc7280_dp_cfg = {
.num_descs = 2,
};
+static const struct msm_dp_config sc8180x_dp_cfg = {
+ .descs = (const struct msm_dp_desc[]) {
+ [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+ [MSM_DP_CONTROLLER_1] = { .io_start = 0x0ae98000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+ [MSM_DP_CONTROLLER_2] = { .io_start = 0x0ae9a000, .connector_type = DRM_MODE_CONNECTOR_eDP },
+ },
+ .num_descs = 3,
+};
+
+static const struct msm_dp_config sm8350_dp_cfg = {
+ .descs = (const struct msm_dp_desc[]) {
+ [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+ },
+ .num_descs = 1,
+};
+
static const struct of_device_id dp_dt_match[] = {
{ .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_cfg },
{ .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_cfg },
{ .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_cfg },
+ { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_cfg },
+ { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_cfg },
+ { .compatible = "qcom,sm8350-dp", .data = &sm8350_dp_cfg },
{}
};
@@ -246,7 +266,7 @@ static int dp_display_bind(struct device *dev, struct device *master,
goto end;
}
- dp->dp_display.panel_bridge = dp->parser->panel_bridge;
+ dp->dp_display.next_bridge = dp->parser->next_bridge;
dp->aux->drm_dev = drm;
rc = dp_aux_register(dp->aux);
@@ -372,36 +392,51 @@ end:
return rc;
}
-static void dp_display_host_init(struct dp_display_private *dp, int reset)
+static void dp_display_host_phy_init(struct dp_display_private *dp)
{
- bool flip = false;
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
- DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized);
- if (dp->core_initialized) {
- DRM_DEBUG_DP("DP core already initialized\n");
- return;
+ if (!dp->phy_initialized) {
+ dp_ctrl_phy_init(dp->ctrl);
+ dp->phy_initialized = true;
+ }
+}
+
+static void dp_display_host_phy_exit(struct dp_display_private *dp)
+{
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
+
+ if (dp->phy_initialized) {
+ dp_ctrl_phy_exit(dp->ctrl);
+ dp->phy_initialized = false;
}
+}
- if (dp->usbpd->orientation == ORIENTATION_CC2)
- flip = true;
+static void dp_display_host_init(struct dp_display_private *dp)
+{
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
- dp_power_init(dp->power, flip);
- dp_ctrl_host_init(dp->ctrl, flip, reset);
+ dp_power_init(dp->power, false);
+ dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
dp_aux_init(dp->aux);
dp->core_initialized = true;
}
static void dp_display_host_deinit(struct dp_display_private *dp)
{
- if (!dp->core_initialized) {
- DRM_DEBUG_DP("DP core not initialized\n");
- return;
- }
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
- dp_ctrl_host_deinit(dp->ctrl);
+ dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
dp_aux_deinit(dp->aux);
dp_power_deinit(dp->power);
-
dp->core_initialized = false;
}
@@ -409,7 +444,7 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
{
struct dp_display_private *dp = dev_get_dp_display_private(dev);
- dp_display_host_init(dp, false);
+ dp_display_host_phy_init(dp);
return dp_display_process_hpd_high(dp);
}
@@ -507,7 +542,9 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
- DRM_DEBUG_DP("hpd_state=%d\n", state);
+ DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -530,11 +567,6 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
ret = dp_display_usbpd_configure_cb(&dp->pdev->dev);
if (ret) { /* link train failed */
dp->hpd_state = ST_DISCONNECTED;
-
- if (ret == -ECONNRESET) { /* cable unplugged */
- dp->core_initialized = false;
- }
-
} else {
/* start sentinel checking in case of missing uevent */
dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout);
@@ -544,6 +576,8 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
dp_catalog_hpd_config_intr(dp->catalog,
DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true);
+ DRM_DEBUG_DP("After, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
mutex_unlock(&dp->event_mutex);
/* uevent will complete connection part */
@@ -560,8 +594,10 @@ static int dp_connect_pending_timeout(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
- if (state == ST_CONNECT_PENDING)
+ if (state == ST_CONNECT_PENDING) {
dp->hpd_state = ST_CONNECTED;
+ DRM_DEBUG_DP("type=%d\n", dp->dp_display.connector_type);
+ }
mutex_unlock(&dp->event_mutex);
@@ -594,6 +630,9 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
state = dp->hpd_state;
+ DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
/* disable irq_hpd/replug interrupts */
dp_catalog_hpd_config_intr(dp->catalog,
DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, false);
@@ -604,8 +643,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
if (state == ST_DISCONNECTED) {
/* triggered by irq_hdp with sink_count = 0 */
if (dp->link->sink_count == 0) {
- dp_ctrl_off_phy(dp->ctrl);
- dp->core_initialized = false;
+ dp_display_host_phy_exit(dp);
}
mutex_unlock(&dp->event_mutex);
return 0;
@@ -637,13 +675,15 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
/* start sentinel checking in case of missing uevent */
dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
- DRM_DEBUG_DP("hpd_state=%d\n", state);
/* signal the disconnect event early to ensure proper teardown */
dp_display_handle_plugged_change(&dp->dp_display, false);
/* enable HDP plug interrupt to prepare for next plugin */
dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true);
+ DRM_DEBUG_DP("After, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
/* uevent will complete disconnection part */
mutex_unlock(&dp->event_mutex);
return 0;
@@ -656,8 +696,10 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
- if (state == ST_DISCONNECT_PENDING)
+ if (state == ST_DISCONNECT_PENDING) {
dp->hpd_state = ST_DISCONNECTED;
+ DRM_DEBUG_DP("type=%d\n", dp->dp_display.connector_type);
+ }
mutex_unlock(&dp->event_mutex);
@@ -667,12 +709,14 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data
static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
{
u32 state;
- int ret;
mutex_lock(&dp->event_mutex);
/* irq_hpd can happen at either connected or disconnected state */
state = dp->hpd_state;
+ DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -692,17 +736,10 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
return 0;
}
- /*
- * dp core (ahb/aux clks) must be initialized before
- * irq_hpd be handled
- */
- if (dp->core_initialized) {
- ret = dp_display_usbpd_attention_cb(&dp->pdev->dev);
- if (ret == -ECONNRESET) { /* cable unplugged */
- dp->core_initialized = false;
- }
- }
- DRM_DEBUG_DP("hpd_state=%d\n", state);
+ dp_display_usbpd_attention_cb(&dp->pdev->dev);
+
+ DRM_DEBUG_DP("After, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
mutex_unlock(&dp->event_mutex);
@@ -892,12 +929,19 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data)
dp_display->audio_enabled = false;
- /* triggered by irq_hpd with sink_count = 0 */
if (dp->link->sink_count == 0) {
+ /*
+ * irq_hpd with sink_count = 0
+ * hdmi unplugged out of dongle
+ */
dp_ctrl_off_link_stream(dp->ctrl);
} else {
+ /*
+ * unplugged interrupt
+ * dongle unplugged out of DUT
+ */
dp_ctrl_off(dp->ctrl);
- dp->core_initialized = false;
+ dp_display_host_phy_exit(dp);
}
dp_display->power_on = false;
@@ -1027,7 +1071,7 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
static void dp_display_config_hpd(struct dp_display_private *dp)
{
- dp_display_host_init(dp, true);
+ dp_display_host_init(dp);
dp_catalog_ctrl_hpd_config(dp->catalog);
/* Enable interrupt first time
@@ -1145,8 +1189,9 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog);
- DRM_DEBUG_DP("hpd isr status=%#x\n", hpd_isr_status);
if (hpd_isr_status & 0x0F) {
+ DRM_DEBUG_DP("type=%d isr=0x%x\n",
+ dp->dp_display.connector_type, hpd_isr_status);
/* hpd related interrupts */
if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK)
dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
@@ -1299,27 +1344,31 @@ static int dp_pm_resume(struct device *dev)
mutex_lock(&dp->event_mutex);
- DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n",
- dp->core_initialized, dp_display->power_on);
+ DRM_DEBUG_DP("Before, type=%d core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
/* start from disconnected state */
dp->hpd_state = ST_DISCONNECTED;
/* turn on dp ctrl/phy */
- dp_display_host_init(dp, true);
+ dp_display_host_init(dp);
dp_catalog_ctrl_hpd_config(dp->catalog);
- /*
- * set sink to normal operation mode -- D0
- * before dpcd read
- */
- dp_link_psm_config(dp->link, &dp->panel->link_info, false);
if (dp_catalog_link_is_connected(dp->catalog)) {
+ /*
+ * set sink to normal operation mode -- D0
+ * before dpcd read
+ */
+ dp_display_host_phy_init(dp);
+ dp_link_psm_config(dp->link, &dp->panel->link_info, false);
sink_count = drm_dp_read_sink_count(dp->aux);
if (sink_count < 0)
sink_count = 0;
+
+ dp_display_host_phy_exit(dp);
}
dp->link->sink_count = sink_count;
@@ -1336,9 +1385,11 @@ static int dp_pm_resume(struct device *dev)
dp_display_handle_plugged_change(dp_display, false);
}
- DRM_DEBUG_DP("After, sink_count=%d is_connected=%d core_inited=%d power_on=%d\n",
- dp->link->sink_count, dp->dp_display.is_connected,
- dp->core_initialized, dp_display->power_on);
+ DRM_DEBUG_DP("After, type=%d sink_count=%d is_connected=%d \
+ core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->link->sink_count,
+ dp->dp_display.is_connected, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
mutex_unlock(&dp->event_mutex);
@@ -1355,24 +1406,24 @@ static int dp_pm_suspend(struct device *dev)
mutex_lock(&dp->event_mutex);
- DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n",
- dp->core_initialized, dp_display->power_on);
-
- if (dp->core_initialized == true) {
- /* mainlink enabled */
- if (dp_power_clk_status(dp->power, DP_CTRL_PM))
- dp_ctrl_off_link_stream(dp->ctrl);
+ DRM_DEBUG_DP("Before, type=%d core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
- dp_display_host_deinit(dp);
- }
+ /* mainlink enabled */
+ if (dp_power_clk_status(dp->power, DP_CTRL_PM))
+ dp_ctrl_off_link_stream(dp->ctrl);
- dp->hpd_state = ST_SUSPENDED;
+ dp_display_host_phy_exit(dp);
/* host_init will be called at pm_resume */
- dp->core_initialized = false;
+ dp_display_host_deinit(dp);
+
+ dp->hpd_state = ST_SUSPENDED;
- DRM_DEBUG_DP("After, core_inited=%d power_on=%d\n",
- dp->core_initialized, dp_display->power_on);
+ DRM_DEBUG_DP("After, type=%d core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
mutex_unlock(&dp->event_mutex);
@@ -1460,6 +1511,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
struct drm_encoder *encoder)
{
struct msm_drm_private *priv;
+ struct dp_display_private *dp_priv;
int ret;
if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev))
@@ -1468,6 +1520,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
priv = dev->dev_private;
dp_display->drm_dev = dev;
+ dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
+
ret = dp_display_request_irq(dp_display);
if (ret) {
DRM_ERROR("request_irq failed, ret=%d\n", ret);
@@ -1485,6 +1539,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
return ret;
}
+ dp_priv->panel->connector = dp_display->connector;
+
priv->connectors[priv->num_connectors++] = dp_display->connector;
dp_display->bridge = msm_dp_bridge_init(dp_display, dev, encoder);
@@ -1535,7 +1591,7 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
state = dp_display->hpd_state;
if (state == ST_DISPLAY_OFF)
- dp_display_host_init(dp_display, true);
+ dp_display_host_phy_init(dp_display);
dp_display_enable(dp_display, 0);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index e3adcd578a90..7af2b186d2d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -16,7 +16,7 @@ struct msm_dp {
struct drm_bridge *bridge;
struct drm_connector *connector;
struct drm_encoder *encoder;
- struct drm_bridge *panel_bridge;
+ struct drm_bridge *next_bridge;
bool is_connected;
bool audio_enabled;
bool power_on;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index d4d360d19eba..80f59cf99089 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -169,16 +169,6 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display)
drm_connector_attach_encoder(connector, dp_display->encoder);
- if (dp_display->panel_bridge) {
- ret = drm_bridge_attach(dp_display->encoder,
- dp_display->panel_bridge, NULL,
- DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- if (ret < 0) {
- DRM_ERROR("failed to attach panel bridge: %d\n", ret);
- return ERR_PTR(ret);
- }
- }
-
return connector;
}
@@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct msm_dp *dp_display, struct drm_devi
return ERR_PTR(rc);
}
+ if (dp_display->next_bridge) {
+ rc = drm_bridge_attach(dp_display->encoder,
+ dp_display->next_bridge, bridge,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (rc < 0) {
+ DRM_ERROR("failed to attach panel bridge: %d\n", rc);
+ drm_bridge_remove(bridge);
+ return ERR_PTR(rc);
+ }
+ }
+
return bridge;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 71db10c0f262..f1418722c549 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -212,6 +212,11 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
if (drm_add_modes_noedid(connector, 640, 480))
drm_set_preferred_mode(connector, 640, 480);
mutex_unlock(&connector->dev->mode_config.mutex);
+ } else {
+ /* always add fail-safe mode as backup mode */
+ mutex_lock(&connector->dev->mode_config.mutex);
+ drm_add_modes_noedid(connector, 640, 480);
+ mutex_unlock(&connector->dev->mode_config.mutex);
}
if (panel->aux_cfg_update_done) {
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c
index a7acc23f742b..1056b8d5755b 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.c
+++ b/drivers/gpu/drm/msm/dp/dp_parser.c
@@ -265,23 +265,16 @@ static int dp_parser_clock(struct dp_parser *parser)
return 0;
}
-static int dp_parser_find_panel(struct dp_parser *parser)
+static int dp_parser_find_next_bridge(struct dp_parser *parser)
{
struct device *dev = &parser->pdev->dev;
- struct drm_panel *panel;
- int rc;
+ struct drm_bridge *bridge;
- rc = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
- if (rc) {
- DRM_ERROR("failed to acquire DRM panel: %d\n", rc);
- return rc;
- }
+ bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
+ if (IS_ERR(bridge))
+ return PTR_ERR(bridge);
- parser->panel_bridge = devm_drm_panel_bridge_add(dev, panel);
- if (IS_ERR(parser->panel_bridge)) {
- DRM_ERROR("failed to create panel bridge\n");
- return PTR_ERR(parser->panel_bridge);
- }
+ parser->next_bridge = bridge;
return 0;
}
@@ -307,10 +300,23 @@ static int dp_parser_parse(struct dp_parser *parser, int connector_type)
if (rc)
return rc;
- if (connector_type == DRM_MODE_CONNECTOR_eDP) {
- rc = dp_parser_find_panel(parser);
- if (rc)
+ /*
+ * External bridges are mandatory for eDP interfaces: one has to
+ * provide at least an eDP panel (which gets wrapped into panel-bridge).
+ *
+ * For DisplayPort interfaces external bridges are optional, so
+ * silently ignore an error if one is not present (-ENODEV).
+ */
+ rc = dp_parser_find_next_bridge(parser);
+ if (rc == -ENODEV) {
+ if (connector_type == DRM_MODE_CONNECTOR_eDP) {
+ DRM_ERROR("eDP: next bridge is not present\n");
return rc;
+ }
+ } else if (rc) {
+ if (rc != -EPROBE_DEFER)
+ DRM_ERROR("DP: error parsing next bridge: %d\n", rc);
+ return rc;
}
/* Map the corresponding regulator information according to
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h
index 3172da089421..d371bae1c968 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.h
+++ b/drivers/gpu/drm/msm/dp/dp_parser.h
@@ -10,7 +10,7 @@
#include <linux/phy/phy.h>
#include <linux/phy/phy-dp.h>
-#include "dpu_io_util.h"
+#include "dp_clk_util.h"
#include "msm_drv.h"
#define DP_LABEL "MDSS DP DISPLAY"
@@ -123,7 +123,7 @@ struct dp_parser {
struct dp_display_data disp_data;
const struct dp_regulator_cfg *regulator_cfg;
u32 max_dp_lanes;
- struct drm_bridge *panel_bridge;
+ struct drm_bridge *next_bridge;
int (*parse)(struct dp_parser *parser, int connector_type);
};
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 0fe02529b5e7..c12e66aa42a3 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -4,6 +4,7 @@
*/
#include "dsi.h"
+#include "dsi_cfg.h"
struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
{
@@ -175,7 +176,8 @@ static int dsi_dev_remove(struct platform_device *pdev)
}
static const struct of_device_id dt_match[] = {
- { .compatible = "qcom,mdss-dsi-ctrl" },
+ { .compatible = "qcom,mdss-dsi-ctrl", .data = NULL /* autodetect cfg */ },
+ { .compatible = "qcom,dsi-ctrl-6g-qcm2290", .data = &qcm2290_dsi_cfg_handler },
{}
};
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 96bbc8b6d009..2c23324a2296 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -213,6 +213,24 @@ static const struct msm_dsi_config sc7280_dsi_cfg = {
.num_dsi = 1,
};
+static const char * const dsi_qcm2290_bus_clk_names[] = {
+ "iface", "bus",
+};
+
+static const struct msm_dsi_config qcm2290_dsi_cfg = {
+ .io_offset = DSI_6G_REG_SHIFT,
+ .reg_cfg = {
+ .num = 1,
+ .regs = {
+ {"vdda", 21800, 4 }, /* 1.2 V */
+ },
+ },
+ .bus_clk_names = dsi_qcm2290_bus_clk_names,
+ .num_bus_clks = ARRAY_SIZE(dsi_qcm2290_bus_clk_names),
+ .io_start = { 0x5e94000 },
+ .num_dsi = 1,
+};
+
static const struct msm_dsi_host_cfg_ops msm_dsi_v2_host_ops = {
.link_clk_set_rate = dsi_link_clk_set_rate_v2,
.link_clk_enable = dsi_link_clk_enable_v2,
@@ -300,3 +318,8 @@ const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor)
return cfg_hnd;
}
+/* Non autodetect configs */
+const struct msm_dsi_cfg_handler qcm2290_dsi_cfg_handler = {
+ .cfg = &qcm2290_dsi_cfg,
+ .ops = &msm_dsi_6g_v2_host_ops,
+};
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 41e99a9fb5de..fe54a999968b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -60,5 +60,8 @@ struct msm_dsi_cfg_handler {
const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor);
+/* Non autodetect configs */
+extern const struct msm_dsi_cfg_handler qcm2290_dsi_cfg_handler;
+
#endif /* __MSM_DSI_CFG_H__ */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 6b3ced4aaaf5..d51e70fab93d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -212,6 +212,10 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
int ret;
u32 major = 0, minor = 0;
+ cfg_hnd = device_get_match_data(dev);
+ if (cfg_hnd)
+ return cfg_hnd;
+
ahb_clk = msm_clk_get(msm_host->pdev, "iface");
if (IS_ERR(ahb_clk)) {
pr_err("%s: cannot get interface clock\n", __func__);
@@ -1813,7 +1817,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
goto fail;
}
- msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", "DSI CTRL", &msm_host->ctrl_size);
+ msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", &msm_host->ctrl_size);
if (IS_ERR(msm_host->ctrl_base)) {
pr_err("%s: unable to map Dsi ctrl base\n", __func__);
ret = PTR_ERR(msm_host->ctrl_base);
@@ -1877,7 +1881,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
/* do not autoenable, will be enabled later */
ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
"dsi_isr", msm_host);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request IRQ%u: %d\n",
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index f19bae475c96..0c1b7dde377c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -305,27 +305,6 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
return num;
}
-static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- int id = dsi_mgr_connector_get_id(connector);
- struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
- struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi);
- struct msm_drm_private *priv = connector->dev->dev_private;
- struct msm_kms *kms = priv->kms;
- long actual, requested;
-
- DBG("");
- requested = 1000 * mode->clock;
- actual = kms->funcs->round_pixclk(kms, requested, encoder);
-
- DBG("requested=%ld, actual=%ld", requested, actual);
- if (actual != requested)
- return MODE_CLOCK_RANGE;
-
- return MODE_OK;
-}
-
static struct drm_encoder *
dsi_mgr_connector_best_encoder(struct drm_connector *connector)
{
@@ -336,13 +315,12 @@ dsi_mgr_connector_best_encoder(struct drm_connector *connector)
return msm_dsi_get_encoder(msm_dsi);
}
-static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
+static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
{
int id = dsi_mgr_bridge_get_id(bridge);
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
struct mipi_dsi_host *host = msm_dsi->host;
- struct drm_panel *panel = msm_dsi->panel;
struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
bool is_bonded_dsi = IS_BONDED_DSI();
int ret;
@@ -383,6 +361,34 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
if (is_bonded_dsi && msm_dsi1)
msm_dsi_host_enable_irq(msm_dsi1->host);
+ return;
+
+host1_on_fail:
+ msm_dsi_host_power_off(host);
+host_on_fail:
+ dsi_mgr_phy_disable(id);
+phy_en_fail:
+ return;
+}
+
+static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
+{
+ int id = dsi_mgr_bridge_get_id(bridge);
+ struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+ struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
+ struct mipi_dsi_host *host = msm_dsi->host;
+ struct drm_panel *panel = msm_dsi->panel;
+ bool is_bonded_dsi = IS_BONDED_DSI();
+ int ret;
+
+ DBG("id=%d", id);
+ if (!msm_dsi_device_connected(msm_dsi))
+ return;
+
+ /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
+ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
+ return;
+
/* Always call panel functions once, because even for dual panels,
* there is only one drm_panel instance.
*/
@@ -417,17 +423,7 @@ host_en_fail:
if (panel)
drm_panel_unprepare(panel);
panel_prep_fail:
- msm_dsi_host_disable_irq(host);
- if (is_bonded_dsi && msm_dsi1)
- msm_dsi_host_disable_irq(msm_dsi1->host);
- if (is_bonded_dsi && msm_dsi1)
- msm_dsi_host_power_off(msm_dsi1->host);
-host1_on_fail:
- msm_dsi_host_power_off(host);
-host_on_fail:
- dsi_mgr_phy_disable(id);
-phy_en_fail:
return;
}
@@ -573,6 +569,8 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
msm_dsi_host_set_display_mode(host, adjusted_mode);
if (is_bonded_dsi && other_dsi)
msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
+
+ dsi_mgr_bridge_power_on(bridge);
}
static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
@@ -586,7 +584,6 @@ static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
static const struct drm_connector_helper_funcs dsi_mgr_conn_helper_funcs = {
.get_modes = dsi_mgr_connector_get_modes,
- .mode_valid = dsi_mgr_connector_mode_valid,
.best_encoder = dsi_mgr_connector_best_encoder,
};
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 2027b38617ab..a39de3bdc7fa 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -709,14 +709,14 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
if (!of_property_read_u32(dev->of_node, "phy-type", &phy_type))
phy->cphy_mode = (phy_type == PHY_TYPE_CPHY);
- phy->base = msm_ioremap_size(pdev, "dsi_phy", "DSI_PHY", &phy->base_size);
+ phy->base = msm_ioremap_size(pdev, "dsi_phy", &phy->base_size);
if (IS_ERR(phy->base)) {
DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__);
ret = -ENOMEM;
goto fail;
}
- phy->pll_base = msm_ioremap_size(pdev, "dsi_pll", "DSI_PLL", &phy->pll_size);
+ phy->pll_base = msm_ioremap_size(pdev, "dsi_pll", &phy->pll_size);
if (IS_ERR(phy->pll_base)) {
DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);
ret = -ENOMEM;
@@ -724,7 +724,7 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
}
if (phy->cfg->has_phy_lane) {
- phy->lane_base = msm_ioremap_size(pdev, "dsi_phy_lane", "DSI_PHY_LANE", &phy->lane_size);
+ phy->lane_base = msm_ioremap_size(pdev, "dsi_phy_lane", &phy->lane_size);
if (IS_ERR(phy->lane_base)) {
DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy lane base\n", __func__);
ret = -ENOMEM;
@@ -733,7 +733,7 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
}
if (phy->cfg->has_phy_regulator) {
- phy->reg_base = msm_ioremap_size(pdev, "dsi_phy_regulator", "DSI_PHY_REG", &phy->reg_size);
+ phy->reg_base = msm_ioremap_size(pdev, "dsi_phy_regulator", &phy->reg_size);
if (IS_ERR(phy->reg_base)) {
DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy regulator base\n", __func__);
ret = -ENOMEM;
@@ -741,6 +741,12 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
}
}
+ if (phy->cfg->ops.parse_dt_properties) {
+ ret = phy->cfg->ops.parse_dt_properties(phy);
+ if (ret)
+ goto fail;
+ }
+
ret = dsi_phy_regulator_init(phy);
if (ret)
goto fail;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 4c8257581bfc..dc91b43d5a38 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -25,6 +25,7 @@ struct msm_dsi_phy_ops {
void (*save_pll_state)(struct msm_dsi_phy *phy);
int (*restore_pll_state)(struct msm_dsi_phy *phy);
bool (*set_continuous_clock)(struct msm_dsi_phy *phy, bool enable);
+ int (*parse_dt_properties)(struct msm_dsi_phy *phy);
};
struct msm_dsi_phy_cfg {
@@ -82,6 +83,8 @@ struct msm_dsi_dphy_timing {
#define DSI_PIXEL_PLL_CLK 1
#define NUM_PROVIDED_CLKS 2
+#define DSI_LANE_MAX 5
+
struct msm_dsi_phy {
struct platform_device *pdev;
void __iomem *base;
@@ -99,6 +102,7 @@ struct msm_dsi_phy {
struct msm_dsi_dphy_timing timing;
const struct msm_dsi_phy_cfg *cfg;
+ void *tuning_cfg;
enum msm_dsi_phy_usecase usecase;
bool regulator_ldo_mode;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
index d8128f50b0dd..08b015ea1b1e 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
@@ -83,6 +83,18 @@ struct dsi_pll_10nm {
#define to_pll_10nm(x) container_of(x, struct dsi_pll_10nm, clk_hw)
+/**
+ * struct dsi_phy_10nm_tuning_cfg - Holds 10nm PHY tuning config parameters.
+ * @rescode_offset_top: Offset for pull-up legs rescode.
+ * @rescode_offset_bot: Offset for pull-down legs rescode.
+ * @vreg_ctrl: vreg ctrl to drive LDO level
+ */
+struct dsi_phy_10nm_tuning_cfg {
+ u8 rescode_offset_top[DSI_LANE_MAX];
+ u8 rescode_offset_bot[DSI_LANE_MAX];
+ u8 vreg_ctrl;
+};
+
/*
* Global list of private DSI PLL struct pointers. We need this for bonded DSI
* mode, where the master PLL's clk_ops needs access the slave's private data
@@ -562,7 +574,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov
char clk_name[32], parent[32], vco_name[32];
char parent2[32], parent3[32], parent4[32];
struct clk_init_data vco_init = {
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "ref",
+ },
.num_parents = 1,
.name = vco_name,
.flags = CLK_IGNORE_UNUSED,
@@ -747,6 +761,7 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
int i;
u8 tx_dctrl[] = { 0x00, 0x00, 0x00, 0x04, 0x01 };
void __iomem *lane_base = phy->lane_base;
+ struct dsi_phy_10nm_tuning_cfg *tuning_cfg = phy->tuning_cfg;
if (phy->cfg->quirks & DSI_PHY_10NM_QUIRK_OLD_TIMINGS)
tx_dctrl[3] = 0x02;
@@ -775,10 +790,13 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG2(i), 0x0);
dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG3(i),
i == 4 ? 0x80 : 0x0);
- dsi_phy_write(lane_base +
- REG_DSI_10nm_PHY_LN_OFFSET_TOP_CTRL(i), 0x0);
- dsi_phy_write(lane_base +
- REG_DSI_10nm_PHY_LN_OFFSET_BOT_CTRL(i), 0x0);
+
+ /* platform specific dsi phy drive strength adjustment */
+ dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_OFFSET_TOP_CTRL(i),
+ tuning_cfg->rescode_offset_top[i]);
+ dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_OFFSET_BOT_CTRL(i),
+ tuning_cfg->rescode_offset_bot[i]);
+
dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(i),
tx_dctrl[i]);
}
@@ -799,6 +817,7 @@ static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy,
u32 const timeout_us = 1000;
struct msm_dsi_dphy_timing *timing = &phy->timing;
void __iomem *base = phy->base;
+ struct dsi_phy_10nm_tuning_cfg *tuning_cfg = phy->tuning_cfg;
u32 data;
DBG("");
@@ -834,8 +853,9 @@ static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy,
/* Select MS1 byte-clk */
dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_GLBL_CTRL, 0x10);
- /* Enable LDO */
- dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_VREG_CTRL, 0x59);
+ /* Enable LDO with platform specific drive level/amplitude adjustment */
+ dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_VREG_CTRL,
+ tuning_cfg->vreg_ctrl);
/* Configure PHY lane swap (TODO: we need to calculate this) */
dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CFG0, 0x21);
@@ -922,6 +942,92 @@ static void dsi_10nm_phy_disable(struct msm_dsi_phy *phy)
DBG("DSI%d PHY disabled", phy->id);
}
+static int dsi_10nm_phy_parse_dt(struct msm_dsi_phy *phy)
+{
+ struct device *dev = &phy->pdev->dev;
+ struct dsi_phy_10nm_tuning_cfg *tuning_cfg;
+ s8 offset_top[DSI_LANE_MAX] = { 0 }; /* No offset */
+ s8 offset_bot[DSI_LANE_MAX] = { 0 }; /* No offset */
+ u32 ldo_level = 400; /* 400mV */
+ u8 level;
+ int ret, i;
+
+ tuning_cfg = devm_kzalloc(dev, sizeof(*tuning_cfg), GFP_KERNEL);
+ if (!tuning_cfg)
+ return -ENOMEM;
+
+ /* Drive strength adjustment parameters */
+ ret = of_property_read_u8_array(dev->of_node, "qcom,phy-rescode-offset-top",
+ offset_top, DSI_LANE_MAX);
+ if (ret && ret != -EINVAL) {
+ DRM_DEV_ERROR(dev, "failed to parse qcom,phy-rescode-offset-top, %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < DSI_LANE_MAX; i++) {
+ if (offset_top[i] < -32 || offset_top[i] > 31) {
+ DRM_DEV_ERROR(dev,
+ "qcom,phy-rescode-offset-top value %d is not in range [-32..31]\n",
+ offset_top[i]);
+ return -EINVAL;
+ }
+ tuning_cfg->rescode_offset_top[i] = 0x3f & offset_top[i];
+ }
+
+ ret = of_property_read_u8_array(dev->of_node, "qcom,phy-rescode-offset-bot",
+ offset_bot, DSI_LANE_MAX);
+ if (ret && ret != -EINVAL) {
+ DRM_DEV_ERROR(dev, "failed to parse qcom,phy-rescode-offset-bot, %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < DSI_LANE_MAX; i++) {
+ if (offset_bot[i] < -32 || offset_bot[i] > 31) {
+ DRM_DEV_ERROR(dev,
+ "qcom,phy-rescode-offset-bot value %d is not in range [-32..31]\n",
+ offset_bot[i]);
+ return -EINVAL;
+ }
+ tuning_cfg->rescode_offset_bot[i] = 0x3f & offset_bot[i];
+ }
+
+ /* Drive level/amplitude adjustment parameters */
+ ret = of_property_read_u32(dev->of_node, "qcom,phy-drive-ldo-level", &ldo_level);
+ if (ret && ret != -EINVAL) {
+ DRM_DEV_ERROR(dev, "failed to parse qcom,phy-drive-ldo-level, %d\n", ret);
+ return ret;
+ }
+
+ switch (ldo_level) {
+ case 375:
+ level = 0;
+ break;
+ case 400:
+ level = 1;
+ break;
+ case 425:
+ level = 2;
+ break;
+ case 450:
+ level = 3;
+ break;
+ case 475:
+ level = 4;
+ break;
+ case 500:
+ level = 5;
+ break;
+ default:
+ DRM_DEV_ERROR(dev, "qcom,phy-drive-ldo-level %d is not supported\n", ldo_level);
+ return -EINVAL;
+ }
+ tuning_cfg->vreg_ctrl = 0x58 | (0x7 & level);
+
+ phy->tuning_cfg = tuning_cfg;
+
+ return 0;
+}
+
const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = {
.has_phy_lane = true,
.reg_cfg = {
@@ -936,6 +1042,7 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = {
.pll_init = dsi_pll_10nm_init,
.save_pll_state = dsi_10nm_pll_save_state,
.restore_pll_state = dsi_10nm_pll_restore_state,
+ .parse_dt_properties = dsi_10nm_phy_parse_dt,
},
.min_pll_rate = 1000000000UL,
.max_pll_rate = 3500000000UL,
@@ -957,6 +1064,7 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs = {
.pll_init = dsi_pll_10nm_init,
.save_pll_state = dsi_10nm_pll_save_state,
.restore_pll_state = dsi_10nm_pll_restore_state,
+ .parse_dt_properties = dsi_10nm_phy_parse_dt,
},
.min_pll_rate = 1000000000UL,
.max_pll_rate = 3500000000UL,
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
index 7414966f198e..75557ac99adf 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
@@ -802,7 +802,9 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov
{
char clk_name[32], parent[32], vco_name[32];
struct clk_init_data vco_init = {
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "ref",
+ },
.num_parents = 1,
.name = vco_name,
.flags = CLK_IGNORE_UNUSED,
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index 2da673a2add6..48eab80b548e 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -521,7 +521,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov
{
char clk_name[32], parent1[32], parent2[32], vco_name[32];
struct clk_init_data vco_init = {
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "ref", .name = "xo",
+ },
.num_parents = 1,
.name = vco_name,
.flags = CLK_IGNORE_UNUSED,
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
index 71ed4aa0dc67..fc56cdcc9ad6 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
@@ -385,7 +385,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov
{
char *clk_name, *parent_name, *vco_name;
struct clk_init_data vco_init = {
- .parent_names = (const char *[]){ "pxo" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "ref",
+ },
.num_parents = 1,
.flags = CLK_IGNORE_UNUSED,
.ops = &clk_ops_dsi_pll_28nm_vco,
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 079613d2aaa9..6e506feb111f 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -588,7 +588,9 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
char clk_name[32], parent[32], vco_name[32];
char parent2[32], parent3[32], parent4[32];
struct clk_init_data vco_init = {
- .parent_names = (const char *[]){ "bi_tcxo" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "ref",
+ },
.num_parents = 1,
.name = vco_name,
.flags = CLK_IGNORE_UNUSED,
@@ -862,20 +864,26 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
/* Alter PHY configurations if data rate less than 1.5GHZ*/
less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000);
- /* For C-PHY, no low power settings for lower clk rate */
- if (phy->cphy_mode)
- less_than_1500_mhz = false;
-
if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {
vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52;
- glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00;
- glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c;
+ if (phy->cphy_mode) {
+ glbl_rescode_top_ctrl = 0x00;
+ glbl_rescode_bot_ctrl = 0x3c;
+ } else {
+ glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00;
+ glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c;
+ }
glbl_str_swi_cal_sel_ctrl = 0x00;
glbl_hstx_str_ctrl_0 = 0x88;
} else {
vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59;
- glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00;
- glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88;
+ if (phy->cphy_mode) {
+ glbl_str_swi_cal_sel_ctrl = 0x03;
+ glbl_hstx_str_ctrl_0 = 0x66;
+ } else {
+ glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00;
+ glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88;
+ }
glbl_rescode_top_ctrl = 0x03;
glbl_rescode_bot_ctrl = 0x3c;
}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 719720709e9e..ec324352e862 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -133,7 +133,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
hdmi->config = config;
spin_lock_init(&hdmi->reg_lock);
- hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI");
+ hdmi->mmio = msm_ioremap(pdev, config->mmio_name);
if (IS_ERR(hdmi->mmio)) {
ret = PTR_ERR(hdmi->mmio);
goto fail;
@@ -144,8 +144,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
config->mmio_name);
hdmi->mmio_phy_addr = res->start;
- hdmi->qfprom_mmio = msm_ioremap(pdev,
- config->qfprom_mmio_name, "HDMI_QFPROM");
+ hdmi->qfprom_mmio = msm_ioremap(pdev, config->qfprom_mmio_name);
if (IS_ERR(hdmi->qfprom_mmio)) {
DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n");
hdmi->qfprom_mmio = NULL;
@@ -306,7 +305,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
}
ret = devm_request_irq(&pdev->dev, hdmi->irq,
- msm_hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ msm_hdmi_irq, IRQF_TRIGGER_HIGH,
"hdmi_isr", hdmi);
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n",
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 68fba4bf7212..10ebe2089cb6 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -282,15 +282,18 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge
long actual, requested;
requested = 1000 * mode->clock;
- actual = kms->funcs->round_pixclk(kms,
- requested, hdmi_bridge->hdmi->encoder);
/* for mdp5/apq8074, we manage our own pixel clk (as opposed to
* mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
* instead):
*/
- if (config->pwr_clk_cnt > 0)
- actual = clk_round_rate(hdmi->pwr_clks[0], actual);
+ if (kms->funcs->round_pixclk)
+ actual = kms->funcs->round_pixclk(kms,
+ requested, hdmi_bridge->hdmi->encoder);
+ else if (config->pwr_clk_cnt > 0)
+ actual = clk_round_rate(hdmi->pwr_clks[0], requested);
+ else
+ actual = requested;
DBG("requested=%ld, actual=%ld", requested, actual);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
index 16b0e8836d27..9780107e1cc9 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
@@ -144,7 +144,7 @@ static int msm_hdmi_phy_probe(struct platform_device *pdev)
if (!phy->cfg)
return -ENODEV;
- phy->mmio = msm_ioremap(pdev, "hdmi_phy", "HDMI_PHY");
+ phy->mmio = msm_ioremap(pdev, "hdmi_phy");
if (IS_ERR(phy->mmio)) {
DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__);
return -ENOMEM;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c
index 99c7853353fd..b06d9d25a189 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c
@@ -716,19 +716,18 @@ int msm_hdmi_pll_8996_init(struct platform_device *pdev)
pll->pdev = pdev;
- pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL");
+ pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
if (IS_ERR(pll->mmio_qserdes_com)) {
DRM_DEV_ERROR(dev, "failed to map pll base\n");
return -ENOMEM;
}
for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
- char name[32], label[32];
+ char name[32];
snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
- snprintf(label, sizeof(label), "HDMI_TX_L%d", i);
- pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name, label);
+ pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
if (IS_ERR(pll->mmio_qserdes_tx[i])) {
DRM_DEV_ERROR(dev, "failed to map pll base\n");
return -ENOMEM;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c
index 562dfac67792..be4b0b67e797 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c
@@ -434,7 +434,7 @@ int msm_hdmi_pll_8960_init(struct platform_device *pdev)
if (!pll)
return -ENOMEM;
- pll->mmio = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL");
+ pll->mmio = msm_ioremap(pdev, "hdmi_pll");
if (IS_ERR(pll->mmio)) {
DRM_DEV_ERROR(dev, "failed to map pll base\n");
return -ENOMEM;
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 27c9ae563f2f..1686fbb611fd 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -5,7 +5,6 @@
*/
#include <drm/drm_atomic_uapi.h>
-#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_vblank.h>
#include "msm_atomic_trace.h"
@@ -13,20 +12,6 @@
#include "msm_gem.h"
#include "msm_kms.h"
-int msm_atomic_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *new_state)
-{
- struct msm_drm_private *priv = plane->dev->dev_private;
- struct msm_kms *kms = priv->kms;
-
- if (!new_state->fb)
- return 0;
-
- drm_gem_plane_helper_prepare_fb(plane, new_state);
-
- return msm_framebuffer_prepare(new_state->fb, kms->aspace);
-}
-
/*
* Helpers to control vblanks while we flush.. basically just to ensure
* that vblank accounting is switched on, so we get valid seqn/timestamp
diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c
index 0804c31e8962..ea2a20699cb4 100644
--- a/drivers/gpu/drm/msm/msm_debugfs.c
+++ b/drivers/gpu/drm/msm/msm_debugfs.c
@@ -201,9 +201,9 @@ shrink_set(void *data, u64 val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(shrink_fops,
- shrink_get, shrink_set,
- "0x%08llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(shrink_fops,
+ shrink_get, shrink_set,
+ "0x%08llx\n");
static int msm_gem_show(struct seq_file *m, void *arg)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index ff19c5a94d6f..c09c23a80c81 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -57,14 +57,6 @@ static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = {
.atomic_commit_tail = msm_atomic_commit_tail,
};
-#ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
-static bool reglog;
-MODULE_PARM_DESC(reglog, "Enable register read/write logging");
-module_param(reglog, bool, 0600);
-#else
-#define reglog 0
-#endif
-
#ifdef CONFIG_DRM_FBDEV_EMULATION
static bool fbdev = true;
MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer");
@@ -83,152 +75,6 @@ static bool modeset = true;
MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)");
module_param(modeset, bool, 0600);
-/*
- * Util/helpers:
- */
-
-struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
- const char *name)
-{
- int i;
- char n[32];
-
- snprintf(n, sizeof(n), "%s_clk", name);
-
- for (i = 0; bulk && i < count; i++) {
- if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
- return bulk[i].clk;
- }
-
-
- return NULL;
-}
-
-struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
-{
- struct clk *clk;
- char name2[32];
-
- clk = devm_clk_get(&pdev->dev, name);
- if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
- return clk;
-
- snprintf(name2, sizeof(name2), "%s_clk", name);
-
- clk = devm_clk_get(&pdev->dev, name2);
- if (!IS_ERR(clk))
- dev_warn(&pdev->dev, "Using legacy clk name binding. Use "
- "\"%s\" instead of \"%s\"\n", name, name2);
-
- return clk;
-}
-
-static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name,
- const char *dbgname, bool quiet, phys_addr_t *psize)
-{
- struct resource *res;
- unsigned long size;
- void __iomem *ptr;
-
- if (name)
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
- else
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- if (!res) {
- if (!quiet)
- DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name);
- return ERR_PTR(-EINVAL);
- }
-
- size = resource_size(res);
-
- ptr = devm_ioremap(&pdev->dev, res->start, size);
- if (!ptr) {
- if (!quiet)
- DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name);
- return ERR_PTR(-ENOMEM);
- }
-
- if (reglog)
- printk(KERN_DEBUG "IO:region %s %p %08lx\n", dbgname, ptr, size);
-
- if (psize)
- *psize = size;
-
- return ptr;
-}
-
-void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
- const char *dbgname)
-{
- return _msm_ioremap(pdev, name, dbgname, false, NULL);
-}
-
-void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name,
- const char *dbgname)
-{
- return _msm_ioremap(pdev, name, dbgname, true, NULL);
-}
-
-void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name,
- const char *dbgname, phys_addr_t *psize)
-{
- return _msm_ioremap(pdev, name, dbgname, false, psize);
-}
-
-void msm_writel(u32 data, void __iomem *addr)
-{
- if (reglog)
- printk(KERN_DEBUG "IO:W %p %08x\n", addr, data);
- writel(data, addr);
-}
-
-u32 msm_readl(const void __iomem *addr)
-{
- u32 val = readl(addr);
- if (reglog)
- pr_err("IO:R %p %08x\n", addr, val);
- return val;
-}
-
-void msm_rmw(void __iomem *addr, u32 mask, u32 or)
-{
- u32 val = msm_readl(addr);
-
- val &= ~mask;
- msm_writel(val | or, addr);
-}
-
-static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t)
-{
- struct msm_hrtimer_work *work = container_of(t,
- struct msm_hrtimer_work, timer);
-
- kthread_queue_work(work->worker, &work->work);
-
- return HRTIMER_NORESTART;
-}
-
-void msm_hrtimer_queue_work(struct msm_hrtimer_work *work,
- ktime_t wakeup_time,
- enum hrtimer_mode mode)
-{
- hrtimer_start(&work->timer, wakeup_time, mode);
-}
-
-void msm_hrtimer_work_init(struct msm_hrtimer_work *work,
- struct kthread_worker *worker,
- kthread_work_func_t fn,
- clockid_t clock_id,
- enum hrtimer_mode mode)
-{
- hrtimer_init(&work->timer, clock_id, mode);
- work->timer.function = msm_hrtimer_worktimer;
- work->worker = worker;
- kthread_init_work(&work->work, fn);
-}
-
static irqreturn_t msm_irq(int irq, void *arg)
{
struct drm_device *dev = arg;
@@ -766,7 +612,8 @@ static int msm_ioctl_get_param(struct drm_device *dev, void *data,
if (!gpu)
return -ENXIO;
- return gpu->funcs->get_param(gpu, args->param, &args->value);
+ return gpu->funcs->get_param(gpu, file->driver_priv,
+ args->param, &args->value);
}
static int msm_ioctl_gem_new(struct drm_device *dev, void *data,
@@ -1438,9 +1285,12 @@ static void msm_pdev_shutdown(struct platform_device *pdev)
static const struct of_device_id dt_match[] = {
{ .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 },
{ .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 },
+ { .compatible = "qcom,msm8998-mdss", .data = (void *)KMS_DPU },
+ { .compatible = "qcom,qcm2290-mdss", .data = (void *)KMS_DPU },
{ .compatible = "qcom,sdm845-mdss", .data = (void *)KMS_DPU },
{ .compatible = "qcom,sc7180-mdss", .data = (void *)KMS_DPU },
{ .compatible = "qcom,sc7280-mdss", .data = (void *)KMS_DPU },
+ { .compatible = "qcom,sc8180x-mdss", .data = (void *)KMS_DPU },
{ .compatible = "qcom,sm8150-mdss", .data = (void *)KMS_DPU },
{ .compatible = "qcom,sm8250-mdss", .data = (void *)KMS_DPU },
{}
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index ae52412d529a..d661debb50f1 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -109,24 +109,6 @@ struct msm_display_topology {
u32 num_dspp;
};
-/**
- * struct msm_display_info - defines display properties
- * @intf_type: DRM_MODE_ENCODER_ type
- * @capabilities: Bitmask of display flags
- * @num_of_h_tiles: Number of horizontal tiles in case of split interface
- * @h_tile_instance: Controller instance used per tile. Number of elements is
- * based on num_of_h_tiles
- * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is
- * used instead of panel TE in cmd mode panels
- */
-struct msm_display_info {
- int intf_type;
- uint32_t capabilities;
- uint32_t num_of_h_tiles;
- uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];
- bool is_te_using_watchdog_timer;
-};
-
/* Commit/Event thread specific structure */
struct msm_drm_thread {
struct drm_device *dev;
@@ -257,8 +239,6 @@ struct msm_format {
struct msm_pending_timer;
-int msm_atomic_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *new_state);
int msm_atomic_init_pending_timer(struct msm_pending_timer *timer,
struct msm_kms *kms, int crtc_idx);
void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer);
@@ -317,9 +297,9 @@ int msm_gem_prime_pin(struct drm_gem_object *obj);
void msm_gem_prime_unpin(struct drm_gem_object *obj);
int msm_framebuffer_prepare(struct drm_framebuffer *fb,
- struct msm_gem_address_space *aspace);
+ struct msm_gem_address_space *aspace, bool needs_dirtyfb);
void msm_framebuffer_cleanup(struct drm_framebuffer *fb,
- struct msm_gem_address_space *aspace);
+ struct msm_gem_address_space *aspace, bool needed_dirtyfb);
uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb,
struct msm_gem_address_space *aspace, int plane);
struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane);
@@ -480,15 +460,21 @@ struct clk *msm_clk_get(struct platform_device *pdev, const char *name);
struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
const char *name);
-void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
- const char *dbgname);
+void __iomem *msm_ioremap(struct platform_device *pdev, const char *name);
void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name,
- const char *dbgname, phys_addr_t *size);
-void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name,
- const char *dbgname);
-void msm_writel(u32 data, void __iomem *addr);
-u32 msm_readl(const void __iomem *addr);
-void msm_rmw(void __iomem *addr, u32 mask, u32 or);
+ phys_addr_t *size);
+void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name);
+
+#define msm_writel(data, addr) writel((data), (addr))
+#define msm_readl(addr) readl((addr))
+
+static inline void msm_rmw(void __iomem *addr, u32 mask, u32 or)
+{
+ u32 val = msm_readl(addr);
+
+ val &= ~mask;
+ msm_writel(val | or, addr);
+}
/**
* struct msm_hrtimer_work - a helper to combine an hrtimer with kthread_work
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 4d34df5354e0..96b379a08327 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -18,16 +18,36 @@
struct msm_framebuffer {
struct drm_framebuffer base;
const struct msm_format *format;
+
+ /* Count of # of attached planes which need dirtyfb: */
+ refcount_t dirtyfb;
};
#define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base)
static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
+static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb,
+ struct drm_file *file_priv, unsigned int flags,
+ unsigned int color, struct drm_clip_rect *clips,
+ unsigned int num_clips)
+{
+ struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
+
+ /* If this fb is not used on any display requiring pixel data to be
+ * flushed, then skip dirtyfb
+ */
+ if (refcount_read(&msm_fb->dirtyfb) == 0)
+ return 0;
+
+ return drm_atomic_helper_dirtyfb(fb, file_priv, flags, color,
+ clips, num_clips);
+}
+
static const struct drm_framebuffer_funcs msm_framebuffer_funcs = {
.create_handle = drm_gem_fb_create_handle,
.destroy = drm_gem_fb_destroy,
- .dirty = drm_atomic_helper_dirtyfb,
+ .dirty = msm_framebuffer_dirtyfb,
};
#ifdef CONFIG_DEBUG_FS
@@ -48,17 +68,19 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
}
#endif
-/* prepare/pin all the fb's bo's for scanout. Note that it is not valid
- * to prepare an fb more multiple different initiator 'id's. But that
- * should be fine, since only the scanout (mdpN) side of things needs
- * this, the gpu doesn't care about fb's.
+/* prepare/pin all the fb's bo's for scanout.
*/
int msm_framebuffer_prepare(struct drm_framebuffer *fb,
- struct msm_gem_address_space *aspace)
+ struct msm_gem_address_space *aspace,
+ bool needs_dirtyfb)
{
+ struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
int ret, i, n = fb->format->num_planes;
uint64_t iova;
+ if (needs_dirtyfb)
+ refcount_inc(&msm_fb->dirtyfb);
+
for (i = 0; i < n; i++) {
ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &iova);
drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret);
@@ -70,10 +92,15 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb,
}
void msm_framebuffer_cleanup(struct drm_framebuffer *fb,
- struct msm_gem_address_space *aspace)
+ struct msm_gem_address_space *aspace,
+ bool needed_dirtyfb)
{
+ struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
int i, n = fb->format->num_planes;
+ if (needed_dirtyfb)
+ refcount_dec(&msm_fb->dirtyfb);
+
for (i = 0; i < n; i++)
msm_gem_unpin_iova(fb->obj[i], aspace);
}
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 54ca0817d807..af612add5264 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -35,6 +35,9 @@ struct msm_gem_address_space {
* will be non-NULL:
*/
struct pid *pid;
+
+ /* @faults: the number of GPU hangs associated with this address space */
+ int faults;
};
struct msm_gem_vma {
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 2c1049c0ea14..bacdabbaad96 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -370,8 +370,8 @@ static void recover_worker(struct kthread_work *work)
struct task_struct *task;
/* Increment the fault counts */
- gpu->global_faults++;
submit->queue->faults++;
+ submit->aspace->faults++;
task = get_pid_task(submit->pid, PIDTYPE_PID);
if (task) {
@@ -389,6 +389,12 @@ static void recover_worker(struct kthread_work *work)
} else {
msm_rd_dump_submit(priv->hangrd, submit, NULL);
}
+ } else {
+ /*
+ * We couldn't attribute this fault to any particular context,
+ * so increment the global fault count instead.
+ */
+ gpu->global_faults++;
}
/* Record the crash state */
@@ -838,7 +844,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
gpu->funcs = funcs;
gpu->name = name;
- gpu->worker = kthread_create_worker(0, "%s-worker", gpu->name);
+ gpu->worker = kthread_create_worker(0, "gpu-worker");
if (IS_ERR(gpu->worker)) {
ret = PTR_ERR(gpu->worker);
gpu->worker = NULL;
@@ -861,7 +867,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
/* Map registers: */
- gpu->mmio = msm_ioremap(pdev, config->ioname, name);
+ gpu->mmio = msm_ioremap(pdev, config->ioname);
if (IS_ERR(gpu->mmio)) {
ret = PTR_ERR(gpu->mmio);
goto fail;
@@ -876,7 +882,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
}
ret = devm_request_irq(&pdev->dev, gpu->irq, irq_handler,
- IRQF_TRIGGER_HIGH, gpu->name, gpu);
+ IRQF_TRIGGER_HIGH, "gpu-irq", gpu);
if (ret) {
DRM_DEV_ERROR(drm->dev, "failed to request IRQ%u: %d\n", gpu->irq, ret);
goto fail;
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 92aa1e9196c6..c99627fc99dd 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -42,7 +42,8 @@ struct msm_gpu_config {
* + z180_gpu
*/
struct msm_gpu_funcs {
- int (*get_param)(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
+ int (*get_param)(struct msm_gpu *gpu, struct msm_file_private *ctx,
+ uint32_t param, uint64_t *value);
int (*hw_init)(struct msm_gpu *gpu);
int (*pm_suspend)(struct msm_gpu *gpu);
int (*pm_resume)(struct msm_gpu *gpu);
@@ -199,7 +200,10 @@ struct msm_gpu {
/* does gpu need hw_init? */
bool needs_hw_init;
- /* number of GPU hangs (for all contexts) */
+ /**
+ * global_faults: number of GPU hangs not attributed to a particular
+ * address space
+ */
int global_faults;
void __iomem *mmio;
diff --git a/drivers/gpu/drm/msm/msm_io_utils.c b/drivers/gpu/drm/msm/msm_io_utils.c
new file mode 100644
index 000000000000..7b504617833a
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_io_utils.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ */
+
+#include "msm_drv.h"
+
+/*
+ * Util/helpers:
+ */
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+ const char *name)
+{
+ int i;
+ char n[32];
+
+ snprintf(n, sizeof(n), "%s_clk", name);
+
+ for (i = 0; bulk && i < count; i++) {
+ if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
+ return bulk[i].clk;
+ }
+
+
+ return NULL;
+}
+
+struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
+{
+ struct clk *clk;
+ char name2[32];
+
+ clk = devm_clk_get(&pdev->dev, name);
+ if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
+ return clk;
+
+ snprintf(name2, sizeof(name2), "%s_clk", name);
+
+ clk = devm_clk_get(&pdev->dev, name2);
+ if (!IS_ERR(clk))
+ dev_warn(&pdev->dev, "Using legacy clk name binding. Use "
+ "\"%s\" instead of \"%s\"\n", name, name2);
+
+ return clk;
+}
+
+static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name,
+ bool quiet, phys_addr_t *psize)
+{
+ struct resource *res;
+ unsigned long size;
+ void __iomem *ptr;
+
+ if (name)
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+ else
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ if (!quiet)
+ DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ size = resource_size(res);
+
+ ptr = devm_ioremap(&pdev->dev, res->start, size);
+ if (!ptr) {
+ if (!quiet)
+ DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (psize)
+ *psize = size;
+
+ return ptr;
+}
+
+void __iomem *msm_ioremap(struct platform_device *pdev, const char *name)
+{
+ return _msm_ioremap(pdev, name, false, NULL);
+}
+
+void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name)
+{
+ return _msm_ioremap(pdev, name, true, NULL);
+}
+
+void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name,
+ phys_addr_t *psize)
+{
+ return _msm_ioremap(pdev, name, false, psize);
+}
+
+static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t)
+{
+ struct msm_hrtimer_work *work = container_of(t,
+ struct msm_hrtimer_work, timer);
+
+ kthread_queue_work(work->worker, &work->work);
+
+ return HRTIMER_NORESTART;
+}
+
+void msm_hrtimer_queue_work(struct msm_hrtimer_work *work,
+ ktime_t wakeup_time,
+ enum hrtimer_mode mode)
+{
+ hrtimer_start(&work->timer, wakeup_time, mode);
+}
+
+void msm_hrtimer_work_init(struct msm_hrtimer_work *work,
+ struct kthread_worker *worker,
+ kthread_work_func_t fn,
+ clockid_t clock_id,
+ enum hrtimer_mode mode)
+{
+ hrtimer_init(&work->timer, clock_id, mode);
+ work->timer.function = msm_hrtimer_worktimer;
+ work->worker = worker;
+ kthread_init_work(&work->work, fn);
+}
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 81432ec07012..9d835331f214 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -62,6 +62,7 @@ enum rd_sect_type {
RD_FRAG_SHADER,
RD_BUFFER_CONTENTS,
RD_GPU_ID,
+ RD_CHIP_ID,
};
#define BUF_SZ 512 /* should be power of 2 */
@@ -196,12 +197,17 @@ static int rd_open(struct inode *inode, struct file *file)
/* the parsing tools need to know gpu-id to know which
* register database to load.
+ *
+ * Note: These particular params do not require a context
*/
- gpu->funcs->get_param(gpu, MSM_PARAM_GPU_ID, &val);
+ gpu->funcs->get_param(gpu, NULL, MSM_PARAM_GPU_ID, &val);
gpu_id = val;
rd_write_section(rd, RD_GPU_ID, &gpu_id, sizeof(gpu_id));
+ gpu->funcs->get_param(gpu, NULL, MSM_PARAM_CHIP_ID, &val);
+ rd_write_section(rd, RD_CHIP_ID, &val, sizeof(val));
+
out:
mutex_unlock(&gpu->lock);
return ret;