Merge branches 'msm-next-lumag-core', 'msm-next-lumag-dpu', 'msm-next-lumag-dp',...
authorDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Tue, 5 Jul 2022 03:01:16 +0000 (06:01 +0300)
committerDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Tue, 5 Jul 2022 03:01:16 +0000 (06:01 +0300)
Changes in this merge:
Core:
- client utilization via fdinfo support
- fix fence rollover issue

DPU:
- constification of HW catalog
- support for using encoder as CRC source
- WB support on sc7180
- WB resolution fixes
- enable DSPP support for sc7280

DP:
- dropped custom bulk clock implementation
- made dp_bridge_mode_valid() return MODE_CLOCK_HIGH where applicable
- fix link retraining on resolution change

MDP5:
- MSM8953 perf data

HDMI:
- YAML'ification of schema
- dropped obsolete GPIO support
- misc cleanups

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
55 files changed:
Documentation/devicetree/bindings/display/msm/hdmi.txt [deleted file]
Documentation/devicetree/bindings/display/msm/hdmi.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/qcom,hdmi-phy-other.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml [new file with mode: 0644]
Documentation/gpu/drm-usage-stats.rst
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h
drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
drivers/gpu/drm/msm/dsi/dsi_host.c
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_fence.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/msm/msm_gpu_devfreq.c
include/drm/drm_gem.h

diff --git a/Documentation/devicetree/bindings/display/msm/hdmi.txt b/Documentation/devicetree/bindings/display/msm/hdmi.txt
deleted file mode 100644 (file)
index 5f90a40..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-Qualcomm adreno/snapdragon hdmi output
-
-Required properties:
-- compatible: one of the following
-   * "qcom,hdmi-tx-8996"
-   * "qcom,hdmi-tx-8994"
-   * "qcom,hdmi-tx-8084"
-   * "qcom,hdmi-tx-8974"
-   * "qcom,hdmi-tx-8660"
-   * "qcom,hdmi-tx-8960"
-- reg: Physical base address and length of the controller's registers
-- reg-names: "core_physical"
-- interrupts: The interrupt signal from the hdmi block.
-- power-domains: Should be <&mmcc MDSS_GDSC>.
-- clocks: device clocks
-  See ../clocks/clock-bindings.txt for details.
-- core-vdda-supply: phandle to supply regulator
-- hdmi-mux-supply: phandle to mux regulator
-- phys: the phandle for the HDMI PHY device
-- phy-names: the name of the corresponding PHY device
-
-Optional properties:
-- hpd-gpios: hpd pin
-- qcom,hdmi-tx-mux-en-gpios: hdmi mux enable pin
-- qcom,hdmi-tx-mux-sel-gpios: hdmi mux select pin
-- qcom,hdmi-tx-mux-lpm-gpios: hdmi mux lpm pin
-- power-domains: reference to the power domain(s), if available.
-- pinctrl-names: the pin control state names; should contain "default"
-- pinctrl-0: the default pinctrl state (active)
-- pinctrl-1: the "sleep" pinctrl state
-
-HDMI PHY:
-Required properties:
-- compatible: Could be the following
-  * "qcom,hdmi-phy-8660"
-  * "qcom,hdmi-phy-8960"
-  * "qcom,hdmi-phy-8974"
-  * "qcom,hdmi-phy-8084"
-  * "qcom,hdmi-phy-8996"
-- #phy-cells: Number of cells in a PHY specifier; Should be 0.
-- reg: Physical base address and length of the registers of the PHY sub blocks.
-- reg-names: The names of register regions. The following regions are required:
-  * "hdmi_phy"
-  * "hdmi_pll"
-  For HDMI PHY on msm8996, these additional register regions are required:
-    * "hdmi_tx_l0"
-    * "hdmi_tx_l1"
-    * "hdmi_tx_l3"
-    * "hdmi_tx_l4"
-- power-domains: Should be <&mmcc MDSS_GDSC>.
-- clocks: device clocks
-  See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
-- core-vdda-supply: phandle to vdda regulator device node
-
-Example:
-
-/ {
-       ...
-
-       hdmi: hdmi@4a00000 {
-               compatible = "qcom,hdmi-tx-8960";
-               reg-names = "core_physical";
-               reg = <0x04a00000 0x2f0>;
-               interrupts = <GIC_SPI 79 0>;
-               power-domains = <&mmcc MDSS_GDSC>;
-               clock-names =
-                   "core",
-                   "master_iface",
-                   "slave_iface";
-               clocks =
-                   <&mmcc HDMI_APP_CLK>,
-                   <&mmcc HDMI_M_AHB_CLK>,
-                   <&mmcc HDMI_S_AHB_CLK>;
-               qcom,hdmi-tx-ddc-clk = <&msmgpio 70 GPIO_ACTIVE_HIGH>;
-               qcom,hdmi-tx-ddc-data = <&msmgpio 71 GPIO_ACTIVE_HIGH>;
-               qcom,hdmi-tx-hpd = <&msmgpio 72 GPIO_ACTIVE_HIGH>;
-               core-vdda-supply = <&pm8921_hdmi_mvs>;
-               hdmi-mux-supply = <&ext_3p3v>;
-               pinctrl-names = "default", "sleep";
-               pinctrl-0 = <&hpd_active  &ddc_active  &cec_active>;
-               pinctrl-1 = <&hpd_suspend &ddc_suspend &cec_suspend>;
-
-               phys = <&hdmi_phy>;
-               phy-names = "hdmi_phy";
-       };
-
-       hdmi_phy: phy@4a00400 {
-               compatible = "qcom,hdmi-phy-8960";
-               reg-names = "hdmi_phy",
-                           "hdmi_pll";
-               reg = <0x4a00400 0x60>,
-                     <0x4a00500 0x100>;
-               #phy-cells = <0>;
-               power-domains = <&mmcc MDSS_GDSC>;
-               clock-names = "slave_iface";
-               clocks = <&mmcc HDMI_S_AHB_CLK>;
-               core-vdda-supply = <&pm8921_hdmi_mvs>;
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/msm/hdmi.yaml b/Documentation/devicetree/bindings/display/msm/hdmi.yaml
new file mode 100644 (file)
index 0000000..47e9766
--- /dev/null
@@ -0,0 +1,232 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/display/msm/hdmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Adreno/Snapdragon HDMI output
+
+maintainers:
+  - Rob Clark <robdclark@gmail.com>
+
+properties:
+  compatible:
+    enum:
+      - qcom,hdmi-tx-8084
+      - qcom,hdmi-tx-8660
+      - qcom,hdmi-tx-8960
+      - qcom,hdmi-tx-8974
+      - qcom,hdmi-tx-8994
+      - qcom,hdmi-tx-8996
+
+  clocks:
+    minItems: 1
+    maxItems: 5
+
+  clock-names:
+    minItems: 1
+    maxItems: 5
+
+  reg:
+    minItems: 1
+    maxItems: 3
+
+  reg-names:
+    minItems: 1
+    items:
+      - const: core_physical
+      - const: qfprom_physical
+      - const: hdcp_physical
+
+  interrupts:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+
+  phy-names:
+    enum:
+      - hdmi_phy
+      - hdmi-phy
+    deprecated: true
+
+  core-vdda-supply:
+    description: phandle to VDDA supply regulator
+
+  hdmi-mux-supply:
+    description: phandle to mux regulator
+    deprecated: true
+
+  core-vcc-supply:
+    description: phandle to VCC supply regulator
+
+  hpd-gpios:
+    maxItems: 1
+    description: hpd pin
+
+  qcom,hdmi-tx-mux-en-gpios:
+    maxItems: 1
+    deprecated: true
+    description: HDMI mux enable pin
+
+  qcom,hdmi-tx-mux-sel-gpios:
+    maxItems: 1
+    deprecated: true
+    description: HDMI mux select pin
+
+  qcom,hdmi-tx-mux-lpm-gpios:
+    maxItems: 1
+    deprecated: true
+    description: HDMI mux lpm pin
+
+  '#sound-dai-cells':
+    const: 1
+
+  ports:
+    type: object
+    $ref: /schemas/graph.yaml#/properties/ports
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        description: |
+          Input endpoints of the controller.
+
+      port@1:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        description: |
+          Output endpoints of the controller.
+
+    required:
+      - port@0
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - reg
+  - reg-names
+  - interrupts
+  - phys
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,hdmi-tx-8960
+              - qcom,hdmi-tx-8660
+    then:
+      properties:
+        clocks:
+          minItems: 3
+          maxItems: 3
+        clock-names:
+          items:
+            - const: core
+            - const: master_iface
+            - const: slave_iface
+        core-vcc-supplies: false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,hdmi-tx-8974
+              - qcom,hdmi-tx-8084
+              - qcom,hdmi-tx-8994
+              - qcom,hdmi-tx-8996
+    then:
+      properties:
+        clocks:
+          minItems: 5
+        clock-names:
+          items:
+            - const: mdp_core
+            - const: iface
+            - const: core
+            - const: alt_iface
+            - const: extp
+        hdmi-mux-supplies: false
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    hdmi: hdmi@4a00000 {
+      compatible = "qcom,hdmi-tx-8960";
+      reg-names = "core_physical";
+      reg = <0x04a00000 0x2f0>;
+      interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+      clock-names = "core",
+                    "master_iface",
+                    "slave_iface";
+      clocks = <&clk 61>,
+               <&clk 72>,
+               <&clk 98>;
+      hpd-gpios = <&msmgpio 72 GPIO_ACTIVE_HIGH>;
+      core-vdda-supply = <&pm8921_hdmi_mvs>;
+      hdmi-mux-supply = <&ext_3p3v>;
+      pinctrl-names = "default", "sleep";
+      pinctrl-0 = <&hpd_active  &ddc_active  &cec_active>;
+      pinctrl-1 = <&hpd_suspend &ddc_suspend &cec_suspend>;
+
+      phys = <&hdmi_phy>;
+    };
+  - |
+    #include <dt-bindings/clock/qcom,gcc-msm8996.h>
+    #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    hdmi@9a0000 {
+      compatible = "qcom,hdmi-tx-8996";
+      reg = <0x009a0000 0x50c>,
+            <0x00070000 0x6158>,
+            <0x009e0000 0xfff>;
+      reg-names = "core_physical",
+                  "qfprom_physical",
+                  "hdcp_physical";
+
+      interrupt-parent = <&mdss>;
+      interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+
+      clocks = <&mmcc MDSS_MDP_CLK>,
+               <&mmcc MDSS_AHB_CLK>,
+               <&mmcc MDSS_HDMI_CLK>,
+               <&mmcc MDSS_HDMI_AHB_CLK>,
+               <&mmcc MDSS_EXTPCLK_CLK>;
+      clock-names = "mdp_core",
+                    "iface",
+                    "core",
+                    "alt_iface",
+                    "extp";
+
+      phys = <&hdmi_phy>;
+      #sound-dai-cells = <1>;
+
+      pinctrl-names = "default", "sleep";
+      pinctrl-0 = <&hdmi_hpd_active &hdmi_ddc_active>;
+      pinctrl-1 = <&hdmi_hpd_suspend &hdmi_ddc_suspend>;
+
+      core-vdda-supply = <&vreg_l12a_1p8>;
+      core-vcc-supply = <&vreg_s4a_1p8>;
+
+      ports {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port@0 {
+          reg = <0>;
+          endpoint {
+            remote-endpoint = <&mdp5_intf3_out>;
+          };
+        };
+      };
+    };
+...
diff --git a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-other.yaml b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-other.yaml
new file mode 100644 (file)
index 0000000..fdb277e
--- /dev/null
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/phy/qcom,hdmi-phy-other.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Adreno/Snapdragon HDMI phy
+
+maintainers:
+  - Rob Clark <robdclark@gmail.com>
+
+properties:
+  compatible:
+    enum:
+      - qcom,hdmi-phy-8660
+      - qcom,hdmi-phy-8960
+      - qcom,hdmi-phy-8974
+      - qcom,hdmi-phy-8084
+
+  reg:
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: hdmi_phy
+      - const: hdmi_pll
+
+  clocks:
+    minItems: 1
+    maxItems: 2
+
+  clock-names:
+    minItems: 1
+    maxItems: 2
+
+  power-domains:
+    maxItems: 1
+
+  core-vdda-supply:
+    description: phandle to VDDA supply regulator
+
+  vddio-supply:
+    description: phandle to VDD I/O supply regulator
+
+  '#phy-cells':
+    const: 0
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,hdmi-phy-8660
+              - qcom,hdmi-phy-8960
+    then:
+      properties:
+        clocks:
+          maxItems: 1
+        clock-names:
+          items:
+            - const: slave_iface
+        vddio-supply: false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,hdmi-phy-8084
+              - qcom,hdmi-phy-8974
+    then:
+      properties:
+        clocks:
+          maxItems: 2
+        clock-names:
+          items:
+            - const: iface
+            - const: alt_iface
+
+required:
+  - compatible
+  - clocks
+  - reg
+  - reg-names
+  - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi_phy: phy@4a00400 {
+      compatible = "qcom,hdmi-phy-8960";
+      reg-names = "hdmi_phy",
+                  "hdmi_pll";
+      reg = <0x4a00400 0x60>,
+            <0x4a00500 0x100>;
+      #phy-cells = <0>;
+      power-domains = <&mmcc 1>;
+      clock-names = "slave_iface";
+      clocks = <&clk 21>;
+      core-vdda-supply = <&pm8921_hdmi_mvs>;
+    };
diff --git a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml
new file mode 100644 (file)
index 0000000..eea2e02
--- /dev/null
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/phy/qcom,hdmi-phy-qmp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Adreno/Snapdragon QMP HDMI phy
+
+maintainers:
+  - Rob Clark <robdclark@gmail.com>
+
+properties:
+  compatible:
+    enum:
+      - qcom,hdmi-phy-8996
+
+  reg:
+    maxItems: 6
+
+  reg-names:
+    items:
+      - const: hdmi_pll
+      - const: hdmi_tx_l0
+      - const: hdmi_tx_l1
+      - const: hdmi_tx_l2
+      - const: hdmi_tx_l3
+      - const: hdmi_phy
+
+  clocks:
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: iface
+      - const: ref
+
+  power-domains:
+    maxItems: 1
+
+  vcca-supply:
+    description: phandle to VCCA supply regulator
+
+  vddio-supply:
+    description: phandle to VDD I/O supply regulator
+
+  '#phy-cells':
+    const: 0
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - reg
+  - reg-names
+  - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi-phy@9a0600 {
+      compatible = "qcom,hdmi-phy-8996";
+      reg = <0x009a0600 0x1c4>,
+            <0x009a0a00 0x124>,
+            <0x009a0c00 0x124>,
+            <0x009a0e00 0x124>,
+            <0x009a1000 0x124>,
+            <0x009a1200 0x0c8>;
+      reg-names = "hdmi_pll",
+                  "hdmi_tx_l0",
+                  "hdmi_tx_l1",
+                  "hdmi_tx_l2",
+                  "hdmi_tx_l3",
+                  "hdmi_phy";
+
+      clocks = <&mmcc 116>,
+               <&gcc 214>;
+      clock-names = "iface",
+                    "ref";
+      #phy-cells = <0>;
+
+      vddio-supply = <&vreg_l12a_1p8>;
+      vcca-supply = <&vreg_l28a_0p925>;
+    };
index 6c9f166..92c5117 100644 (file)
@@ -105,6 +105,27 @@ object belong to this client, in the respective memory region.
 Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
 indicating kibi- or mebi-bytes.
 
+- drm-cycles-<str> <uint>
+
+Engine identifier string must be the same as the one specified in the
+drm-engine-<str> tag and shall contain the number of busy cycles for the given
+engine.
+
+Values are not required to be constantly monotonic if it makes the driver
+implementation easier, but are required to catch up with the previously reported
+larger value within a reasonable period. Upon observing a value lower than what
+was previously read, userspace is expected to stay with that larger previous
+value until a monotonic update is seen.
+
+- drm-maxfreq-<str> <uint> [Hz|MHz|KHz]
+
+Engine identifier string must be the same as the one specified in the
+drm-engine-<str> tag and shall contain the maximum frequency for the given
+engine.  Taken together with drm-cycles-<str>, this can be used to calculate
+percentage utilization of the engine, whereas drm-engine-<str> only reflects
+time active without considering what frequency the engine is operating as a
+percentage of it's maximum frequency.
+
 ===============================
 Driver specific implementations
 ===============================
index a7492dd..1d9d83d 100644 (file)
@@ -53,7 +53,7 @@ static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms,
                crtc_plane_bw += pstate->plane_fetch_bw;
        }
 
