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>
34 files changed:
Documentation/devicetree/bindings/display/msm/dp-controller.yaml
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/Makefile
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/dp/dp_clk_util.c [deleted file]
drivers/gpu/drm/msm/dp/dp_clk_util.h [deleted file]
drivers/gpu/drm/msm/dp/dp_ctrl.c
drivers/gpu/drm/msm/dp/dp_display.c
drivers/gpu/drm/msm/dp/dp_display.h
drivers/gpu/drm/msm/dp/dp_drm.c
drivers/gpu/drm/msm/dp/dp_drm.h
drivers/gpu/drm/msm/dp/dp_parser.c
drivers/gpu/drm/msm/dp/dp_parser.h
drivers/gpu/drm/msm/dp/dp_power.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_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

index cd05cfd..94bc6e1 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: MSM Display Port Controller
 
 maintainers:
-  - Kuogee Hsieh <khsieh@codeaurora.org>
+  - Kuogee Hsieh <quic_khsieh@quicinc.com>
 
 description: |
   Device tree bindings for DisplayPort host controller for MSM targets
@@ -76,6 +76,9 @@ properties:
   "#sound-dai-cells":
     const: 0
 
+  vdda-0p9-supply: true
+  vdda-1p2-supply: true
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
     properties:
@@ -137,6 +140,9 @@ examples:
 
         power-domains = <&rpmhpd SC7180_CX>;
 
+        vdda-0p9-supply = <&vdda_usb_ss_dp_core>;
+        vdda-1p2-supply = <&vdda_usb_ss_dp_1p2>;
+
         ports {
             #address-cells = <1>;
             #size-cells = <0>;
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 66395ee..7274c41 100644 (file)
@@ -119,7 +119,6 @@ msm-$(CONFIG_DRM_MSM_GPU_STATE)     += adreno/a6xx_gpu_state.o
 
 msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
        dp/dp_catalog.o \
-       dp/dp_clk_util.o \
        dp/dp_ctrl.o \
        dp/dp_display.o \
        dp/dp_drm.o \
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,
 };
 