-       bw_factor = kms->catalog->perf.bw_inefficiency_factor;
+       bw_factor = kms->catalog->perf->bw_inefficiency_factor;
        if (bw_factor) {
                crtc_plane_bw *= bw_factor;
                do_div(crtc_plane_bw, 100);
@@ -90,7 +90,7 @@ static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms,
                crtc_clk = max(pstate->plane_clk, crtc_clk);
        }
 
-       clk_factor = kms->catalog->perf.clk_inefficiency_factor;
+       clk_factor = kms->catalog->perf->clk_inefficiency_factor;
        if (clk_factor) {
                crtc_clk *= clk_factor;
                do_div(crtc_clk, 100);
@@ -128,7 +128,7 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
                perf->core_clk_rate = kms->perf.fix_core_clk_rate;
        } else {
                perf->bw_ctl = _dpu_core_perf_calc_bw(kms, crtc);
-               perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib;
+               perf->max_per_pipe_ib = kms->catalog->perf->min_dram_ib;
                perf->core_clk_rate = _dpu_core_perf_calc_clk(kms, crtc, state);
        }
 
@@ -189,7 +189,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
                bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000);
                DRM_DEBUG_ATOMIC("calculated bandwidth=%uk\n", bw);
 
-               threshold = kms->catalog->perf.max_bw_high;
+               threshold = kms->catalog->perf->max_bw_high;
 
                DRM_DEBUG_ATOMIC("final threshold bw limit = %d\n", threshold);
 
@@ -413,7 +413,7 @@ static ssize_t _dpu_core_perf_mode_write(struct file *file,
                    const char __user *user_buf, size_t count, loff_t *ppos)
 {
        struct dpu_core_perf *perf = file->private_data;
-       struct dpu_perf_cfg *cfg = &perf->catalog->perf;
+       const struct dpu_perf_cfg *cfg = perf->catalog->perf;
        u32 perf_mode = 0;
        int ret;
 
@@ -468,7 +468,7 @@ static const struct file_operations dpu_core_perf_mode_fops = {
 int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent)
 {
        struct dpu_core_perf *perf = &dpu_kms->perf;
-       struct dpu_mdss_cfg *catalog = perf->catalog;
+       const struct dpu_mdss_cfg *catalog = perf->catalog;
        struct dentry *entry;
 
        entry = debugfs_create_dir("core_perf", parent);
@@ -480,15 +480,15 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent)
        debugfs_create_u32("enable_bw_release", 0600, entry,
                        (u32 *)&perf->enable_bw_release);
        debugfs_create_u32("threshold_low", 0600, entry,
-                       (u32 *)&catalog->perf.max_bw_low);
+                       (u32 *)&catalog->perf->max_bw_low);
        debugfs_create_u32("threshold_high", 0600, entry,
-                       (u32 *)&catalog->perf.max_bw_high);
+                       (u32 *)&catalog->perf->max_bw_high);
        debugfs_create_u32("min_core_ib", 0600, entry,
-                       (u32 *)&catalog->perf.min_core_ib);
+                       (u32 *)&catalog->perf->min_core_ib);
        debugfs_create_u32("min_llcc_ib", 0600, entry,
-                       (u32 *)&catalog->perf.min_llcc_ib);
+                       (u32 *)&catalog->perf->min_llcc_ib);
        debugfs_create_u32("min_dram_ib", 0600, entry,
-                       (u32 *)&catalog->perf.min_dram_ib);
+                       (u32 *)&catalog->perf->min_dram_ib);
        debugfs_create_file("perf_mode", 0600, entry,
                        (u32 *)perf, &dpu_core_perf_mode_fops);
        debugfs_create_u64("fix_core_clk_rate", 0600, entry,
@@ -517,7 +517,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,
+               const struct dpu_mdss_cfg *catalog,
                struct clk *core_clk)
 {
        perf->dev = dev;
index 8dfcc6d..e379599 100644 (file)
@@ -68,7 +68,7 @@ struct dpu_core_perf_tune {
 struct dpu_core_perf {
        struct drm_device *dev;
        struct dentry *debugfs_root;
-       struct dpu_mdss_cfg *catalog;
+       const struct dpu_mdss_cfg *catalog;
        struct clk *core_clk;
        u64 core_clk_rate;
        u64 max_core_clk_rate;
@@ -119,7 +119,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,
+               const struct dpu_mdss_cfg *catalog,
                struct clk *core_clk);
 
 struct dpu_kms;
index b56f777..4dd0ce0 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
@@ -78,6 +79,8 @@ static enum dpu_crtc_crc_source dpu_crtc_parse_crc_source(const char *src_name)
        if (!strcmp(src_name, "auto") ||
            !strcmp(src_name, "lm"))
                return DPU_CRTC_CRC_SOURCE_LAYER_MIXER;
+       if (!strcmp(src_name, "encoder"))
+               return DPU_CRTC_CRC_SOURCE_ENCODER;
 
        return DPU_CRTC_CRC_SOURCE_INVALID;
 }
@@ -93,23 +96,54 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
-       if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
+       if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) {
                *values_cnt = crtc_state->num_mixers;
+       } else if (source == DPU_CRTC_CRC_SOURCE_ENCODER) {
+               struct drm_encoder *drm_enc;
+
+               *values_cnt = 0;
+
+               drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask)
+                       *values_cnt += dpu_encoder_get_crc_values_cnt(drm_enc);
+       }
 
        return 0;
 }
 
+static void dpu_crtc_setup_lm_misr(struct dpu_crtc_state *crtc_state)
+{
+       struct dpu_crtc_mixer *m;
+       int i;
+
+       for (i = 0; i < crtc_state->num_mixers; ++i) {
+               m = &crtc_state->mixers[i];
+
+               if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
+                       continue;
+
+               /* Calculate MISR over 1 frame */
+               m->hw_lm->ops.setup_misr(m->hw_lm, true, 1);
+       }
+}
+
+static void dpu_crtc_setup_encoder_misr(struct drm_crtc *crtc)
+{
+       struct drm_encoder *drm_enc;
+
+       drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask)
+               dpu_encoder_setup_misr(drm_enc);
+}
+
 static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
 {
        enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name);
        enum dpu_crtc_crc_source current_source;
        struct dpu_crtc_state *crtc_state;
        struct drm_device *drm_dev = crtc->dev;
-       struct dpu_crtc_mixer *m;
 
        bool was_enabled;
        bool enable = false;
-       int i, ret = 0;
+       int ret = 0;
 
        if (source < 0) {
                DRM_DEBUG_DRIVER("Invalid CRC source %s for CRTC%d\n", src_name, crtc->index);
@@ -146,16 +180,12 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
 
        crtc_state->crc_frame_skip_count = 0;
 
-       for (i = 0; i < crtc_state->num_mixers; ++i) {
-               m = &crtc_state->mixers[i];
-
-               if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
-                       continue;
-
-               /* Calculate MISR over 1 frame */
-               m->hw_lm->ops.setup_misr(m->hw_lm, true, 1);
-       }
-
+       if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
+               dpu_crtc_setup_lm_misr(crtc_state);
+       else if (source == DPU_CRTC_CRC_SOURCE_ENCODER)
+               dpu_crtc_setup_encoder_misr(crtc);
+       else
+               ret = -EINVAL;
 
 cleanup:
        drm_modeset_unlock(&crtc->mutex);
@@ -174,26 +204,17 @@ static u32 dpu_crtc_get_vblank_counter(struct drm_crtc *crtc)
        return dpu_encoder_get_vsync_count(encoder);
 }
 
-
-static int dpu_crtc_get_crc(struct drm_crtc *crtc)
+static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc,
+               struct dpu_crtc_state *crtc_state)
 {
-       struct dpu_crtc_state *crtc_state;
        struct dpu_crtc_mixer *m;
        u32 crcs[CRTC_DUAL_MIXERS];
 
-       int i = 0;
        int rc = 0;
-
-       crtc_state = to_dpu_crtc_state(crtc->state);
+       int i;
 
        BUILD_BUG_ON(ARRAY_SIZE(crcs) != ARRAY_SIZE(crtc_state->mixers));
 
-       /* Skip first 2 frames in case of "uncooked" CRCs */
-       if (crtc_state->crc_frame_skip_count < 2) {
-               crtc_state->crc_frame_skip_count++;
-               return 0;
-       }
-
        for (i = 0; i < crtc_state->num_mixers; ++i) {
 
                m = &crtc_state->mixers[i];
@@ -214,6 +235,46 @@ static int dpu_crtc_get_crc(struct drm_crtc *crtc)
                        drm_crtc_accurate_vblank_count(crtc), crcs);
 }
 
+static int dpu_crtc_get_encoder_crc(struct drm_crtc *crtc)
+{
+       struct drm_encoder *drm_enc;
+       int rc, pos = 0;
+       u32 crcs[INTF_MAX];
+
+       drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask) {
+               rc = dpu_encoder_get_crc(drm_enc, crcs, pos);
+               if (rc < 0) {
+                       if (rc != -ENODATA)
+                               DRM_DEBUG_DRIVER("MISR read failed\n");
+
+                       return rc;
+               }
+
+               pos += rc;
+       }
+
+       return drm_crtc_add_crc_entry(crtc, true,
+                       drm_crtc_accurate_vblank_count(crtc), crcs);
+}
+
+static int dpu_crtc_get_crc(struct drm_crtc *crtc)
+{
+       struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);
+
+       /* Skip first 2 frames in case of "uncooked" CRCs */
+       if (crtc_state->crc_frame_skip_count < 2) {
+               crtc_state->crc_frame_skip_count++;
+               return 0;
+       }
+
+       if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
+               return dpu_crtc_get_lm_crc(crtc, crtc_state);
+       else if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_ENCODER)
+               return dpu_crtc_get_encoder_crc(crtc);
+
+       return -EINVAL;
+}
+
 static bool dpu_crtc_get_scanout_position(struct drm_crtc *crtc,
                                           bool in_vblank_irq,
                                           int *vpos, int *hpos,
index b8785c3..af03277 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
@@ -73,11 +74,13 @@ struct dpu_crtc_smmu_state_data {
  * enum dpu_crtc_crc_source: CRC source
  * @DPU_CRTC_CRC_SOURCE_NONE: no source set
  * @DPU_CRTC_CRC_SOURCE_LAYER_MIXER: CRC in layer mixer
+ * @DPU_CRTC_CRC_SOURCE_ENCODER: CRC in encoder
  * @DPU_CRTC_CRC_SOURCE_INVALID: Invalid source
  */
 enum dpu_crtc_crc_source {
        DPU_CRTC_CRC_SOURCE_NONE = 0,
        DPU_CRTC_CRC_SOURCE_LAYER_MIXER,
+       DPU_CRTC_CRC_SOURCE_ENCODER,
        DPU_CRTC_CRC_SOURCE_MAX,
        DPU_CRTC_CRC_SOURCE_INVALID = -1
 };
@@ -201,6 +204,8 @@ struct dpu_crtc {
  * @mixers        : List of active mixers
  * @num_ctls      : Number of ctl paths in use
  * @hw_ctls       : List of active ctl paths
+ * @crc_source    : CRC source
+ * @crc_frame_skip_count: Number of frames skipped before getting CRC
  */
 struct dpu_crtc_state {
        struct drm_crtc_state base;
index a1b8c45..c682d4e 100644 (file)
@@ -225,6 +225,70 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
        return dpu_enc->wide_bus_en;
 }
 
+int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc)
+{
+       struct dpu_encoder_virt *dpu_enc;
+       int i, num_intf = 0;
+
+       dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+       for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+               struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+
+               if (phys->hw_intf && phys->hw_intf->ops.setup_misr
+                               && phys->hw_intf->ops.collect_misr)
+                       num_intf++;
+       }
+
+       return num_intf;
+}
+
+void dpu_encoder_setup_misr(const struct drm_encoder *drm_enc)
+{
+       struct dpu_encoder_virt *dpu_enc;
+
+       int i;
+
+       dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+       for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+               struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+
+               if (!phys->hw_intf || !phys->hw_intf->ops.setup_misr)
+                       continue;
+
+               phys->hw_intf->ops.setup_misr(phys->hw_intf, true, 1);
+       }
+}
+
+int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos)
+{
+       struct dpu_encoder_virt *dpu_enc;
+
+       int i, rc = 0, entries_added = 0;
+
+       if (!drm_enc->crtc) {
+               DRM_ERROR("no crtc found for encoder %d\n", drm_enc->index);
+               return -EINVAL;
+       }
+
+       dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+       for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+               struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+
+               if (!phys->hw_intf || !phys->hw_intf->ops.collect_misr)
+                       continue;
+
+               rc = phys->hw_intf->ops.collect_misr(phys->hw_intf, &crcs[pos + entries_added]);
+               if (rc)
+                       return rc;
+               entries_added++;
+       }
+
+       return entries_added;
+}
+
 static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc)
 {
        struct dpu_hw_dither_cfg dither_cfg = { 0 };
@@ -634,7 +698,7 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
        }
 
        if (hw_mdptop->ops.setup_vsync_source &&
-                       disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) {
+                       disp_info->is_cmd_mode) {
                for (i = 0; i < dpu_enc->num_phys_encs; i++)
                        vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx;
 
@@ -718,8 +782,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc,
        }
        dpu_enc = to_dpu_encoder_virt(drm_enc);
        priv = drm_enc->dev->dev_private;