diff --git a/drivers/gpu/drm/msm/dp/dp_clk_util.c b/drivers/gpu/drm/msm/dp/dp_clk_util.c
deleted file mode 100644 (file)
index 44a4fc5..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation.
- * All rights reserved.
- */
-
-#include <linux/clk.h>
-#include <linux/clk/clk-conf.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-
-#include <drm/drm_print.h>
-
-#include "dp_clk_util.h"
-
-void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
-{
-       int i;
-
-       for (i = num_clk - 1; i >= 0; i--) {
-               if (clk_arry[i].clk)
-                       clk_put(clk_arry[i].clk);
-               clk_arry[i].clk = NULL;
-       }
-}
-
-int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk)
-{
-       int i, rc = 0;
-
-       for (i = 0; i < num_clk; i++) {
-               clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name);
-               rc = PTR_ERR_OR_ZERO(clk_arry[i].clk);
-               if (rc) {
-                       DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n",
-                               __builtin_return_address(0), __func__,
-                               clk_arry[i].clk_name, rc);
-                       goto error;
-               }
-       }
-
-       return rc;
-
-error:
-       for (i--; i >= 0; i--) {
-               if (clk_arry[i].clk)
-                       clk_put(clk_arry[i].clk);
-               clk_arry[i].clk = NULL;
-       }
-
-       return rc;
-}
-
-int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk)
-{
-       int i, rc = 0;
-
-       for (i = 0; i < num_clk; i++) {
-               if (clk_arry[i].clk) {
-                       if (clk_arry[i].type != DSS_CLK_AHB) {
-                               DEV_DBG("%pS->%s: '%s' rate %ld\n",
-                                       __builtin_return_address(0), __func__,
-                                       clk_arry[i].clk_name,
-                                       clk_arry[i].rate);
-                               rc = clk_set_rate(clk_arry[i].clk,
-                                       clk_arry[i].rate);
-                               if (rc) {
-                                       DEV_ERR("%pS->%s: %s failed. rc=%d\n",
-                                               __builtin_return_address(0),
-                                               __func__,
-                                               clk_arry[i].clk_name, rc);
-                                       break;
-                               }
-                       }
-               } else {
-                       DEV_ERR("%pS->%s: '%s' is not available\n",
-                               __builtin_return_address(0), __func__,
-                               clk_arry[i].clk_name);
-                       rc = -EPERM;
-                       break;
-               }
-       }
-
-       return rc;
-}
-
-int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
-{
-       int i, rc = 0;
-
-       if (enable) {
-               for (i = 0; i < num_clk; i++) {
-                       DEV_DBG("%pS->%s: enable '%s'\n",
-                               __builtin_return_address(0), __func__,
-                               clk_arry[i].clk_name);
-                       rc = clk_prepare_enable(clk_arry[i].clk);
-                       if (rc)
-                               DEV_ERR("%pS->%s: %s en fail. rc=%d\n",
-                                       __builtin_return_address(0),
-                                       __func__,
-                                       clk_arry[i].clk_name, rc);
-
-                       if (rc && i) {
-                               msm_dss_enable_clk(&clk_arry[i - 1],
-                                       i - 1, false);
-                               break;
-                       }
-               }
-       } else {
-               for (i = num_clk - 1; i >= 0; i--) {
-                       DEV_DBG("%pS->%s: disable '%s'\n",
-                               __builtin_return_address(0), __func__,
-                               clk_arry[i].clk_name);
-
-                       clk_disable_unprepare(clk_arry[i].clk);
-               }
-       }
-
-       return rc;
-}
diff --git a/drivers/gpu/drm/msm/dp/dp_clk_util.h b/drivers/gpu/drm/msm/dp/dp_clk_util.h
deleted file mode 100644 (file)
index 067bf87..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved.
- */
-
-#ifndef __DP_CLK_UTIL_H__
-#define __DP_CLK_UTIL_H__
-
-#include <linux/platform_device.h>
-#include <linux/types.h>
-
-#define DEV_DBG(fmt, args...)   pr_debug(fmt, ##args)
-#define DEV_INFO(fmt, args...)  pr_info(fmt, ##args)
-#define DEV_WARN(fmt, args...)  pr_warn(fmt, ##args)
-#define DEV_ERR(fmt, args...)   pr_err(fmt, ##args)
-
-enum dss_clk_type {
-       DSS_CLK_AHB, /* no set rate. rate controlled through rpm */
-       DSS_CLK_PCLK,
-};
-
-struct dss_clk {
-       struct clk *clk; /* clk handle */
-       char clk_name[32];
-       enum dss_clk_type type;
-       unsigned long rate;
-       unsigned long max_rate;
-};
-
-struct dss_module_power {
-       unsigned int num_clk;
-       struct dss_clk *clk_config;
-};
-
-int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk);
-void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk);
-int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk);
-int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable);
-#endif /* __DP_CLK_UTIL_H__ */
index 7032493..ab6aa13 100644 (file)
@@ -1321,9 +1321,9 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl,
                        enum dp_pm_type module, char *name, unsigned long rate)
 {
        u32 num = ctrl->parser->mp[module].num_clk;
-       struct dss_clk *cfg = ctrl->parser->mp[module].clk_config;
+       struct clk_bulk_data *cfg = ctrl->parser->mp[module].clocks;
 
-       while (num && strcmp(cfg->clk_name, name)) {
+       while (num && strcmp(cfg->id, name)) {
                num--;
                cfg++;
        }
@@ -1332,7 +1332,7 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl,
                                                rate, name);
 
        if (num)
-               cfg->rate = rate;
+               clk_set_rate(cfg->clk, rate);
        else
                DRM_ERROR("%s clock doesn't exit to set rate %lu\n",
                                name, rate);
@@ -1349,12 +1349,11 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
        opts_dp->lanes = ctrl->link->link_params.num_lanes;
        opts_dp->link_rate = ctrl->link->link_params.rate / 100;
        opts_dp->ssc = drm_dp_max_downspread(dpcd);
-       dp_ctrl_set_clock_rate(ctrl, DP_CTRL_PM, "ctrl_link",
-                                       ctrl->link->link_params.rate * 1000);
 
        phy_configure(phy, &dp_io->phy_opts);
        phy_power_on(phy);
 
+       dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000);
        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, true);
        if (ret)
                DRM_ERROR("Unable to start link clocks. ret=%d\n", ret);