-       is_vid_mode = dpu_enc->disp_info.capabilities &
-                                               MSM_DISPLAY_CAP_VID_MODE;
+       is_vid_mode = !dpu_enc->disp_info.is_cmd_mode;
 
        /*
         * when idle_pc is not supported, process only KICKOFF, STOP and MODESET
@@ -1048,24 +1111,6 @@ static void dpu_encoder_virt_atomic_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]);
 
-               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->wb_idx >= WB_0 && phys->wb_idx < WB_MAX)
-                       phys->hw_wb = dpu_rm_get_wb(&dpu_kms->rm, phys->wb_idx);
-
-               if (!phys->hw_intf && !phys->hw_wb) {
-                       DPU_ERROR_ENC(dpu_enc,
-                                     "no intf or wb block assigned at idx: %d\n", i);
-                       return;
-               }
-
-               if (phys->hw_intf && phys->hw_wb) {
-                       DPU_ERROR_ENC(dpu_enc,
-                                       "invalid phys both intf and wb block at idx: %d\n", i);
-                       return;
-               }
-
                phys->cached_mode = crtc_state->adjusted_mode;
                if (phys->ops.atomic_mode_set)
                        phys->ops.atomic_mode_set(phys, crtc_state, conn_state);
@@ -1205,37 +1250,37 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
        mutex_unlock(&dpu_enc->enc_lock);
 }
 
-static enum dpu_intf dpu_encoder_get_intf(struct dpu_mdss_cfg *catalog,
+static enum dpu_intf dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog,
                enum dpu_intf_type type, u32 controller_id)
 {
        int i = 0;
 
-       if (type != INTF_WB) {
-               for (i = 0; i < catalog->intf_count; i++) {
-                       if (catalog->intf[i].type == type
-                               && catalog->intf[i].controller_id == controller_id) {
-                               return catalog->intf[i].id;
-                       }
+       if (type == INTF_WB)
+               return INTF_MAX;
+
+       for (i = 0; i < catalog->intf_count; i++) {
+               if (catalog->intf[i].type == type
+                   && catalog->intf[i].controller_id == controller_id) {
+                       return catalog->intf[i].id;
                }
        }
 
        return INTF_MAX;
 }
 
-static enum dpu_wb dpu_encoder_get_wb(struct dpu_mdss_cfg *catalog,
+static enum dpu_wb dpu_encoder_get_wb(const struct dpu_mdss_cfg *catalog,
                enum dpu_intf_type type, u32 controller_id)
 {
        int i = 0;
 
        if (type != INTF_WB)
-               goto end;
+               return WB_MAX;
 
        for (i = 0; i < catalog->wb_count; i++) {
                if (catalog->wb[i].id == controller_id)
                        return catalog->wb[i].id;
        }
 
-end:
        return WB_MAX;
 }
 
@@ -1603,7 +1648,7 @@ void dpu_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc)
 
                /* update only for command mode primary ctl */
                if ((phys == dpu_enc->cur_master) &&
-                  (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE)
+                   disp_info->is_cmd_mode
                    && ctl->ops.trigger_pending)
                        ctl->ops.trigger_pending(ctl);
        }
@@ -2139,39 +2184,36 @@ static int dpu_encoder_virt_add_phys_encs(
                return -EINVAL;
        }
 
-       if (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE) {
-               enc = dpu_encoder_phys_vid_init(params);
 
-               if (IS_ERR_OR_NULL(enc)) {
-                       DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n",
+       if (disp_info->intf_type == DRM_MODE_ENCODER_VIRTUAL) {
+               enc = dpu_encoder_phys_wb_init(params);
+
+               if (IS_ERR(enc)) {
+                       DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n",
                                PTR_ERR(enc));
-                       return enc == NULL ? -EINVAL : PTR_ERR(enc);
+                       return PTR_ERR(enc);
                }
 
                dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
                ++dpu_enc->num_phys_encs;
-       }
-
-       if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) {
+       } else if (disp_info->is_cmd_mode) {
                enc = dpu_encoder_phys_cmd_init(params);
 
-               if (IS_ERR_OR_NULL(enc)) {
+               if (IS_ERR(enc)) {
                        DPU_ERROR_ENC(dpu_enc, "failed to init cmd enc: %ld\n",
                                PTR_ERR(enc));
-                       return enc == NULL ? -EINVAL : PTR_ERR(enc);
+                       return PTR_ERR(enc);
                }
 
                dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
                ++dpu_enc->num_phys_encs;
-       }
-
-       if (disp_info->intf_type == DRM_MODE_ENCODER_VIRTUAL) {
-               enc = dpu_encoder_phys_wb_init(params);
+       } else {
+               enc = dpu_encoder_phys_vid_init(params);
 
-               if (IS_ERR_OR_NULL(enc)) {
-                       DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n",
-                                       PTR_ERR(enc));
-                       return enc == NULL ? -EINVAL : PTR_ERR(enc);
+               if (IS_ERR(enc)) {
+                       DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n",
+                               PTR_ERR(enc));
+                       return PTR_ERR(enc);
                }
 
                dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
@@ -2230,8 +2272,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
 
        DPU_DEBUG("dsi_info->num_of_h_tiles %d\n", disp_info->num_of_h_tiles);
 
-       if ((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) ||
-           (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE))
+       if (disp_info->intf_type != DRM_MODE_ENCODER_VIRTUAL)
                dpu_enc->idle_pc_supported =
                                dpu_kms->catalog->caps->has_idle_pc;
 
@@ -2294,7 +2335,25 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
                struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
                atomic_set(&phys->vsync_cnt, 0);
                atomic_set(&phys->underrun_cnt, 0);
+
+               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->wb_idx >= WB_0 && phys->wb_idx < WB_MAX)
+                       phys->hw_wb = dpu_rm_get_wb(&dpu_kms->rm, phys->wb_idx);
+
+               if (!phys->hw_intf && !phys->hw_wb) {
+                       DPU_ERROR_ENC(dpu_enc, "no intf or wb block assigned at idx: %d\n", i);
+                       ret = -EINVAL;
+               }
+
+               if (phys->hw_intf && phys->hw_wb) {
+                       DPU_ERROR_ENC(dpu_enc,
+                                       "invalid phys both intf and wb block at idx: %d\n", i);
+                       ret = -EINVAL;
+               }
        }
+
        mutex_unlock(&dpu_enc->enc_lock);
 
        return ret;
index 781d41c..d4d1ecd 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
 /**
  * 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_cmd_mode                Boolean to indicate if the CMD mode is requested
  * @is_te_using_watchdog_timer:  Boolean to indicate watchdog TE is
  *                              used instead of panel TE in cmd mode panels
  * @dsc:               DSC configuration data for DSC-enabled displays
  */
 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_cmd_mode;
        bool is_te_using_watchdog_timer;
        struct msm_display_dsc_config *dsc;
 };
@@ -175,6 +176,27 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
 
 /**
+ * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained
+ *     in virtual encoder that can collect CRC values
+ * @drm_enc:    Pointer to previously created drm encoder structure
+ * Returns:     Number of physical encoders for given drm encoder
+ */
+int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc);
+
+/**
+ * dpu_encoder_setup_misr - enable misr calculations
+ * @drm_enc:    Pointer to previously created drm encoder structure
+ */
+void dpu_encoder_setup_misr(const struct drm_encoder *drm_encoder);
+
+/**
+ * dpu_encoder_get_crc - get the crc value from interface blocks
+ * @drm_enc:    Pointer to previously created drm encoder structure
+ * Returns:     0 on success, error otherwise
+ */
+int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos);
+
+/**
  * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
  * @drm_enc:    Pointer to previously created drm encoder structure
  */
index 0ec809a..d301070 100644 (file)
@@ -20,8 +20,6 @@
 #include "dpu_crtc.h"
 #include "disp/msm_disp_snapshot.h"
 
-#define DEFAULT_MAX_WRITEBACK_WIDTH 2048
-
 #define to_dpu_encoder_phys_wb(x) \
        container_of(x, struct dpu_encoder_phys_wb, base)
 
@@ -103,8 +101,8 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
 {
        struct dpu_hw_wb *hw_wb;
        struct dpu_hw_wb_qos_cfg qos_cfg;
-       struct dpu_mdss_cfg *catalog;
-       struct dpu_qos_lut_tbl *qos_lut_tb;
+       const struct dpu_mdss_cfg *catalog;
+       const struct dpu_qos_lut_tbl *qos_lut_tb;
 
        if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) {
                DPU_ERROR("invalid parameter(s)\n");
@@ -118,11 +116,11 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
        memset(&qos_cfg, 0, sizeof(struct dpu_hw_wb_qos_cfg));
        qos_cfg.danger_safe_en = true;
        qos_cfg.danger_lut =
-               catalog->perf.danger_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
+               catalog->perf->danger_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
 
-       qos_cfg.safe_lut = catalog->perf.safe_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
+       qos_cfg.safe_lut = catalog->perf->safe_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
 
-       qos_lut_tb = &catalog->perf.qos_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
+       qos_lut_tb = &catalog->perf->qos_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
        qos_cfg.creq_lut = _dpu_hw_get_qos_lut(qos_lut_tb, 0);
 
        if (hw_wb->ops.setup_qos_lut)
@@ -166,7 +164,7 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
        if (hw_wb->ops.setup_cdp) {
                memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));
 
-               cdp_cfg.enable = phys_enc->dpu_kms->catalog->perf.cdp_cfg
+               cdp_cfg.enable = phys_enc->dpu_kms->catalog->perf->cdp_cfg
                                [DPU_PERF_CDP_USAGE_NRT].wr_enable;
                cdp_cfg.ubwc_meta_enable =
                                DPU_FORMAT_IS_UBWC(wb_cfg->dest.format);
@@ -278,9 +276,9 @@ static int dpu_encoder_phys_wb_atomic_check(
                DPU_ERROR("invalid fb h=%d, mode h=%d\n", fb->height,
                                  mode->vdisplay);
                return -EINVAL;
-       } else if (fb->width > DEFAULT_MAX_WRITEBACK_WIDTH) {
+       } else if (fb->width > phys_enc->hw_wb->caps->maxlinewidth) {
                DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n",
-                                 fb->width, DEFAULT_MAX_WRITEBACK_WIDTH);
+                                 fb->width, phys_enc->hw_wb->caps->maxlinewidth);
                return -EINVAL;
        }
 
index 400ebce..0239a81 100644 (file)
 #define DMA_CURSOR_MSM8998_MASK \
        (DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
 
-#define MIXER_SDM845_MASK \
+#define MIXER_MSM8998_MASK \
        (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER))
 
+#define MIXER_SDM845_MASK \
+       (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA))
+
 #define MIXER_SC7180_MASK \
-       (BIT(DPU_DIM_LAYER))
+       (BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA))
 
 #define PINGPONG_SDM845_MASK BIT(DPU_PINGPONG_DITHER)
 