@@ -1462,6 +1461,7 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl)
         * link clock might have been adjusted as part of the
         * link maintenance.
         */
+       dev_pm_opp_set_rate(ctrl->dev, 0);
        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
        if (ret) {
                DRM_ERROR("Failed to disable clocks. ret=%d\n", ret);
@@ -1493,6 +1493,7 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl)
 
        dp_catalog_ctrl_reset(ctrl->catalog);
 
+       dev_pm_opp_set_rate(ctrl->dev, 0);
        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
        if (ret) {
                DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret);
@@ -1929,6 +1930,7 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
                }
        }
 
+       dev_pm_opp_set_rate(ctrl->dev, 0);
        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
        if (ret) {
                DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret);
@@ -1997,6 +1999,7 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
        if (ret)
                DRM_ERROR("Failed to disable pixel clocks. ret=%d\n", ret);
 
+       dev_pm_opp_set_rate(ctrl->dev, 0);
        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
        if (ret) {
                DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret);
index 239c8e3..b36f8b6 100644 (file)
@@ -131,35 +131,43 @@ struct msm_dp_config {
        size_t num_descs;
 };
 
+static const struct msm_dp_desc sc7180_dp_descs[] = {
+       [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+};
+
 static const struct msm_dp_config sc7180_dp_cfg = {
-       .descs = (const struct msm_dp_desc[]) {
-               [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
-       },
-       .num_descs = 1,
+       .descs = sc7180_dp_descs,
+       .num_descs = ARRAY_SIZE(sc7180_dp_descs),
+};
+
+static const struct msm_dp_desc sc7280_dp_descs[] = {
+       [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
+       [MSM_DP_CONTROLLER_1] = { .io_start = 0x0aea0000, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
 };
 
 static const struct msm_dp_config sc7280_dp_cfg = {
-       .descs = (const struct msm_dp_desc[]) {
-               [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-               [MSM_DP_CONTROLLER_1] = { .io_start = 0x0aea0000, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-       },
-       .num_descs = 2,
+       .descs = sc7280_dp_descs,
+       .num_descs = ARRAY_SIZE(sc7280_dp_descs),
+};
+
+static const struct msm_dp_desc sc8180x_dp_descs[] = {
+       [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+       [MSM_DP_CONTROLLER_1] = { .io_start = 0x0ae98000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+       [MSM_DP_CONTROLLER_2] = { .io_start = 0x0ae9a000, .connector_type = DRM_MODE_CONNECTOR_eDP },
 };
 
 static const struct msm_dp_config sc8180x_dp_cfg = {
-       .descs = (const struct msm_dp_desc[]) {
-               [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
-               [MSM_DP_CONTROLLER_1] = { .io_start = 0x0ae98000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
-               [MSM_DP_CONTROLLER_2] = { .io_start = 0x0ae9a000, .connector_type = DRM_MODE_CONNECTOR_eDP },
-       },
-       .num_descs = 3,
+       .descs = sc8180x_dp_descs,
+       .num_descs = ARRAY_SIZE(sc8180x_dp_descs),
+};
+
+static const struct msm_dp_desc sm8350_dp_descs[] = {
+       [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
 };
 
 static const struct msm_dp_config sm8350_dp_cfg = {
-       .descs = (const struct msm_dp_desc[]) {
-               [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
-       },
-       .num_descs = 1,
+       .descs = sm8350_dp_descs,
+       .num_descs = ARRAY_SIZE(sm8350_dp_descs),
 };
 
 static const struct of_device_id dp_dt_match[] = {
@@ -992,7 +1000,7 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
                return MODE_OK;
 
        if (mode->clock > DP_MAX_PIXEL_CLK_KHZ)
-               return MODE_BAD;
+               return MODE_CLOCK_HIGH;
 
        dp_display = container_of(dp, struct dp_display_private, dp_display);
        link_info = &dp_display->panel->link_info;
@@ -1624,8 +1632,6 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
                return ret;
        }
 
-       dp_display->encoder = encoder;
-
        ret = dp_display_get_next_bridge(dp_display);
        if (ret)
                return ret;
@@ -1641,7 +1647,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
 
        priv->bridges[priv->num_bridges++] = dp_display->bridge;
 
-       dp_display->connector = dp_drm_connector_init(dp_display);
+       dp_display->connector = dp_drm_connector_init(dp_display, encoder);
        if (IS_ERR(dp_display->connector)) {
                ret = PTR_ERR(dp_display->connector);
                DRM_DEV_ERROR(dev->dev,
index 4f9fe4d..dcedf02 100644 (file)
@@ -15,7 +15,6 @@ struct msm_dp {
        struct device *codec_dev;
        struct drm_bridge *bridge;
        struct drm_connector *connector;
-       struct drm_encoder *encoder;
        struct drm_bridge *next_bridge;
        bool is_connected;
        bool audio_enabled;
index 62d58b9..6df25f7 100644 (file)
@@ -116,7 +116,7 @@ struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *
        }
 
        if (dp_display->next_bridge) {
-               rc = drm_bridge_attach(dp_display->encoder,
+               rc = drm_bridge_attach(encoder,
                                        dp_display->next_bridge, bridge,
                                        DRM_BRIDGE_ATTACH_NO_CONNECTOR);
                if (rc < 0) {
@@ -130,15 +130,15 @@ struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *
 }
 
 /* connector initialization */
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display)
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct drm_encoder *encoder)
 {
        struct drm_connector *connector = NULL;
 
-       connector = drm_bridge_connector_init(dp_display->drm_dev, dp_display->encoder);
+       connector = drm_bridge_connector_init(dp_display->drm_dev, encoder);
        if (IS_ERR(connector))
                return connector;
 
-       drm_connector_attach_encoder(connector, dp_display->encoder);
+       drm_connector_attach_encoder(connector, encoder);
 
        return connector;
 }
index f4b1ed1..82035db 100644 (file)
@@ -19,7 +19,7 @@ struct msm_dp_bridge {
 
 #define to_dp_bridge(x)     container_of((x), struct msm_dp_bridge, bridge)
 
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display);
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct drm_encoder *encoder);
 struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
                        struct drm_encoder *encoder);
 
index 8f9fed9..29107f1 100644 (file)
@@ -162,11 +162,11 @@ static int dp_parser_init_clk_data(struct dp_parser *parser)
        }
 
        core_power->num_clk = core_clk_count;
-       core_power->clk_config = devm_kzalloc(dev,
-                       sizeof(struct dss_clk) * core_power->num_clk,
+       core_power->clocks = devm_kcalloc(dev,
+                       core_power->num_clk, sizeof(struct clk_bulk_data),
                        GFP_KERNEL);
-       if (!core_power->clk_config)
-               return -EINVAL;
+       if (!core_power->clocks)
+               return -ENOMEM;
 
        /* Initialize the CTRL power module */
        if (ctrl_clk_count == 0) {
@@ -175,12 +175,12 @@ static int dp_parser_init_clk_data(struct dp_parser *parser)
        }
 
        ctrl_power->num_clk = ctrl_clk_count;
-       ctrl_power->clk_config = devm_kzalloc(dev,
-                       sizeof(struct dss_clk) * ctrl_power->num_clk,
+       ctrl_power->clocks = devm_kcalloc(dev,
+                       ctrl_power->num_clk, sizeof(struct clk_bulk_data),
                        GFP_KERNEL);
-       if (!ctrl_power->clk_config) {
+       if (!ctrl_power->clocks) {
                ctrl_power->num_clk = 0;
-               return -EINVAL;
+               return -ENOMEM;
        }
 
        /* Initialize the STREAM power module */
@@ -190,12 +190,12 @@ static int dp_parser_init_clk_data(struct dp_parser *parser)
        }
 
        stream_power->num_clk = stream_clk_count;
-       stream_power->clk_config = devm_kzalloc(dev,
-                       sizeof(struct dss_clk) * stream_power->num_clk,
+       stream_power->clocks = devm_kcalloc(dev,
+                       stream_power->num_clk, sizeof(struct clk_bulk_data),
                        GFP_KERNEL);
-       if (!stream_power->clk_config) {
+       if (!stream_power->clocks) {
                stream_power->num_clk = 0;
-               return -EINVAL;
+               return -ENOMEM;
        }
 
        return 0;
@@ -234,29 +234,16 @@ static int dp_parser_clock(struct dp_parser *parser)
                }
                if (dp_parser_check_prefix("core", clk_name) &&
                                core_clk_index < core_clk_count) {
-                       struct dss_clk *clk =
-                               &core_power->clk_config[core_clk_index];
-                       strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
-                       clk->type = DSS_CLK_AHB;
+                       core_power->clocks[core_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
                        core_clk_index++;
                } else if (dp_parser_check_prefix("stream", clk_name) &&
                                stream_clk_index < stream_clk_count) {
-                       struct dss_clk *clk =
-                               &stream_power->clk_config[stream_clk_index];
-                       strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
-                       clk->type = DSS_CLK_PCLK;
+                       stream_power->clocks[stream_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
                        stream_clk_index++;
                } else if (dp_parser_check_prefix("ctrl", clk_name) &&
                           ctrl_clk_index < ctrl_clk_count) {
-                       struct dss_clk *clk =
-                               &ctrl_power->clk_config[ctrl_clk_index];
-                       strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
+                       ctrl_power->clocks[ctrl_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
                        ctrl_clk_index++;
-                       if (dp_parser_check_prefix("ctrl_link", clk_name) ||
-                           dp_parser_check_prefix("stream_pixel", clk_name))
-                               clk->type = DSS_CLK_PCLK;
-                       else
-                               clk->type = DSS_CLK_AHB;
                }
        }
 
index 3a4d797..9abddc6 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/phy/phy.h>
 #include <linux/phy/phy-dp.h>
 
-#include "dp_clk_util.h"
 #include "msm_drv.h"
 
 #define DP_LABEL "MDSS DP DISPLAY"
@@ -106,6 +105,11 @@ struct dp_regulator_cfg {
        struct dp_reg_entry regs[DP_DEV_REGULATOR_MAX];
 };
 
+struct dss_module_power {
+       unsigned int num_clk;
+       struct clk_bulk_data *clocks;
+};
+
 /**
  * struct dp_parser - DP parser's data exposed to clients
  *
index d9e0117..b415b35 100644 (file)
@@ -106,107 +106,30 @@ static int dp_power_clk_init(struct dp_power_private *power)
        ctrl = &power->parser->mp[DP_CTRL_PM];
        stream = &power->parser->mp[DP_STREAM_PM];
 
-       rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk);
+       rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks);
        if (rc) {
                DRM_ERROR("failed to get %s clk. err=%d\n",
                        dp_parser_pm_name(DP_CORE_PM), rc);
                return rc;
        }
 
-       rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk);
+       rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks);
        if (rc) {
                DRM_ERROR("failed to get %s clk. err=%d\n",
                        dp_parser_pm_name(DP_CTRL_PM), rc);
-               msm_dss_put_clk(core->clk_config, core->num_clk);
                return -ENODEV;
        }
 
-       rc = msm_dss_get_clk(dev, stream->clk_config, stream->num_clk);
+       rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks);
        if (rc) {
                DRM_ERROR("failed to get %s clk. err=%d\n",
                        dp_parser_pm_name(DP_CTRL_PM), rc);
-               msm_dss_put_clk(core->clk_config, core->num_clk);
                return -ENODEV;
        }
 
        return 0;
 }
 
-static int dp_power_clk_deinit(struct dp_power_private *power)
-{
-       struct dss_module_power *core, *ctrl, *stream;
-
-       core = &power->parser->mp[DP_CORE_PM];
-       ctrl = &power->parser->mp[DP_CTRL_PM];
-       stream = &power->parser->mp[DP_STREAM_PM];
-
-       if (!core || !ctrl || !stream) {
-               DRM_ERROR("invalid power_data\n");
-               return -EINVAL;
-       }
-
-       msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk);
-       msm_dss_put_clk(core->clk_config, core->num_clk);
-       msm_dss_put_clk(stream->clk_config, stream->num_clk);
-       return 0;
-}
-
-static int dp_power_clk_set_link_rate(struct dp_power_private *power,
-                       struct dss_clk *clk_arry, int num_clk, int enable)
-{
-       u32 rate;
-       int i, rc = 0;
-
-       for (i = 0; i < num_clk; i++) {
-               if (clk_arry[i].clk) {
-                       if (clk_arry[i].type == DSS_CLK_PCLK) {
-                               if (enable)
-                                       rate = clk_arry[i].rate;
-                               else
-                                       rate = 0;
-
-                               rc = dev_pm_opp_set_rate(power->dev, rate);
-                               if (rc)
-                                       break;
-                       }
-
-               }
-       }
-       return rc;
-}
-
-static int dp_power_clk_set_rate(struct dp_power_private *power,
-               enum dp_pm_type module, bool enable)
-{
-       int rc = 0;
-       struct dss_module_power *mp = &power->parser->mp[module];
-
-       if (module == DP_CTRL_PM) {
-               rc = dp_power_clk_set_link_rate(power, mp->clk_config, mp->num_clk, enable);
-               if (rc) {
-                       DRM_ERROR("failed to set link clks rate\n");
-                       return rc;
-               }
-       } else {
-
-               if (enable) {
-                       rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
-                       if (rc) {
-                               DRM_ERROR("failed to set clks rate\n");
-                               return rc;
-                       }
-               }
-       }
-
-       rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
-       if (rc) {
-               DRM_ERROR("failed to %d clks, err: %d\n", enable, rc);
-               return rc;
-       }
-
-       return 0;
-}
-
 int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type)
 {
        struct dp_power_private *power;
@@ -234,6 +157,7 @@ int dp_power_clk_enable(struct dp_power *dp_power,
 {
        int rc = 0;
        struct dp_power_private *power;
+       struct dss_module_power *mp;
 
        power = container_of(dp_power, struct dp_power_private, dp_power);
 
@@ -266,8 +190,9 @@ int dp_power_clk_enable(struct dp_power *dp_power,
                if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) {
                        drm_dbg_dp(power->drm_dev,
                                        "Enable core clks before link clks\n");
+                       mp = &power->parser->mp[DP_CORE_PM];
 
-                       rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable);
+                       rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
                        if (rc) {
                                DRM_ERROR("fail to enable clks: %s. err=%d\n",
                                        dp_parser_pm_name(DP_CORE_PM), rc);
@@ -277,12 +202,15 @@ int dp_power_clk_enable(struct dp_power *dp_power,
                }
        }
 
-       rc = dp_power_clk_set_rate(power, pm_type, enable);
-       if (rc) {
-               DRM_ERROR("failed to '%s' clks for: %s. err=%d\n",
-                       enable ? "enable" : "disable",
-                       dp_parser_pm_name(pm_type), rc);
-               return rc;
+       mp = &power->parser->mp[pm_type];
+       if (enable) {
+               rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
+               if (rc) {
+                       DRM_ERROR("failed to enable clks, err: %d\n", rc);
+                       return rc;
+               }
+       } else {
+               clk_bulk_disable_unprepare(mp->num_clk, mp->clocks);
        }
 
        if (pm_type == DP_CORE_PM)
@@ -347,9 +275,7 @@ void dp_power_client_deinit(struct dp_power *dp_power)
 
        power = container_of(dp_power, struct dp_power_private, dp_power);
 
-       dp_power_clk_deinit(power);
        pm_runtime_disable(&power->pdev->dev);
-
 }
 
 int dp_power_init(struct dp_power *dp_power, bool flip)
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 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);