@@ -936,17 +939,17 @@ static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
 };
 
 static const struct dpu_lm_cfg msm8998_lm[] = {
-       LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
+       LM_BLK("lm_0", LM_0, 0x44000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0),
-       LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
+       LM_BLK("lm_1", LM_1, 0x45000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1),
-       LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
+       LM_BLK("lm_2", LM_2, 0x46000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_2, LM_0, 0),
-       LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
+       LM_BLK("lm_3", LM_3, 0x47000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
-       LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK,
+       LM_BLK("lm_4", LM_4, 0x48000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
-       LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
+       LM_BLK("lm_5", LM_5, 0x49000, MIXER_MSM8998_MASK,
                &msm8998_lm_sblk, PINGPONG_3, LM_1, 0),
 };
 
@@ -1012,7 +1015,7 @@ static const struct dpu_lm_cfg sm8150_lm[] = {
 
 static const struct dpu_lm_cfg sc7280_lm[] = {
        LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK,
-               &sc7180_lm_sblk, PINGPONG_0, 0, 0),
+               &sc7180_lm_sblk, PINGPONG_0, 0, DSPP_0),
        LM_BLK("lm_2", LM_2, 0x46000, MIXER_SC7180_MASK,
                &sc7180_lm_sblk, PINGPONG_2, LM_3, 0),
        LM_BLK("lm_3", LM_3, 0x47000, MIXER_SC7180_MASK,
@@ -1285,7 +1288,7 @@ static const struct dpu_intf_cfg qcm2290_intf[] = {
  * Writeback blocks config
  *************************************************************/
 #define WB_BLK(_name, _id, _base, _features, _clk_ctrl, \
-               __xin_id, vbif_id, _reg, _wb_done_bit) \
+               __xin_id, vbif_id, _reg, _max_linewidth, _wb_done_bit) \
        { \
        .name = _name, .id = _id, \
        .base = _base, .len = 0x2c8, \
@@ -1295,13 +1298,13 @@ static const struct dpu_intf_cfg qcm2290_intf[] = {
        .clk_ctrl = _clk_ctrl, \
        .xin_id = __xin_id, \
        .vbif_idx = vbif_id, \
-       .maxlinewidth = DEFAULT_DPU_LINE_WIDTH, \
+       .maxlinewidth = _max_linewidth, \
        .intr_wb_done = DPU_IRQ_IDX(_reg, _wb_done_bit) \
        }
 
 static const struct dpu_wb_cfg sm8250_wb[] = {
        WB_BLK("wb_2", WB_2, 0x65000, WB_SM8250_MASK, DPU_CLK_CTRL_WB2, 6,
-                       VBIF_RT, MDP_SSPP_TOP0_INTR, 4),
+                       VBIF_RT, MDP_SSPP_TOP0_INTR, 4096, 4),
 };
 
 /*************************************************************
@@ -1336,6 +1339,7 @@ static const struct dpu_vbif_cfg msm8998_vbif[] = {
        .default_ot_wr_limit = 32,
        .features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
        .xin_halt_timeout = 0x4000,
+       .qos_rp_remap_size = 0x20,
        .dynamic_ot_rd_tbl = {
                .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
                .cfg = msm8998_ot_rdwr_cfg,
@@ -1363,6 +1367,7 @@ static const struct dpu_vbif_cfg sdm845_vbif[] = {
        .base = 0, .len = 0x1040,
        .features = BIT(DPU_VBIF_QOS_REMAP),
        .xin_halt_timeout = 0x4000,
+       .qos_rp_remap_size = 0x40,
        .qos_rt_tbl = {
                .npriority_lvl = ARRAY_SIZE(sdm845_rt_pri_lvl),
                .priority_lvl = sdm845_rt_pri_lvl,
@@ -1717,275 +1722,221 @@ static const struct dpu_perf_cfg qcm2290_perf_data = {
        .bw_inefficiency_factor = 120,
 };
 /*************************************************************
- * Hardware catalog init
+ * Hardware catalog
  *************************************************************/
 
-/*
- * 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.
- */
-static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
-{
-       *dpu_cfg = (struct dpu_mdss_cfg){
-               .caps = &sdm845_dpu_caps,
-               .mdp_count = ARRAY_SIZE(sdm845_mdp),
-               .mdp = sdm845_mdp,
-               .ctl_count = ARRAY_SIZE(sdm845_ctl),
-               .ctl = sdm845_ctl,
-               .sspp_count = ARRAY_SIZE(sdm845_sspp),
-               .sspp = sdm845_sspp,
-               .mixer_count = ARRAY_SIZE(sdm845_lm),
-               .mixer = sdm845_lm,
-               .pingpong_count = ARRAY_SIZE(sdm845_pp),
-               .pingpong = sdm845_pp,
-               .dsc_count = ARRAY_SIZE(sdm845_dsc),
-               .dsc = sdm845_dsc,
-               .intf_count = ARRAY_SIZE(sdm845_intf),
-               .intf = sdm845_intf,
-               .vbif_count = ARRAY_SIZE(sdm845_vbif),
-               .vbif = sdm845_vbif,
-               .reg_dma_count = 1,
-               .dma_cfg = sdm845_regdma,
-               .perf = sdm845_perf_data,
-               .mdss_irqs = IRQ_SDM845_MASK,
-       };
-}
-
-/*
- * sc7180_cfg_init(): populate sc7180 dpu sub-blocks reg offsets
- * and instance counts.
- */
-static void sc7180_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
-{
-       *dpu_cfg = (struct dpu_mdss_cfg){
-               .caps = &sc7180_dpu_caps,
-               .mdp_count = ARRAY_SIZE(sc7180_mdp),
-               .mdp = sc7180_mdp,
-               .ctl_count = ARRAY_SIZE(sc7180_ctl),
-               .ctl = sc7180_ctl,
-               .sspp_count = ARRAY_SIZE(sc7180_sspp),
-               .sspp = sc7180_sspp,
-               .mixer_count = ARRAY_SIZE(sc7180_lm),
-               .mixer = sc7180_lm,
-               .dspp_count = ARRAY_SIZE(sc7180_dspp),
-               .dspp = sc7180_dspp,
-               .pingpong_count = ARRAY_SIZE(sc7180_pp),
-               .pingpong = sc7180_pp,
-               .intf_count = ARRAY_SIZE(sc7180_intf),
-               .intf = sc7180_intf,
-               .vbif_count = ARRAY_SIZE(sdm845_vbif),
-               .vbif = sdm845_vbif,
-               .reg_dma_count = 1,
-               .dma_cfg = sdm845_regdma,
-               .perf = sc7180_perf_data,
-               .mdss_irqs = IRQ_SC7180_MASK,
-       };
-}
-
-/*
- * sm8150_cfg_init(): populate sm8150 dpu sub-blocks reg offsets
- * and instance counts.
- */
-static void sm8150_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
-{
-       *dpu_cfg = (struct dpu_mdss_cfg){
-               .caps = &sm8150_dpu_caps,
-               .mdp_count = ARRAY_SIZE(sdm845_mdp),
-               .mdp = sdm845_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,
-               .dspp_count = ARRAY_SIZE(sm8150_dspp),
-               .dspp = sm8150_dspp,
-               .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(sm8150_intf),
-               .intf = sm8150_intf,
-               .vbif_count = ARRAY_SIZE(sdm845_vbif),
-               .vbif = sdm845_vbif,
-               .reg_dma_count = 1,
-               .dma_cfg = sm8150_regdma,
-               .perf = sm8150_perf_data,
-               .mdss_irqs = IRQ_SDM845_MASK,
-       };
-}
-
-/*
- * 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.
- */
-static void sm8250_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
-{
-       *dpu_cfg = (struct dpu_mdss_cfg){
-               .caps = &sm8250_dpu_caps,
-               .mdp_count = ARRAY_SIZE(sm8250_mdp),
-               .mdp = sm8250_mdp,
-               .ctl_count = ARRAY_SIZE(sm8150_ctl),
-               .ctl = sm8150_ctl,
-               .sspp_count = ARRAY_SIZE(sm8250_sspp),
-               .sspp = sm8250_sspp,
-               .mixer_count = ARRAY_SIZE(sm8150_lm),
-               .mixer = sm8150_lm,
-               .dspp_count = ARRAY_SIZE(sm8150_dspp),
-               .dspp = sm8150_dspp,
-               .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(sm8150_intf),
-               .intf = sm8150_intf,
-               .vbif_count = ARRAY_SIZE(sdm845_vbif),
-               .vbif = sdm845_vbif,
-               .wb_count = ARRAY_SIZE(sm8250_wb),
-               .wb = sm8250_wb,
-               .reg_dma_count = 1,
-               .dma_cfg = sm8250_regdma,
-               .perf = sm8250_perf_data,
-               .mdss_irqs = IRQ_SM8250_MASK,
-       };
-}
-
-static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
-{
-       *dpu_cfg = (struct dpu_mdss_cfg){
-               .caps = &sc7280_dpu_caps,
-               .mdp_count = ARRAY_SIZE(sc7280_mdp),
-               .mdp = sc7280_mdp,
-               .ctl_count = ARRAY_SIZE(sc7280_ctl),
-               .ctl = sc7280_ctl,
-               .sspp_count = ARRAY_SIZE(sc7280_sspp),
-               .sspp = sc7280_sspp,
-               .mixer_count = ARRAY_SIZE(sc7280_lm),
-               .mixer = sc7280_lm,
-               .pingpong_count = ARRAY_SIZE(sc7280_pp),
-               .pingpong = sc7280_pp,
-               .intf_count = ARRAY_SIZE(sc7280_intf),
-               .intf = sc7280_intf,
-               .vbif_count = ARRAY_SIZE(sdm845_vbif),
-               .vbif = sdm845_vbif,
-               .perf = sc7280_perf_data,
-               .mdss_irqs = IRQ_SC7280_MASK,
-       };
-}
-
-
-/*
- * 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_cfg msm8998_dpu_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,
+};
+
+static const struct dpu_mdss_cfg sdm845_dpu_cfg = {
+       .caps = &sdm845_dpu_caps,
+       .mdp_count = ARRAY_SIZE(sdm845_mdp),
+       .mdp = sdm845_mdp,
+       .ctl_count = ARRAY_SIZE(sdm845_ctl),
+       .ctl = sdm845_ctl,
+       .sspp_count = ARRAY_SIZE(sdm845_sspp),
+       .sspp = sdm845_sspp,
+       .mixer_count = ARRAY_SIZE(sdm845_lm),
+       .mixer = sdm845_lm,
+       .pingpong_count = ARRAY_SIZE(sdm845_pp),
+       .pingpong = sdm845_pp,
+       .dsc_count = ARRAY_SIZE(sdm845_dsc),
+       .dsc = sdm845_dsc,
+       .intf_count = ARRAY_SIZE(sdm845_intf),
+       .intf = sdm845_intf,
+       .vbif_count = ARRAY_SIZE(sdm845_vbif),
+       .vbif = sdm845_vbif,
+       .reg_dma_count = 1,
+       .dma_cfg = &sdm845_regdma,
+       .perf = &sdm845_perf_data,
+       .mdss_irqs = IRQ_SDM845_MASK,
+};
+
+static const struct dpu_mdss_cfg sc7180_dpu_cfg = {
+       .caps = &sc7180_dpu_caps,
+       .mdp_count = ARRAY_SIZE(sc7180_mdp),
+       .mdp = sc7180_mdp,
+       .ctl_count = ARRAY_SIZE(sc7180_ctl),
+       .ctl = sc7180_ctl,
+       .sspp_count = ARRAY_SIZE(sc7180_sspp),
+       .sspp = sc7180_sspp,
+       .mixer_count = ARRAY_SIZE(sc7180_lm),
+       .mixer = sc7180_lm,
+       .dspp_count = ARRAY_SIZE(sc7180_dspp),
+       .dspp = sc7180_dspp,
+       .pingpong_count = ARRAY_SIZE(sc7180_pp),
+       .pingpong = sc7180_pp,
+       .intf_count = ARRAY_SIZE(sc7180_intf),
+       .intf = sc7180_intf,
+       .wb_count = ARRAY_SIZE(sm8250_wb),
+       .wb = sm8250_wb,
+       .vbif_count = ARRAY_SIZE(sdm845_vbif),
+       .vbif = sdm845_vbif,
+       .reg_dma_count = 1,
+       .dma_cfg = &sdm845_regdma,
+       .perf = &sc7180_perf_data,
+       .mdss_irqs = IRQ_SC7180_MASK,
+};
+
+static const struct dpu_mdss_cfg sm8150_dpu_cfg = {
+       .caps = &sm8150_dpu_caps,
+       .mdp_count = ARRAY_SIZE(sdm845_mdp),
+       .mdp = sdm845_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,
+       .dspp_count = ARRAY_SIZE(sm8150_dspp),
+       .dspp = sm8150_dspp,
+       .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(sm8150_intf),
+       .intf = sm8150_intf,
+       .vbif_count = ARRAY_SIZE(sdm845_vbif),
+       .vbif = sdm845_vbif,
+       .reg_dma_count = 1,
+       .dma_cfg = &sm8150_regdma,
+       .perf = &sm8150_perf_data,
+       .mdss_irqs = IRQ_SDM845_MASK,
+};
+
+static const struct dpu_mdss_cfg sc8180x_dpu_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,
+};
+
+static const struct dpu_mdss_cfg sm8250_dpu_cfg = {
+       .caps = &sm8250_dpu_caps,
+       .mdp_count = ARRAY_SIZE(sm8250_mdp),
+       .mdp = sm8250_mdp,
+       .ctl_count = ARRAY_SIZE(sm8150_ctl),
+       .ctl = sm8150_ctl,
+       .sspp_count = ARRAY_SIZE(sm8250_sspp),
+       .sspp = sm8250_sspp,
+       .mixer_count = ARRAY_SIZE(sm8150_lm),
+       .mixer = sm8150_lm,
+       .dspp_count = ARRAY_SIZE(sm8150_dspp),
+       .dspp = sm8150_dspp,
+       .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(sm8150_intf),
+       .intf = sm8150_intf,
+       .vbif_count = ARRAY_SIZE(sdm845_vbif),
+       .vbif = sdm845_vbif,
+       .wb_count = ARRAY_SIZE(sm8250_wb),
+       .wb = sm8250_wb,
+       .reg_dma_count = 1,
+       .dma_cfg = &sm8250_regdma,
+       .perf = &sm8250_perf_data,
+       .mdss_irqs = IRQ_SM8250_MASK,
+};
+
+static const struct dpu_mdss_cfg sc7280_dpu_cfg = {
+       .caps = &sc7280_dpu_caps,
+       .mdp_count = ARRAY_SIZE(sc7280_mdp),
+       .mdp = sc7280_mdp,
+       .ctl_count = ARRAY_SIZE(sc7280_ctl),
+       .ctl = sc7280_ctl,
+       .sspp_count = ARRAY_SIZE(sc7280_sspp),
+       .sspp = sc7280_sspp,
+       .dspp_count = ARRAY_SIZE(sc7180_dspp),
+       .dspp = sc7180_dspp,
+       .mixer_count = ARRAY_SIZE(sc7280_lm),
+       .mixer = sc7280_lm,
+       .pingpong_count = ARRAY_SIZE(sc7280_pp),
+       .pingpong = sc7280_pp,
+       .intf_count = ARRAY_SIZE(sc7280_intf),
+       .intf = sc7280_intf,
+       .vbif_count = ARRAY_SIZE(sdm845_vbif),
+       .vbif = sdm845_vbif,
+       .perf = &sc7280_perf_data,
+       .mdss_irqs = IRQ_SC7280_MASK,
+};
+
+static const struct dpu_mdss_cfg qcm2290_dpu_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},
-};
-
-void dpu_hw_catalog_deinit(struct dpu_mdss_cfg *dpu_cfg)
-{
-       kfree(dpu_cfg);
-}
-
-struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev)
+       { .hw_rev = DPU_HW_VER_300, .dpu_cfg = &msm8998_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_301, .dpu_cfg = &msm8998_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_400, .dpu_cfg = &sdm845_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_401, .dpu_cfg = &sdm845_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_500, .dpu_cfg = &sm8150_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_501, .dpu_cfg = &sm8150_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_510, .dpu_cfg = &sc8180x_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_600, .dpu_cfg = &sm8250_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_620, .dpu_cfg = &sc7180_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_650, .dpu_cfg = &qcm2290_dpu_cfg},
+       { .hw_rev = DPU_HW_VER_720, .dpu_cfg = &sc7280_dpu_cfg},
+};
+
+const struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev)
 {
        int i;
        struct dpu_mdss_cfg *dpu_cfg;
@@ -1995,15 +1946,12 @@ struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev)
                return ERR_PTR(-ENOMEM);
 
        for (i = 0; i < ARRAY_SIZE(cfg_handler); i++) {
-               if (cfg_handler[i].hw_rev == hw_rev) {
-                       cfg_handler[i].cfg_init(dpu_cfg);
-                       dpu_cfg->hwversion = hw_rev;
-                       return dpu_cfg;
-               }
+               if (cfg_handler[i].hw_rev == hw_rev)
+                       return cfg_handler[i].dpu_cfg;
        }
 
        DPU_ERROR("unsupported chipset id:%X\n", hw_rev);
-       dpu_hw_catalog_deinit(dpu_cfg);
+
        return ERR_PTR(-ENODEV);
 }
 
index 8cb6d1f..71fe4c5 100644 (file)
@@ -145,6 +145,7 @@ enum {
  * @DPU_MIXER_SOURCESPLIT     Layer mixer supports source-split configuration
  * @DPU_MIXER_GC              Gamma correction block
  * @DPU_DIM_LAYER             Layer mixer supports dim layer
+ * @DPU_MIXER_COMBINED_ALPHA  Layer mixer has combined alpha register
  * @DPU_MIXER_MAX             maximum value
  */
 enum {
@@ -152,6 +153,7 @@ enum {
        DPU_MIXER_SOURCESPLIT,
        DPU_MIXER_GC,
        DPU_DIM_LAYER,
+       DPU_MIXER_COMBINED_ALPHA,
        DPU_MIXER_MAX
 };
 
@@ -707,6 +709,7 @@ struct dpu_vbif_qos_tbl {
  * @ot_rd_limit        default OT read limit
  * @ot_wr_limit        default OT write limit
  * @xin_halt_timeout   maximum time (in usec) for xin to halt
+ * @qos_rp_remap_size  size of VBIF_XINL_QOS_RP_REMAP register space
  * @dynamic_ot_rd_tbl  dynamic OT read configuration table
  * @dynamic_ot_wr_tbl  dynamic OT write configuration table
  * @qos_rt_tbl         real-time QoS priority table
@@ -719,6 +722,7 @@ struct dpu_vbif_cfg {
        u32 default_ot_rd_limit;
        u32 default_ot_wr_limit;
        u32 xin_halt_timeout;
+       u32 qos_rp_remap_size;
        struct dpu_vbif_dynamic_ot_tbl dynamic_ot_rd_tbl;
        struct dpu_vbif_dynamic_ot_tbl dynamic_ot_wr_tbl;
        struct dpu_vbif_qos_tbl qos_rt_tbl;
@@ -822,8 +826,6 @@ struct dpu_perf_cfg {
  * @mdss_irqs:         Bitmap with the irqs supported by the target
  */
 struct dpu_mdss_cfg {
-       u32 hwversion;
-
        const struct dpu_caps *caps;
 
        u32 mdp_count;
@@ -857,7 +859,7 @@ struct dpu_mdss_cfg {
        const struct dpu_wb_cfg *wb;
 
        u32 reg_dma_count;
-       struct dpu_reg_dma_cfg dma_cfg;
+       const struct dpu_reg_dma_cfg *dma_cfg;
 
        u32 ad_count;
 
@@ -866,7 +868,7 @@ struct dpu_mdss_cfg {
 
        /* Add additional block data structures here */
 
-       struct dpu_perf_cfg perf;
+       const struct dpu_perf_cfg *perf;
        const struct dpu_format_extended *dma_formats;
        const struct dpu_format_extended *cursor_formats;
        const struct dpu_format_extended *vig_formats;
@@ -876,7 +878,7 @@ struct dpu_mdss_cfg {
 
 struct dpu_mdss_hw_cfg_handler {
        u32 hw_rev;
-       void (*cfg_init)(struct dpu_mdss_cfg *dpu_cfg);
+       const struct dpu_mdss_cfg *dpu_cfg;
 };
 
 /**
@@ -886,12 +888,6 @@ struct dpu_mdss_hw_cfg_handler {
  *
  * Return: dpu config structure
  */
-struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev);
-
-/**
- * dpu_hw_catalog_deinit - dpu hardware catalog cleanup
- * @dpu_cfg:      pointer returned from init function
- */
-void dpu_hw_catalog_deinit(struct dpu_mdss_cfg *dpu_cfg);
+const struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev);
 
 #endif /* _DPU_HW_CATALOG_H */
index c33e7ef..7d416bf 100644 (file)
@@ -61,7 +61,6 @@ static const struct dpu_ctl_cfg *_ctl_offset(enum dpu_ctl ctl,
                        b->base_off = addr;
                        b->blk_off = m->ctl[i].base;
                        b->length = m->ctl[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_CTL;
                        return &m->ctl[i];
                }
index 4ad8991..184a1b2 100644 (file)
@@ -158,7 +158,7 @@ static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
 }
 
 static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
-                                      struct dpu_mdss_cfg *m,
+                                      const struct dpu_mdss_cfg *m,
                                       void __iomem *addr,
                                       struct dpu_hw_blk_reg_map *b)
 {
@@ -169,7 +169,6 @@ static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
                        b->base_off = addr;
                        b->blk_off = m->dsc[i].base;
                        b->length = m->dsc[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_DSC;
                        return &m->dsc[i];
                }
@@ -187,7 +186,7 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
 };
 
 struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
-                                  struct dpu_mdss_cfg *m)
+                                  const struct dpu_mdss_cfg *m)
 {
        struct dpu_hw_dsc *c;
        struct dpu_dsc_cfg *cfg;
index b39ee4e..45e4118 100644 (file)
@@ -64,7 +64,7 @@ struct dpu_hw_dsc {
  * Returns: Error code or allocated dpu_hw_dsc context
  */
 struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
-                                  struct dpu_mdss_cfg *m);
+                                  const struct dpu_mdss_cfg *m);
 
 /**
  * dpu_hw_dsc_destroy - destroys dsc driver context
index 355894a..3e63bf4 100644 (file)
@@ -83,7 +83,6 @@ static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
                        b->base_off = addr;
                        b->blk_off = m->dspp[i].base;
                        b->length = m->dspp[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_DSPP;
                        return &m->dspp[i];
                }
index 61284e6..d83503e 100644 (file)
@@ -398,16 +398,15 @@ u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx)
        return intr_status;
 }
 
-static void __intr_offset(struct dpu_mdss_cfg *m,
+static void __intr_offset(const struct dpu_mdss_cfg *m,
                void __iomem *addr, struct dpu_hw_blk_reg_map *hw)
 {
        hw->base_off = addr;
        hw->blk_off = m->mdp[0].base;
-       hw->hwversion = m->hwversion;
 }
 
 struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
-               struct dpu_mdss_cfg *m)
+               const struct dpu_mdss_cfg *m)
 {
        struct dpu_hw_intr *intr;
        int nirq = MDP_INTR_MAX * 32;
index 4154c5e..4644395 100644 (file)
@@ -67,7 +67,7 @@ struct dpu_hw_intr {
  * @m :   pointer to mdss catalog data
  */
 struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
-               struct dpu_mdss_cfg *m);
+               const struct dpu_mdss_cfg *m);
 
 /**
  * dpu_hw_intr_destroy(): Cleanup interrutps hw object
index 3f4d2c6..90613f7 100644 (file)
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
 #include "dpu_hwio.h"
@@ -67,6 +69,9 @@
 #define INTF_CFG2_DATABUS_WIDEN        BIT(0)
 #define INTF_CFG2_DATA_HCTL_EN BIT(4)
 
+#define INTF_MISR_CTRL                 0x180
+#define INTF_MISR_SIGNATURE            0x184
+
 static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf,
                const struct dpu_mdss_cfg *m,
                void __iomem *addr,
@@ -80,7 +85,6 @@ static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf,
                        b->base_off = addr;
                        b->blk_off = m->intf[i].base;
                        b->length = m->intf[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_INTF;
                        return &m->intf[i];
                }
@@ -319,6 +323,16 @@ static u32 dpu_hw_intf_get_line_count(struct dpu_hw_intf *intf)
        return DPU_REG_READ(c, INTF_LINE_COUNT);
 }
 
+static void dpu_hw_intf_setup_misr(struct dpu_hw_intf *intf, bool enable, u32 frame_count)
+{
+       dpu_hw_setup_misr(&intf->hw, INTF_MISR_CTRL, enable, frame_count);
+}
+
+static int dpu_hw_intf_collect_misr(struct dpu_hw_intf *intf, u32 *misr_value)
+{
+       return dpu_hw_collect_misr(&intf->hw, INTF_MISR_CTRL, INTF_MISR_SIGNATURE, misr_value);
+}
+
 static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
                unsigned long cap)
 {
@@ -329,6 +343,8 @@ static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
        ops->get_line_count = dpu_hw_intf_get_line_count;
        if (cap & BIT(DPU_INTF_INPUT_CTRL))
                ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk;
+       ops->setup_misr = dpu_hw_intf_setup_misr;
+       ops->collect_misr = dpu_hw_intf_collect_misr;
 }
 
 struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx,
index 7b2d96a..8d0e7b5 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _DPU_HW_INTF_H
@@ -57,6 +59,8 @@ struct intf_status {
  * @ get_line_count: reads current vertical line counter
  * @bind_pingpong_blk: enable/disable the connection with pingpong which will
  *                     feed pixels to this interface
+ * @setup_misr: enable/disable MISR
+ * @collect_misr: read MISR signature
  */
 struct dpu_hw_intf_ops {
        void (*setup_timing_gen)(struct dpu_hw_intf *intf,
@@ -77,6 +81,8 @@ struct dpu_hw_intf_ops {
        void (*bind_pingpong_blk)(struct dpu_hw_intf *intf,
                        bool enable,
                        const enum dpu_pingpong pp);
+       void (*setup_misr)(struct dpu_hw_intf *intf, bool enable, u32 frame_count);
+       int (*collect_misr)(struct dpu_hw_intf *intf, u32 *misr_value);
 };
 
 struct dpu_hw_intf {
index 462f508..f1d2370 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
 
 #define LM_MISR_CTRL                     0x310
 #define LM_MISR_SIGNATURE                0x314
-#define LM_MISR_FRAME_COUNT_MASK         0xFF
-#define LM_MISR_CTRL_ENABLE              BIT(8)
-#define LM_MISR_CTRL_STATUS              BIT(9)
-#define LM_MISR_CTRL_STATUS_CLEAR        BIT(10)
-#define LM_MISR_CTRL_FREE_RUN_MASK     BIT(31)
 
 
 static const struct dpu_lm_cfg *_lm_offset(enum dpu_lm mixer,
@@ -46,7 +42,6 @@ static const struct dpu_lm_cfg *_lm_offset(enum dpu_lm mixer,
                        b->base_off = addr;
                        b->blk_off = m->mixer[i].base;
                        b->length = m->mixer[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_LM;
                        return &m->mixer[i];
                }
@@ -108,47 +103,15 @@ static void dpu_hw_lm_setup_border_color(struct dpu_hw_mixer *ctx,
 
 static void dpu_hw_lm_setup_misr(struct dpu_hw_mixer *ctx, bool enable, u32 frame_count)
 {
-       struct dpu_hw_blk_reg_map *c = &ctx->hw;
-       u32 config = 0;
-
-       DPU_REG_WRITE(c, LM_MISR_CTRL, LM_MISR_CTRL_STATUS_CLEAR);
-
-       /* Clear old MISR value (in case it's read before a new value is calculated)*/
-       wmb();
-
-       if (enable) {
-               config = (frame_count & LM_MISR_FRAME_COUNT_MASK) |
-                       LM_MISR_CTRL_ENABLE | LM_MISR_CTRL_FREE_RUN_MASK;
-
-               DPU_REG_WRITE(c, LM_MISR_CTRL, config);
-       } else {
-               DPU_REG_WRITE(c, LM_MISR_CTRL, 0);
-       }
-
+       dpu_hw_setup_misr(&ctx->hw, LM_MISR_CTRL, enable, frame_count);
 }
 
 static int dpu_hw_lm_collect_misr(struct dpu_hw_mixer *ctx, u32 *misr_value)
 {
-       struct dpu_hw_blk_reg_map *c = &ctx->hw;
-       u32 ctrl = 0;
-
-       if (!misr_value)
-               return -EINVAL;
-
-       ctrl = DPU_REG_READ(c, LM_MISR_CTRL);
-
-       if (!(ctrl & LM_MISR_CTRL_ENABLE))
-               return -ENODATA;
-
-       if (!(ctrl & LM_MISR_CTRL_STATUS))
-               return -EINVAL;
-
-       *misr_value = DPU_REG_READ(c, LM_MISR_SIGNATURE);
-
-       return 0;
+       return dpu_hw_collect_misr(&ctx->hw, LM_MISR_CTRL, LM_MISR_SIGNATURE, misr_value);
 }
 
-static void dpu_hw_lm_setup_blend_config_sdm845(struct dpu_hw_mixer *ctx,
+static void dpu_hw_lm_setup_blend_config_combined_alpha(struct dpu_hw_mixer *ctx,
        u32 stage, u32 fg_alpha, u32 bg_alpha, u32 blend_op)
 {
        struct dpu_hw_blk_reg_map *c = &ctx->hw;
@@ -204,8 +167,8 @@ static void _setup_mixer_ops(const struct dpu_mdss_cfg *m,
                unsigned long features)
 {
        ops->setup_mixer_out = dpu_hw_lm_setup_out;
-       if (m->hwversion >= DPU_HW_VER_400)
-               ops->setup_blend_config = dpu_hw_lm_setup_blend_config_sdm845;
+       if (test_bit(DPU_MIXER_COMBINED_ALPHA, &features))
+               ops->setup_blend_config = dpu_hw_lm_setup_blend_config_combined_alpha;
        else
                ops->setup_blend_config = dpu_hw_lm_setup_blend_config;
        ops->setup_alpha_out = dpu_hw_lm_setup_color3;
index c06d595..b053d68 100644 (file)
@@ -26,7 +26,6 @@ static const struct dpu_merge_3d_cfg *_merge_3d_offset(enum dpu_merge_3d idx,
                        b->base_off = addr;
                        b->blk_off = m->merge_3d[i].base;
                        b->length = m->merge_3d[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_PINGPONG;
                        return &m->merge_3d[i];
                }
index 47c6ab6..6538e19 100644 (file)
@@ -54,7 +54,6 @@ static const struct dpu_pingpong_cfg *_pingpong_offset(enum dpu_pingpong pp,
                        b->base_off = addr;
                        b->blk_off = m->pingpong[i].base;
                        b->length = m->pingpong[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_PINGPONG;
                        return &m->pingpong[i];
                }
index 0a0864d..da4c7e4 100644 (file)
@@ -761,7 +761,7 @@ int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms *kms,
 
 static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
                void __iomem *addr,
-               struct dpu_mdss_cfg *catalog,
+               const struct dpu_mdss_cfg *catalog,
                struct dpu_hw_blk_reg_map *b)
 {
        int i;
@@ -772,7 +772,6 @@ static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
                                b->base_off = addr;
                                b->blk_off = catalog->sspp[i].base;
                                b->length = catalog->sspp[i].len;
-                               b->hwversion = catalog->hwversion;
                                b->log_mask = DPU_DBG_MASK_SSPP;
                                return &catalog->sspp[i];
                        }
@@ -783,7 +782,7 @@ static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
 }
 
 struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
-               void __iomem *addr, struct dpu_mdss_cfg *catalog,
+               void __iomem *addr, const struct dpu_mdss_cfg *catalog,
                bool is_virtual_pipe)
 {
        struct dpu_hw_pipe *hw_pipe;
index a81e166..7f7338f 100644 (file)
@@ -360,7 +360,7 @@ struct dpu_hw_sspp_ops {
 struct dpu_hw_pipe {
        struct dpu_hw_blk base;
        struct dpu_hw_blk_reg_map hw;
-       struct dpu_mdss_cfg *catalog;
+       const struct dpu_mdss_cfg *catalog;
        const struct dpu_mdp_cfg *mdp;
 
        /* Pipe */
@@ -381,7 +381,7 @@ struct dpu_kms;
  * @is_virtual_pipe: is this pipe virtual pipe
  */
 struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
-               void __iomem *addr, struct dpu_mdss_cfg *catalog,
+               void __iomem *addr, const struct dpu_mdss_cfg *catalog,
                bool is_virtual_pipe);
 
 /**
index ab3ef16..12d3b00 100644 (file)
@@ -288,7 +288,6 @@ static const struct dpu_mdp_cfg *_top_offset(enum dpu_mdp mdp,
                        b->base_off = addr;
                        b->blk_off = m->mdp[i].base;
                        b->length = m->mdp[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_TOP;
                        return &m->mdp[i];
                }
index 512316f..a679757 100644 (file)
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 #define pr_fmt(fmt)    "[drm:%s:%d] " fmt, __func__, __LINE__
 
@@ -447,3 +449,48 @@ u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
 
        return 0;
 }
+
+void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c,
+               u32 misr_ctrl_offset,
+               bool enable, u32 frame_count)
+{
+       u32 config = 0;
+
+       DPU_REG_WRITE(c, misr_ctrl_offset, MISR_CTRL_STATUS_CLEAR);
+
+       /* Clear old MISR value (in case it's read before a new value is calculated)*/
+       wmb();
+
+       if (enable) {
+               config = (frame_count & MISR_FRAME_COUNT_MASK) |
+                       MISR_CTRL_ENABLE | MISR_CTRL_FREE_RUN_MASK;
+
+               DPU_REG_WRITE(c, misr_ctrl_offset, config);
+       } else {
+               DPU_REG_WRITE(c, misr_ctrl_offset, 0);
+       }
+
+}
+
+int dpu_hw_collect_misr(struct dpu_hw_blk_reg_map *c,
+               u32 misr_ctrl_offset,
+               u32 misr_signature_offset,
+               u32 *misr_value)
+{
+       u32 ctrl = 0;
+
+       if (!misr_value)
+               return -EINVAL;
+
+       ctrl = DPU_REG_READ(c, misr_ctrl_offset);
+
+       if (!(ctrl & MISR_CTRL_ENABLE))
+               return -ENODATA;
+
+       if (!(ctrl & MISR_CTRL_STATUS))
+               return -EINVAL;
+
+       *misr_value = DPU_REG_READ(c, misr_signature_offset);
+
+       return 0;
+}
index e4a65eb..ca74474 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
 #include "dpu_hw_catalog.h"
 
 #define REG_MASK(n)                     ((BIT(n)) - 1)
+#define MISR_FRAME_COUNT_MASK           0xFF
+#define MISR_CTRL_ENABLE                BIT(8)
+#define MISR_CTRL_STATUS                BIT(9)
+#define MISR_CTRL_STATUS_CLEAR          BIT(10)
+#define MISR_CTRL_FREE_RUN_MASK         BIT(31)
 
 /*
  * This is the common struct maintained by each sub block
  * @blk_off:      pipe offset relative to mdss offset
  * @length        length of register block offset
  * @xin_id        xin id
- * @hwversion     mdss hw version number
  */
 struct dpu_hw_blk_reg_map {
        void __iomem *base_off;
        u32 blk_off;
        u32 length;
        u32 xin_id;
-       u32 hwversion;
        u32 log_mask;
 };
 
@@ -343,4 +347,14 @@ void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map  *c,
 u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
                u32 total_fl);
 
+void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c,
+               u32 misr_ctrl_offset,
+               bool enable,
+               u32 frame_count);
+
+int dpu_hw_collect_misr(struct dpu_hw_blk_reg_map *c,
+               u32 misr_ctrl_offset,
+               u32 misr_signature_offset,
+               u32 *misr_value);
+
 #endif /* _DPU_HW_UTIL_H */
index b757054..789ecc5 100644 (file)
@@ -30,7 +30,7 @@
 #define VBIF_XIN_HALT_CTRL0            0x0200
 #define VBIF_XIN_HALT_CTRL1            0x0204
 #define VBIF_XINL_QOS_RP_REMAP_000     0x0550
-#define VBIF_XINL_QOS_LVL_REMAP_000(v) (v < DPU_HW_VER_400 ? 0x570 : 0x0590)
+#define VBIF_XINL_QOS_LVL_REMAP_000(vbif)      (VBIF_XINL_QOS_RP_REMAP_000 + (vbif)->cap->qos_rp_remap_size)
 
 static void dpu_hw_clear_errors(struct dpu_hw_vbif *vbif,
                u32 *pnd_errors, u32 *src_errors)
@@ -163,7 +163,7 @@ static void dpu_hw_set_qos_remap(struct dpu_hw_vbif *vbif,
 
        c = &vbif->hw;
 
-       reg_lvl = VBIF_XINL_QOS_LVL_REMAP_000(c->hwversion);
+       reg_lvl = VBIF_XINL_QOS_LVL_REMAP_000(vbif);
        reg_high = ((xin_id & 0x8) >> 3) * 4 + (level * 8);
        reg_shift = (xin_id & 0x7) * 4;
 
@@ -223,7 +223,6 @@ static const struct dpu_vbif_cfg *_top_offset(enum dpu_vbif vbif,
                        b->base_off = addr;
                        b->blk_off = m->vbif[i].base;
                        b->length = m->vbif[i].len;
-                       b->hwversion = m->hwversion;
                        b->log_mask = DPU_DBG_MASK_VBIF;
                        return &m->vbif[i];
                }
index bcccce2..084439f 100644 (file)
@@ -63,7 +63,6 @@ static const struct dpu_wb_cfg *_wb_offset(enum dpu_wb wb,
                        b->base_off = addr;
                        b->blk_off = m->wb[i].base;
                        b->length = m->wb[i].len;
-                       b->hwversion = m->hwversion;
                        return &m->wb[i];
                }
        }
index e23e255..a2d71f0 100644 (file)
@@ -582,9 +582,7 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
                }
 
                info.h_tile_instance[info.num_of_h_tiles++] = i;
-               info.capabilities = msm_dsi_is_cmd_mode(priv->dsi[i]) ?
-                       MSM_DISPLAY_CAP_CMD_MODE :
-                       MSM_DISPLAY_CAP_VID_MODE;
+               info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]);
 
                info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]);
 
@@ -637,7 +635,6 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev,
 
                info.num_of_h_tiles = 1;
                info.h_tile_instance[0] = i;
-               info.capabilities = MSM_DISPLAY_CAP_VID_MODE;
                info.intf_type = encoder->encoder_type;
                rc = dpu_encoder_setup(dev, encoder, &info);
                if (rc) {
@@ -745,7 +742,7 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
        unsigned int num_encoders;
 
        struct msm_drm_private *priv;
-       struct dpu_mdss_cfg *catalog;
+       const struct dpu_mdss_cfg *catalog;
 
        int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
        int max_crtc_count;
@@ -842,8 +839,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
                dpu_rm_destroy(&dpu_kms->rm);
        dpu_kms->rm_init = false;
 
-       if (dpu_kms->catalog)
-               dpu_hw_catalog_deinit(dpu_kms->catalog);
        dpu_kms->catalog = NULL;
 
        if (dpu_kms->vbif[VBIF_NRT])
@@ -905,7 +900,7 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k
 {
        int i;
        struct dpu_kms *dpu_kms;
-       struct dpu_mdss_cfg *cat;
+       const struct dpu_mdss_cfg *cat;
        struct dpu_hw_mdp *top;
 
        dpu_kms = to_dpu_kms(kms);
index 832a076..ed80ed6 100644 (file)
@@ -69,7 +69,7 @@ struct dpu_kms {
        struct msm_kms base;
        struct drm_device *dev;
        int core_rev;
-       struct dpu_mdss_cfg *catalog;
+       const struct dpu_mdss_cfg *catalog;
 
        /* io/register spaces: */
        void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma;
index 5b5aef2..7899418 100644 (file)
@@ -106,7 +106,7 @@ struct dpu_plane {
        bool is_rt_pipe;
        bool is_virtual;
        struct list_head mplane_list;
-       struct dpu_mdss_cfg *catalog;
+       const struct dpu_mdss_cfg *catalog;
 };
 
 static const uint64_t supported_format_modifiers[] = {
@@ -160,7 +160,7 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane,
        vbp = mode->vtotal - mode->vsync_end;
        vpw = mode->vsync_end - mode->vsync_start;
        vfp = mode->vsync_start - mode->vdisplay;
-       hw_latency_lines =  dpu_kms->catalog->perf.min_prefill_lines;
+       hw_latency_lines =  dpu_kms->catalog->perf->min_prefill_lines;
        scale_factor = src_height > dst_height ?
                mult_frac(src_height, 1, dst_height) : 1;
 
@@ -309,7 +309,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
        }
 
        qos_lut = _dpu_hw_get_qos_lut(
-                       &pdpu->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
+                       &pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl);
 
        trace_dpu_perf_set_qos_luts(pdpu->pipe - SSPP_VIG0,
                        (fmt) ? fmt->base.pixel_format : 0,
@@ -336,9 +336,9 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
        u32 danger_lut, safe_lut;
 
        if (!pdpu->is_rt_pipe) {
-               danger_lut = pdpu->catalog->perf.danger_lut_tbl
+               danger_lut = pdpu->catalog->perf->danger_lut_tbl
                                [DPU_QOS_LUT_USAGE_NRT];
-               safe_lut = pdpu->catalog->perf.safe_lut_tbl
+               safe_lut = pdpu->catalog->perf->safe_lut_tbl
                                [DPU_QOS_LUT_USAGE_NRT];
        } else {
                fmt = dpu_get_dpu_format_ext(
@@ -346,14 +346,14 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
                                fb->modifier);
 
                if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) {
-                       danger_lut = pdpu->catalog->perf.danger_lut_tbl
+                       danger_lut = pdpu->catalog->perf->danger_lut_tbl
                                        [DPU_QOS_LUT_USAGE_LINEAR];
-                       safe_lut = pdpu->catalog->perf.safe_lut_tbl
+                       safe_lut = pdpu->catalog->perf->safe_lut_tbl
                                        [DPU_QOS_LUT_USAGE_LINEAR];
                } else {
-                       danger_lut = pdpu->catalog->perf.danger_lut_tbl
+                       danger_lut = pdpu->catalog->perf->danger_lut_tbl
                                        [DPU_QOS_LUT_USAGE_MACROTILE];
-                       safe_lut = pdpu->catalog->perf.safe_lut_tbl
+                       safe_lut = pdpu->catalog->perf->safe_lut_tbl
                                        [DPU_QOS_LUT_USAGE_MACROTILE];
                }
        }
@@ -1225,7 +1225,7 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
 
                        memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));
 
-                       cdp_cfg.enable = pdpu->catalog->perf.cdp_cfg
+                       cdp_cfg.enable = pdpu->catalog->perf->cdp_cfg
                                        [DPU_PERF_CDP_USAGE_RT].rd_enable;
                        cdp_cfg.ubwc_meta_enable =
                                        DPU_FORMAT_IS_UBWC(fmt);
index 06f03e7..73b3442 100644 (file)
@@ -95,7 +95,7 @@ int dpu_rm_destroy(struct dpu_rm *rm)
 }
 
 int dpu_rm_init(struct dpu_rm *rm,
-               struct dpu_mdss_cfg *cat,
+               const struct dpu_mdss_cfg *cat,
                void __iomem *mmio)
 {
        int rc, i;
index 2f34a31..59de72b 100644 (file)
@@ -42,7 +42,7 @@ struct dpu_rm {
  * @Return: 0 on Success otherwise -ERROR
  */
 int dpu_rm_init(struct dpu_rm *rm,
-               struct dpu_mdss_cfg *cat,
+               const struct dpu_mdss_cfg *cat,
                void __iomem *mmio);
 
 /**
index 17cb1fc..964573d 100644 (file)
@@ -13,8 +13,6 @@
 #include "msm_mmu.h"
 #include "mdp4_kms.h"
 
-static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev);
-
 static int mdp4_hw_init(struct msm_kms *kms)
 {
        struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
@@ -386,13 +384,17 @@ static void read_mdp_hw_revision(struct mdp4_kms *mdp4_kms,
 static int mdp4_kms_init(struct drm_device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev->dev);
-       struct mdp4_platform_config *config = mdp4_get_config(pdev);
        struct msm_drm_private *priv = dev->dev_private;
        struct mdp4_kms *mdp4_kms;
        struct msm_kms *kms = NULL;
+       struct iommu_domain *iommu;
        struct msm_gem_address_space *aspace;
        int irq, ret;
        u32 major, minor;
+       unsigned long max_clk;
+
+       /* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */
+       max_clk = 266667000;
 
        mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
        if (!mdp4_kms) {
@@ -460,7 +462,7 @@ static int mdp4_kms_init(struct drm_device *dev)
                goto fail;
        }
 
-       clk_set_rate(mdp4_kms->clk, config->max_clk);
+       clk_set_rate(mdp4_kms->clk, max_clk);
 
        read_mdp_hw_revision(mdp4_kms, &major, &minor);
 
@@ -480,7 +482,7 @@ static int mdp4_kms_init(struct drm_device *dev)
                        ret = PTR_ERR(mdp4_kms->lut_clk);
                        goto fail;
                }
-               clk_set_rate(mdp4_kms->lut_clk, config->max_clk);
+               clk_set_rate(mdp4_kms->lut_clk, max_clk);
        }
 
        pm_runtime_enable(dev->dev);
@@ -497,9 +499,9 @@ static int mdp4_kms_init(struct drm_device *dev)
        mdp4_disable(mdp4_kms);
        mdelay(16);
 
-       if (config->iommu) {
-               struct msm_mmu *mmu = msm_iommu_new(&pdev->dev,
-                       config->iommu);
+       iommu = iommu_domain_alloc(pdev->dev.bus);
+       if (iommu) {
+               struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, iommu);
 
                aspace  = msm_gem_address_space_create(mmu,
                        "mdp4", 0x1000, 0x100000000 - 0x1000);
@@ -553,17 +555,6 @@ fail:
        return ret;
 }
 
-static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
-{
-       static struct mdp4_platform_config config = {};
-
-       /* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */
-       config.max_clk = 266667000;
-       config.iommu = iommu_domain_alloc(&platform_bus_type);
-
-       return &config;
-}
-
 static const struct dev_pm_ops mdp4_pm_ops = {
        .prepare = msm_pm_prepare,
        .complete = msm_pm_complete,
index e8ee92a..01179e7 100644 (file)
@@ -42,12 +42,6 @@ struct mdp4_kms {
 };
 #define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
 
-/* platform config data (ie. from DT, or pdata) */
-struct mdp4_platform_config {
-       struct iommu_domain *iommu;
-       uint32_t max_clk;
-};
-
 static inline void mdp4_write(struct mdp4_kms *mdp4_kms, u32 reg, u32 data)
 {
        msm_writel(data, mdp4_kms->mmio + reg);
index 1bf9ff5..b17f868 100644 (file)
@@ -837,6 +837,11 @@ static const struct mdp5_cfg_hw msm8x53_config = {
                        [2] = INTF_DSI,
                },
        },
+       .perf = {
+               .ab_inefficiency = 100,
+               .ib_inefficiency = 200,
+               .clk_inefficiency = 105
+       },
        .max_clk = 400000000,
 };
 
index a95d5df..bab2634 100644 (file)
@@ -1080,12 +1080,32 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
 
 static void dsi_sw_reset(struct msm_dsi_host *msm_host)
 {
+       u32 ctrl;
+
+       ctrl = dsi_read(msm_host, REG_DSI_CTRL);
+
+       if (ctrl & DSI_CTRL_ENABLE) {
+               dsi_write(msm_host, REG_DSI_CTRL, ctrl & ~DSI_CTRL_ENABLE);
+               /*
+                * dsi controller need to be disabled before
+                * clocks turned on
+                */
+               wmb();
+       }
+
        dsi_write(msm_host, REG_DSI_CLK_CTRL, DSI_CLK_CTRL_ENABLE_CLKS);
        wmb(); /* clocks need to be enabled before reset */
 
+       /* dsi controller can only be reset while clocks are running */
        dsi_write(msm_host, REG_DSI_RESET, 1);
        msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */
        dsi_write(msm_host, REG_DSI_RESET, 0);
+       wmb(); /* controller out of reset */
+
+       if (ctrl & DSI_CTRL_ENABLE) {
+               dsi_write(msm_host, REG_DSI_CTRL, ctrl);
+               wmb();  /* make sure dsi controller enabled again */
+       }
 }
 
 static void dsi_op_mode_config(struct msm_dsi_host *msm_host,
@@ -1478,32 +1498,6 @@ static int dsi_cmds2buf_tx(struct msm_dsi_host *msm_host,
        return len;
 }
 
-static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host)
-{
-       u32 data0, data1;
-
-       data0 = dsi_read(msm_host, REG_DSI_CTRL);
-       data1 = data0;
-       data1 &= ~DSI_CTRL_ENABLE;
-       dsi_write(msm_host, REG_DSI_CTRL, data1);
-       /*
-        * dsi controller need to be disabled before
-        * clocks turned on
-        */
-       wmb();
-
-       dsi_write(msm_host, REG_DSI_CLK_CTRL, DSI_CLK_CTRL_ENABLE_CLKS);
-       wmb();  /* make sure clocks enabled */
-
-       /* dsi controller can only be reset while clocks are running */
-       dsi_write(msm_host, REG_DSI_RESET, 1);
-       msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */
-       dsi_write(msm_host, REG_DSI_RESET, 0);
-       wmb();  /* controller out of reset */
-       dsi_write(msm_host, REG_DSI_CTRL, data0);
-       wmb();  /* make sure dsi controller enabled again */
-}
-
 static void dsi_hpd_worker(struct work_struct *work)
 {
        struct msm_dsi_host *msm_host =
@@ -1520,7 +1514,7 @@ static void dsi_err_worker(struct work_struct *work)
 
        pr_err_ratelimited("%s: status=%x\n", __func__, status);
        if (status & DSI_ERR_STATE_MDP_FIFO_UNDERFLOW)
-               dsi_sw_reset_restore(msm_host);
+               dsi_sw_reset(msm_host);
 
        /* It is safe to clear here because error irq is disabled. */
        msm_host->err_work_state = 0;
index cf24e68..93fe61b 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/of_gpio.h>
 
 #include <drm/drm_bridge_connector.h>
+#include <drm/drm_of.h>
 
 #include <sound/hdmi-codec.h>
 #include "hdmi.h"
@@ -133,6 +134,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
        hdmi->config = config;
        spin_lock_init(&hdmi->reg_lock);
 
+       ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge);
+       if (ret && ret != -ENODEV)
+               goto fail;
+
        hdmi->mmio = msm_ioremap(pdev, config->mmio_name);
        if (IS_ERR(hdmi->mmio)) {
                ret = PTR_ERR(hdmi->mmio);
@@ -180,6 +185,9 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
                goto fail;
        }
 
+       for (i = 0; i < config->pwr_reg_cnt; i++)
+               hdmi->pwr_regs[i].supply = config->pwr_reg_names[i];
+
        ret = devm_regulator_bulk_get(&pdev->dev, config->pwr_reg_cnt, hdmi->pwr_regs);
        if (ret) {
                DRM_DEV_ERROR(&pdev->dev, "failed to get pwr regulator: %d\n", ret);
@@ -230,6 +238,20 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
                hdmi->pwr_clks[i] = clk;
        }
 
+       hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
+       /* This will catch e.g. -EPROBE_DEFER */
+       if (IS_ERR(hdmi->hpd_gpiod)) {
+               ret = PTR_ERR(hdmi->hpd_gpiod);
+               DRM_DEV_ERROR(&pdev->dev, "failed to get hpd gpio: (%d)\n", ret);
+               goto fail;
+       }
+
+       if (!hdmi->hpd_gpiod)
+               DBG("failed to get HPD gpio");
+
+       if (hdmi->hpd_gpiod)
+               gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD");
+
        pm_runtime_enable(&pdev->dev);
 
        hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0);
@@ -291,6 +313,15 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
                goto fail;
        }
 
+       if (hdmi->next_bridge) {
+               ret = drm_bridge_attach(hdmi->encoder, hdmi->next_bridge, hdmi->bridge,
+                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+               if (ret) {
+                       DRM_DEV_ERROR(dev->dev, "failed to attach next HDMI bridge: %d\n", ret);
+                       goto fail;
+               }
+       }
+
        hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);
        if (IS_ERR(hdmi->connector)) {
                ret = PTR_ERR(hdmi->connector);
@@ -353,12 +384,7 @@ fail:
        .item ## _names = item ##_names_ ## entry, \
        .item ## _cnt   = ARRAY_SIZE(item ## _names_ ## entry)
 
-static const char *pwr_reg_names_none[] = {};
-static const char *hpd_reg_names_none[] = {};
-
-static struct hdmi_platform_config hdmi_tx_8660_config;
-
-static const char *hpd_reg_names_8960[] = {"core-vdda", "hdmi-mux"};
+static const char *hpd_reg_names_8960[] = {"core-vdda"};
 static const char *hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"};
 
 static struct hdmi_platform_config hdmi_tx_8960_config = {
@@ -367,59 +393,17 @@ static struct hdmi_platform_config hdmi_tx_8960_config = {
 };
 
 static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"};
-static const char *hpd_reg_names_8x74[] = {"hpd-gdsc", "hpd-5v"};
 static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"};
 static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"};
 static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0};
 
 static struct hdmi_platform_config hdmi_tx_8974_config = {
                HDMI_CFG(pwr_reg, 8x74),
-               HDMI_CFG(hpd_reg, 8x74),
                HDMI_CFG(pwr_clk, 8x74),
                HDMI_CFG(hpd_clk, 8x74),
                .hpd_freq      = hpd_clk_freq_8x74,
 };
 
-static const char *hpd_reg_names_8084[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
-
-static struct hdmi_platform_config hdmi_tx_8084_config = {
-               HDMI_CFG(pwr_reg, 8x74),
-               HDMI_CFG(hpd_reg, 8084),
-               HDMI_CFG(pwr_clk, 8x74),
-               HDMI_CFG(hpd_clk, 8x74),
-               .hpd_freq      = hpd_clk_freq_8x74,
-};
-
-static struct hdmi_platform_config hdmi_tx_8994_config = {
-               HDMI_CFG(pwr_reg, 8x74),
-               HDMI_CFG(hpd_reg, none),
-               HDMI_CFG(pwr_clk, 8x74),
-               HDMI_CFG(hpd_clk, 8x74),
-               .hpd_freq      = hpd_clk_freq_8x74,
-};
-
-static struct hdmi_platform_config hdmi_tx_8996_config = {
-               HDMI_CFG(pwr_reg, none),
-               HDMI_CFG(hpd_reg, none),
-               HDMI_CFG(pwr_clk, 8x74),
-               HDMI_CFG(hpd_clk, 8x74),
-               .hpd_freq      = hpd_clk_freq_8x74,
-};
-
-static const struct {
-       const char *name;
-       const bool output;
-       const int value;
-       const char *label;
-} msm_hdmi_gpio_pdata[] = {
-       { "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" },
-       { "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" },
-       { "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" },
-       { "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" },
-       { "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" },
-       { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
-};
-
 /*
  * HDMI audio codec callbacks
  */
@@ -531,7 +515,7 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
        struct hdmi_platform_config *hdmi_cfg;
        struct hdmi *hdmi;
        struct device_node *of_node = dev->of_node;
-       int i, err;
+       int err;
 
        hdmi_cfg = (struct hdmi_platform_config *)
                        of_device_get_match_data(dev);
@@ -543,42 +527,6 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
        hdmi_cfg->mmio_name     = "core_physical";
        hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
 
-       for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
-               const char *name = msm_hdmi_gpio_pdata[i].name;
-               struct gpio_desc *gpiod;
-
-               /*
-                * We are fetching the GPIO lines "as is" since the connector
-                * code is enabling and disabling the lines. Until that point
-                * the power-on default value will be kept.
-                */
-               gpiod = devm_gpiod_get_optional(dev, name, GPIOD_ASIS);
-               /* This will catch e.g. -PROBE_DEFER */
-               if (IS_ERR(gpiod))
-                       return PTR_ERR(gpiod);
-               if (!gpiod) {
-                       /* Try a second time, stripping down the name */
-                       char name3[32];
-
-                       /*
-                        * Try again after stripping out the "qcom,hdmi-tx"
-                        * prefix. This is mainly to match "hpd-gpios" used
-                        * in the upstream bindings.
-                        */
-                       if (sscanf(name, "qcom,hdmi-tx-%s", name3))
-                               gpiod = devm_gpiod_get_optional(dev, name3, GPIOD_ASIS);
-                       if (IS_ERR(gpiod))
-                               return PTR_ERR(gpiod);
-                       if (!gpiod)
-                               DBG("failed to get gpio: %s", name);
-               }
-               hdmi_cfg->gpios[i].gpiod = gpiod;
-               if (gpiod)
-                       gpiod_set_consumer_name(gpiod, msm_hdmi_gpio_pdata[i].label);
-               hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output;
-               hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value;
-       }
-
        dev->platform_data = hdmi_cfg;
 
        hdmi = msm_hdmi_init(to_platform_device(dev));
@@ -626,12 +574,12 @@ static int msm_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id msm_hdmi_dt_match[] = {
-       { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8996_config },
-       { .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8994_config },
-       { .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8084_config },
+       { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8974_config },
+       { .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8974_config },
+       { .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8974_config },
        { .compatible = "qcom,hdmi-tx-8974", .data = &hdmi_tx_8974_config },
        { .compatible = "qcom,hdmi-tx-8960", .data = &hdmi_tx_8960_config },
-       { .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8660_config },
+       { .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8960_config },
        {}
 };
 
index 736f348..04a7438 100644 (file)
 #include "msm_drv.h"
 #include "hdmi.xml.h"
 
-#define HDMI_MAX_NUM_GPIO      6
-
 struct hdmi_phy;
 struct hdmi_platform_config;
 
-struct hdmi_gpio_data {
-       struct gpio_desc *gpiod;
-       bool output;
-       int value;
-};
-
 struct hdmi_audio {
        bool enabled;
        struct hdmi_audio_infoframe infoframe;
@@ -61,6 +53,8 @@ struct hdmi {
        struct clk **hpd_clks;
        struct clk **pwr_clks;
 
+       struct gpio_desc *hpd_gpiod;
+
        struct hdmi_phy *phy;
        struct device *phy_dev;
 
@@ -68,6 +62,8 @@ struct hdmi {
        struct drm_connector *connector;
        struct drm_bridge *bridge;
 
+       struct drm_bridge *next_bridge;
+
        /* the encoder we are hooked to (outside of hdmi block) */
        struct drm_encoder *encoder;
 
@@ -109,9 +105,6 @@ struct hdmi_platform_config {
        /* clks that need to be on for screen pwr (ie pixel clk): */
        const char **pwr_clk_names;
        int pwr_clk_cnt;
-
-       /* gpio's: */
-       struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
 };
 
 struct hdmi_bridge {
index 97c2401..d569f0c 100644 (file)
@@ -159,14 +159,6 @@ static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
                msm_hdmi_hdcp_on(hdmi->hdcp_ctrl);
 }
 
-static void msm_hdmi_bridge_enable(struct drm_bridge *bridge)
-{
-}
-
-static void msm_hdmi_bridge_disable(struct drm_bridge *bridge)
-{
-}
-
 static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge)
 {
        struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
@@ -306,8 +298,6 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge
 
 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
                .pre_enable = msm_hdmi_bridge_pre_enable,
-               .enable = msm_hdmi_bridge_enable,
-               .disable = msm_hdmi_bridge_disable,
                .post_disable = msm_hdmi_bridge_post_disable,
                .mode_set = msm_hdmi_bridge_mode_set,
                .mode_valid = msm_hdmi_bridge_mode_valid,
index 75605dd..bfa827b 100644 (file)
@@ -60,48 +60,6 @@ static void msm_hdmi_phy_reset(struct hdmi *hdmi)
        }
 }
 
-static int gpio_config(struct hdmi *hdmi, bool on)
-{
-       const struct hdmi_platform_config *config = hdmi->config;
-       int i;
-
-       if (on) {
-               for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
-                       struct hdmi_gpio_data gpio = config->gpios[i];
-
-                       if (gpio.gpiod) {
-                               if (gpio.output) {
-                                       gpiod_direction_output(gpio.gpiod,
-                                                              gpio.value);
-                               } else {
-                                       gpiod_direction_input(gpio.gpiod);
-                                       gpiod_set_value_cansleep(gpio.gpiod,
-                                                                gpio.value);
-                               }
-                       }
-               }
-
-               DBG("gpio on");
-       } else {
-               for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
-                       struct hdmi_gpio_data gpio = config->gpios[i];
-
-                       if (!gpio.gpiod)
-                               continue;
-
-                       if (gpio.output) {
-                               int value = gpio.value ? 0 : 1;
-
-                               gpiod_set_value_cansleep(gpio.gpiod, value);
-                       }
-               }
-
-               DBG("gpio off");
-       }
-
-       return 0;
-}
-
 static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
 {
        const struct hdmi_platform_config *config = hdmi->config;
@@ -154,11 +112,8 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
                goto fail;
        }
 
-       ret = gpio_config(hdmi, true);
-       if (ret) {
-               DRM_DEV_ERROR(dev, "failed to configure GPIOs: %d\n", ret);
-               goto fail;
-       }
+       if (hdmi->hpd_gpiod)
+               gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1);
 
        pm_runtime_get_sync(dev);
        enable_hpd_clocks(hdmi, true);
@@ -207,10 +162,6 @@ void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
        enable_hpd_clocks(hdmi, false);
        pm_runtime_put(dev);
 
-       ret = gpio_config(hdmi, false);
-       if (ret)
-               dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret);
-
        ret = pinctrl_pm_select_sleep_state(dev);
        if (ret)
                dev_warn(dev, "pinctrl state chg failed: %d\n", ret);
@@ -269,10 +220,7 @@ static enum drm_connector_status detect_reg(struct hdmi *hdmi)
 #define HPD_GPIO_INDEX 2
 static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
 {
-       const struct hdmi_platform_config *config = hdmi->config;
-       struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
-
-       return gpiod_get_value(hpd_gpio.gpiod) ?
+       return gpiod_get_value(hdmi->hpd_gpiod) ?
                        connector_status_connected :
                        connector_status_disconnected;
 }
@@ -282,8 +230,6 @@ enum drm_connector_status msm_hdmi_bridge_detect(
 {
        struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
        struct hdmi *hdmi = hdmi_bridge->hdmi;
-       const struct hdmi_platform_config *config = hdmi->config;
-       struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
        enum drm_connector_status stat_gpio, stat_reg;
        int retry = 20;
 
@@ -291,7 +237,7 @@ enum drm_connector_status msm_hdmi_bridge_detect(
         * some platforms may not have hpd gpio. Rely only on the status
         * provided by REG_HDMI_HPD_INT_STATUS in this case.
         */
-       if (!hpd_gpio.gpiod)
+       if (!hdmi->hpd_gpiod)
                return detect_reg(hdmi);
 
        do {
index 95f2928..1d97640 100644 (file)
@@ -122,8 +122,20 @@ static void hdmi_phy_8x60_powerdown(struct hdmi_phy *phy)
                       HDMI_8x60_PHY_REG2_PD_DESER);
 }
 
+static const char * const hdmi_phy_8x60_reg_names[] = {
+       "core-vdda",
+};
+
+static const char * const hdmi_phy_8x60_clk_names[] = {
+       "slave_iface",
+};
+
 const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg = {
        .type = MSM_HDMI_PHY_8x60,
        .powerup = hdmi_phy_8x60_powerup,
        .powerdown = hdmi_phy_8x60_powerdown,
+       .reg_names = hdmi_phy_8x60_reg_names,
+       .num_regs = ARRAY_SIZE(hdmi_phy_8x60_reg_names),
+       .clk_names = hdmi_phy_8x60_clk_names,
+       .num_clks = ARRAY_SIZE(hdmi_phy_8x60_clk_names),
 };
index 14ab9a6..57a6609 100644 (file)
@@ -948,7 +948,24 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
        DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
 };
 
-DEFINE_DRM_GEM_FOPS(fops);
+static void msm_fop_show_fdinfo(struct seq_file *m, struct file *f)
+{
+       struct drm_file *file = f->private_data;
+       struct drm_device *dev = file->minor->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       struct drm_printer p = drm_seq_file_printer(m);
+
+       if (!priv->gpu)
+               return;
+
+       msm_gpu_show_fdinfo(priv->gpu, file->driver_priv, &p);
+}
+
+static const struct file_operations fops = {
+       .owner = THIS_MODULE,
+       DRM_GEM_FOPS,
+       .show_fdinfo = msm_fop_show_fdinfo,
+};
 
 static const struct drm_driver msm_driver = {
        .driver_features    = DRIVER_GEM |
index 099a67d..ae49e56 100644 (file)
@@ -62,16 +62,6 @@ enum msm_dp_controller {
 #define MAX_H_TILES_PER_DISPLAY 2
 
 /**
- * enum msm_display_caps - features/capabilities supported by displays
- * @MSM_DISPLAY_CAP_VID_MODE:           Video or "active" mode supported
- * @MSM_DISPLAY_CAP_CMD_MODE:           Command mode supported
- */
-enum msm_display_caps {
-       MSM_DISPLAY_CAP_VID_MODE        = BIT(0),
-       MSM_DISPLAY_CAP_CMD_MODE        = BIT(1),
-};
-
-/**
  * enum msm_event_wait - type of HW events to wait for
  * @MSM_ENC_COMMIT_DONE - wait for the driver to flush the registers to HW
  * @MSM_ENC_TX_COMPLETE - wait for the HW to transfer the frame to panel
index 38e3323..a47e583 100644 (file)
@@ -28,6 +28,14 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr,
        fctx->fenceptr = fenceptr;
        spin_lock_init(&fctx->spinlock);
 
+       /*
+        * Start out close to the 32b fence rollover point, so we can
+        * catch bugs with fence comparisons.
+        */
+       fctx->last_fence = 0xffffff00;
+       fctx->completed_fence = fctx->last_fence;
+       *fctx->fenceptr = fctx->last_fence;
+
        return fctx;
 }
 
@@ -52,7 +60,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
        unsigned long flags;
 
        spin_lock_irqsave(&fctx->spinlock, flags);
-       fctx->completed_fence = max(fence, fctx->completed_fence);
+       if (fence_after(fence, fctx->completed_fence))
+               fctx->completed_fence = fence;
        spin_unlock_irqrestore(&fctx->spinlock, flags);
 }
 
index 7f92231..5514aca 100644 (file)
@@ -1004,7 +1004,7 @@ void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
 #endif
 
 /* don't call directly!  Use drm_gem_object_put() */
-void msm_gem_free_object(struct drm_gem_object *obj)
+static void msm_gem_free_object(struct drm_gem_object *obj)
 {
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        struct drm_device *dev = obj->dev;
index 6b7d5bb..d608339 100644 (file)
@@ -175,7 +175,6 @@ void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu);
 void msm_gem_active_put(struct drm_gem_object *obj);
 int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
 int msm_gem_cpu_fini(struct drm_gem_object *obj);
-void msm_gem_free_object(struct drm_gem_object *obj);
 int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
                uint32_t size, uint32_t flags, uint32_t *handle, char *name);
 struct drm_gem_object *msm_gem_new(struct drm_device *dev,
index c8cd9bf..484346d 100644 (file)
@@ -4,6 +4,8 @@
  * Author: Rob Clark <robdclark@gmail.com>
  */
 
+#include "drm/drm_drv.h"
+
 #include "msm_gpu.h"
 #include "msm_gem.h"
 #include "msm_mmu.h"
@@ -146,6 +148,16 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
        return 0;
 }
 
+void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_file_private *ctx,
+                        struct drm_printer *p)
+{
+       drm_printf(p, "drm-driver:\t%s\n", gpu->dev->driver->name);
+       drm_printf(p, "drm-client-id:\t%u\n", ctx->seqno);
+       drm_printf(p, "drm-engine-gpu:\t%llu ns\n", ctx->elapsed_ns);
+       drm_printf(p, "drm-cycles-gpu:\t%llu\n", ctx->cycles);
+       drm_printf(p, "drm-maxfreq-gpu:\t%u Hz\n", gpu->fast_rate);
+}
+
 int msm_gpu_hw_init(struct msm_gpu *gpu)
 {
        int ret;
@@ -634,7 +646,7 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
 {
        int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT;
        volatile struct msm_gpu_submit_stats *stats;
-       u64 elapsed, clock = 0;
+       u64 elapsed, clock = 0, cycles;
        unsigned long flags;
 
        stats = &ring->memptrs->stats[index];
@@ -642,12 +654,17 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
        elapsed = (stats->alwayson_end - stats->alwayson_start) * 10000;
        do_div(elapsed, 192);
 
+       cycles = stats->cpcycles_end - stats->cpcycles_start;
+
        /* Calculate the clock frequency from the number of CP cycles */
        if (elapsed) {
-               clock = (stats->cpcycles_end - stats->cpcycles_start) * 1000;
+               clock = cycles * 1000;
                do_div(clock, elapsed);
        }
 
+       submit->queue->ctx->elapsed_ns += elapsed;
+       submit->queue->ctx->cycles     += cycles;
+
        trace_msm_gpu_submit_retired(submit, elapsed, clock,
                stats->alwayson_start, stats->alwayson_end);
 
index 6def008..4911943 100644 (file)
@@ -362,6 +362,22 @@ struct msm_file_private {
        char *cmdline;
 
        /**
+        * elapsed:
+        *
+        * The total (cumulative) elapsed time GPU was busy with rendering
+        * from this context in ns.
+        */
+       uint64_t elapsed_ns;
+
+       /**
+        * cycles:
+        *
+        * The total (cumulative) GPU cycles elapsed attributed to this
+        * context.
+        */
+       uint64_t cycles;
+
+       /**
         * entities:
         *
         * Table of per-priority-level sched entities used by submitqueues
@@ -544,6 +560,9 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
 int msm_gpu_pm_suspend(struct msm_gpu *gpu);
 int msm_gpu_pm_resume(struct msm_gpu *gpu);
 
+void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_file_private *ctx,
+                        struct drm_printer *p);
+
 int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx);
 struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
                u32 id);
index d2539ca..c2ea978 100644 (file)
@@ -69,7 +69,7 @@ static void get_raw_dev_status(struct msm_gpu *gpu,
        df->time = time;
 
        busy_time *= USEC_PER_SEC;
-       do_div(busy_time, sample_rate);
+       busy_time = div64_ul(busy_time, sample_rate);
        if (WARN_ON(busy_time > ~0LU))
                busy_time = ~0LU;
 
index 9d7c61a..87cffc9 100644 (file)
@@ -315,6 +315,23 @@ struct drm_gem_object {
 };
 
 /**
+ * DRM_GEM_FOPS - Default drm GEM file operations
+ *
+ * This macro provides a shorthand for setting the GEM file ops in the
+ * &file_operations structure.  If all you need are the default ops, use
+ * DEFINE_DRM_GEM_FOPS instead.
+ */
+#define DRM_GEM_FOPS \
+       .open           = drm_open,\
+       .release        = drm_release,\
+       .unlocked_ioctl = drm_ioctl,\
+       .compat_ioctl   = drm_compat_ioctl,\
+       .poll           = drm_poll,\
+       .read           = drm_read,\
+       .llseek         = noop_llseek,\
+       .mmap           = drm_gem_mmap
+
+/**
  * DEFINE_DRM_GEM_FOPS() - macro to generate file operations for GEM drivers
  * @name: name for the generated structure
  *
@@ -330,14 +347,7 @@ struct drm_gem_object {
 #define DEFINE_DRM_GEM_FOPS(name) \
        static const struct file_operations name = {\
                .owner          = THIS_MODULE,\
-               .open           = drm_open,\
-               .release        = drm_release,\
-               .unlocked_ioctl = drm_ioctl,\
-               .compat_ioctl   = drm_compat_ioctl,\
-               .poll           = drm_poll,\
-               .read           = drm_read,\
-               .llseek         = noop_llseek,\
-               .mmap           = drm_gem_mmap,\
+               DRM_GEM_FOPS,\
        }
 
 void drm_gem_object_release(struct drm_gem_object *obj);