mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-03 19:55:31 +00:00
Merge tag 'drm-msm-next-2024-10-28' of https://gitlab.freedesktop.org/drm/msm into drm-next
Updates for v6.13 Core: - Switch to aperture_remove_all_conflicting_devices() - Simplify msm_disp_state_dump_regs() DPU: - Add SA8775P support - Add (disabled by default) MSM8917, MSM8937, MSM8953 and MSM8996 support - Enable support for larger framebuffers (required for X.Org working with several outputs) - Dropped LM_3, LM_4 (MSM8998, SDM845) - Fixed DSPP_3 routing on SDM845 DP: - Add SA8775P support HDMI: - Mark two arrays as const in MSM8998 HDMI PHY driver GPU: - a7xx preemption support - Adreno A663 support - Typos fixes, etc - Fix excessive stack usage in a6xx GMU Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rob Clark <robdclark@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGt7k8zDHsg2Uzx9apzyQMut8XdLXMQSRNn7WArdPUV5Qw@mail.gmail.com
This commit is contained in:
commit
ffd99396c6
@ -17,6 +17,7 @@ properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- qcom,sa8775p-dp
|
||||
- qcom,sc7180-dp
|
||||
- qcom,sc7280-dp
|
||||
- qcom,sc7280-edp
|
||||
|
@ -125,6 +125,7 @@ allOf:
|
||||
enum:
|
||||
- qcom,adreno-gmu-635.0
|
||||
- qcom,adreno-gmu-660.1
|
||||
- qcom,adreno-gmu-663.0
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
|
@ -0,0 +1,241 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sa8775p-mdss.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. SA87755P Display MDSS
|
||||
|
||||
maintainers:
|
||||
- Mahadevan <quic_mahap@quicinc.com>
|
||||
|
||||
description:
|
||||
SA8775P MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like
|
||||
DPU display controller, DP interfaces and EDP etc.
|
||||
|
||||
$ref: /schemas/display/msm/mdss-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sa8775p-mdss
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display AHB
|
||||
- description: Display hf AXI
|
||||
- description: Display core
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
interconnects:
|
||||
maxItems: 3
|
||||
|
||||
interconnect-names:
|
||||
maxItems: 3
|
||||
|
||||
patternProperties:
|
||||
"^display-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sa8775p-dpu
|
||||
|
||||
"^displayport-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: qcom,sa8775p-dp
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/qcom,sa8775p-gcc.h>
|
||||
#include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
display-subsystem@ae00000 {
|
||||
compatible = "qcom,sa8775p-mdss";
|
||||
reg = <0x0ae00000 0x1000>;
|
||||
reg-names = "mdss";
|
||||
|
||||
interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>,
|
||||
<&mmss_noc MASTER_MDP1 &mc_virt SLAVE_EBI1>,
|
||||
<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_DISPLAY_CFG>;
|
||||
interconnect-names = "mdp0-mem",
|
||||
"mdp1-mem",
|
||||
"cpu-cfg";
|
||||
|
||||
|
||||
resets = <&dispcc_core_bcr>;
|
||||
power-domains = <&dispcc_gdsc>;
|
||||
|
||||
clocks = <&dispcc_ahb_clk>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&dispcc_mdp_clk>;
|
||||
|
||||
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
iommus = <&apps_smmu 0x1000 0x402>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sa8775p-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&dispcc_ahb_clk>,
|
||||
<&dispcc_mdp_lut_clk>,
|
||||
<&dispcc_mdp_clk>,
|
||||
<&dispcc_mdp_vsync_clk>;
|
||||
clock-names = "nrt_bus",
|
||||
"iface",
|
||||
"lut",
|
||||
"core",
|
||||
"vsync";
|
||||
|
||||
assigned-clocks = <&dispcc_mdp_vsync_clk>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdss0_mdp_opp_table>;
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss0>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dpu_intf0_out: endpoint {
|
||||
remote-endpoint = <&mdss0_dp0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdss0_mdp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-375000000 {
|
||||
opp-hz = /bits/ 64 <375000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-500000000 {
|
||||
opp-hz = /bits/ 64 <500000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
|
||||
opp-575000000 {
|
||||
opp-hz = /bits/ 64 <575000000>;
|
||||
required-opps = <&rpmhpd_opp_turbo>;
|
||||
};
|
||||
|
||||
opp-650000000 {
|
||||
opp-hz = /bits/ 64 <650000000>;
|
||||
required-opps = <&rpmhpd_opp_turbo_l1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
displayport-controller@af54000 {
|
||||
compatible = "qcom,sa8775p-dp";
|
||||
|
||||
pinctrl-0 = <&dp_hot_plug_det>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
reg = <0xaf54000 0x104>,
|
||||
<0xaf54200 0x0c0>,
|
||||
<0xaf55000 0x770>,
|
||||
<0xaf56000 0x09c>;
|
||||
|
||||
interrupt-parent = <&mdss0>;
|
||||
interrupts = <12>;
|
||||
|
||||
clocks = <&dispcc_mdss_ahb_clk>,
|
||||
<&dispcc_dptx0_aux_clk>,
|
||||
<&dispcc_dptx0_link_clk>,
|
||||
<&dispcc_dptx0_link_intf_clk>,
|
||||
<&dispcc_dptx0_pixel0_clk>;
|
||||
clock-names = "core_iface",
|
||||
"core_aux",
|
||||
"ctrl_link",
|
||||
"ctrl_link_iface",
|
||||
"stream_pixel";
|
||||
|
||||
assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
|
||||
<&dispcc_mdss_dptx0_pixel0_clk_src>;
|
||||
assigned-clock-parents = <&mdss0_edp_phy 0>, <&mdss0_edp_phy 1>;
|
||||
|
||||
phys = <&mdss0_edp_phy>;
|
||||
phy-names = "dp";
|
||||
|
||||
operating-points-v2 = <&dp_opp_table>;
|
||||
power-domains = <&rpmhpd SA8775P_MMCX>;
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
mdss0_dp0_in: endpoint {
|
||||
remote-endpoint = <&dpu_intf0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
mdss0_dp_out: endpoint { };
|
||||
};
|
||||
};
|
||||
|
||||
dp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-160000000 {
|
||||
opp-hz = /bits/ 64 <160000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-270000000 {
|
||||
opp-hz = /bits/ 64 <270000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-540000000 {
|
||||
opp-hz = /bits/ 64 <540000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-810000000 {
|
||||
opp-hz = /bits/ 64 <810000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -7,13 +7,21 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: Qualcomm Display DPU on SC7280
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <andersson@kernel.org>
|
||||
- Neil Armstrong <neil.armstrong@linaro.org>
|
||||
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
- Krishna Manikandan <quic_mkrishn@quicinc.com>
|
||||
|
||||
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sc7280-dpu
|
||||
enum:
|
||||
- qcom,sc7280-dpu
|
||||
- qcom,sc8280xp-dpu
|
||||
- qcom,sm8350-dpu
|
||||
- qcom,sm8450-dpu
|
||||
- qcom,sm8550-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
@ -1,122 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sc8280xp-dpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SC8280XP Display Processing Unit
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <andersson@kernel.org>
|
||||
|
||||
description:
|
||||
Device tree bindings for SC8280XP Display Processing Unit.
|
||||
|
||||
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sc8280xp-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Address offset and size for mdp register set
|
||||
- description: Address offset and size for vbif register set
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: mdp
|
||||
- const: vbif
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display hf axi clock
|
||||
- description: Display sf axi clock
|
||||
- description: Display ahb clock
|
||||
- description: Display lut clock
|
||||
- description: Display core clock
|
||||
- description: Display vsync clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: nrt_bus
|
||||
- const: iface
|
||||
- const: lut
|
||||
- const: core
|
||||
- const: vsync
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,dispcc-sc8280xp.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interconnect/qcom,sc8280xp.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sc8280xp-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&gcc GCC_DISP_SF_AXI_CLK>,
|
||||
<&dispcc0 DISP_CC_MDSS_AHB_CLK>,
|
||||
<&dispcc0 DISP_CC_MDSS_MDP_LUT_CLK>,
|
||||
<&dispcc0 DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc0 DISP_CC_MDSS_VSYNC_CLK>;
|
||||
clock-names = "bus",
|
||||
"nrt_bus",
|
||||
"iface",
|
||||
"lut",
|
||||
"core",
|
||||
"vsync";
|
||||
|
||||
assigned-clocks = <&dispcc0 DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc0 DISP_CC_MDSS_VSYNC_CLK>;
|
||||
assigned-clock-rates = <460000000>,
|
||||
<19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
power-domains = <&rpmhpd SC8280XP_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss0>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
endpoint {
|
||||
remote-endpoint = <&mdss0_dp0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
endpoint {
|
||||
remote-endpoint = <&mdss0_dp1_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
endpoint {
|
||||
remote-endpoint = <&mdss0_dp3_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
endpoint {
|
||||
remote-endpoint = <&mdss0_dp2_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -13,7 +13,9 @@ $ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8150-dpu
|
||||
enum:
|
||||
- qcom,sm8150-dpu
|
||||
- qcom,sm8250-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
@ -1,99 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sm8250-dpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SM8250 Display DPU
|
||||
|
||||
maintainers:
|
||||
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
|
||||
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8250-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Address offset and size for mdp register set
|
||||
- description: Address offset and size for vbif register set
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: mdp
|
||||
- const: vbif
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display ahb clock
|
||||
- description: Display hf axi clock
|
||||
- description: Display core clock
|
||||
- description: Display vsync clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: iface
|
||||
- const: bus
|
||||
- const: core
|
||||
- const: vsync
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,dispcc-sm8250.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sm8250.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interconnect/qcom,sm8250.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sm8250-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
clock-names = "iface", "bus", "core", "vsync";
|
||||
|
||||
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dsi1_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -1,120 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sm8350-dpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SM8350 Display DPU
|
||||
|
||||
maintainers:
|
||||
- Robert Foss <robert.foss@linaro.org>
|
||||
|
||||
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8350-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Address offset and size for mdp register set
|
||||
- description: Address offset and size for vbif register set
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: mdp
|
||||
- const: vbif
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display hf axi clock
|
||||
- description: Display sf axi clock
|
||||
- description: Display ahb clock
|
||||
- description: Display lut clock
|
||||
- description: Display core clock
|
||||
- description: Display vsync clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: nrt_bus
|
||||
- const: iface
|
||||
- const: lut
|
||||
- const: core
|
||||
- const: vsync
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,dispcc-sm8350.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sm8350.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interconnect/qcom,sm8350.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sm8350-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&gcc GCC_DISP_SF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
clock-names = "bus",
|
||||
"nrt_bus",
|
||||
"iface",
|
||||
"lut",
|
||||
"core",
|
||||
"vsync";
|
||||
|
||||
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dpu_intf1_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-200000000 {
|
||||
opp-hz = /bits/ 64 <200000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-345000000 {
|
||||
opp-hz = /bits/ 64 <345000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-460000000 {
|
||||
opp-hz = /bits/ 64 <460000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -1,139 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sm8450-dpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SM8450 Display DPU
|
||||
|
||||
maintainers:
|
||||
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
|
||||
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8450-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Address offset and size for mdp register set
|
||||
- description: Address offset and size for vbif register set
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: mdp
|
||||
- const: vbif
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display hf axi
|
||||
- description: Display sf axi
|
||||
- description: Display ahb
|
||||
- description: Display lut
|
||||
- description: Display core
|
||||
- description: Display vsync
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: nrt_bus
|
||||
- const: iface
|
||||
- const: lut
|
||||
- const: core
|
||||
- const: vsync
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,sm8450-dispcc.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sm8450.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interconnect/qcom,sm8450.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sm8450-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&gcc GCC_DISP_SF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
clock-names = "bus",
|
||||
"nrt_bus",
|
||||
"iface",
|
||||
"lut",
|
||||
"core",
|
||||
"vsync";
|
||||
|
||||
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dpu_intf1_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dpu_intf2_out: endpoint {
|
||||
remote-endpoint = <&dsi1_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-172000000{
|
||||
opp-hz = /bits/ 64 <172000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs_d1>;
|
||||
};
|
||||
|
||||
opp-200000000 {
|
||||
opp-hz = /bits/ 64 <200000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-325000000 {
|
||||
opp-hz = /bits/ 64 <325000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-375000000 {
|
||||
opp-hz = /bits/ 64 <375000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-500000000 {
|
||||
opp-hz = /bits/ 64 <500000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -1,133 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sm8550-dpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SM8550 Display DPU
|
||||
|
||||
maintainers:
|
||||
- Neil Armstrong <neil.armstrong@linaro.org>
|
||||
|
||||
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8550-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Address offset and size for mdp register set
|
||||
- description: Address offset and size for vbif register set
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: mdp
|
||||
- const: vbif
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display AHB
|
||||
- description: Display hf axi
|
||||
- description: Display MDSS ahb
|
||||
- description: Display lut
|
||||
- description: Display core
|
||||
- description: Display vsync
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: nrt_bus
|
||||
- const: iface
|
||||
- const: lut
|
||||
- const: core
|
||||
- const: vsync
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,sm8550-dispcc.h>
|
||||
#include <dt-bindings/clock/qcom,sm8550-gcc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sm8550-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&gcc GCC_DISP_AHB_CLK>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
clock-names = "bus",
|
||||
"nrt_bus",
|
||||
"iface",
|
||||
"lut",
|
||||
"core",
|
||||
"vsync";
|
||||
|
||||
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dpu_intf1_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dpu_intf2_out: endpoint {
|
||||
remote-endpoint = <&dsi1_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-200000000 {
|
||||
opp-hz = /bits/ 64 <200000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-325000000 {
|
||||
opp-hz = /bits/ 64 <325000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-375000000 {
|
||||
opp-hz = /bits/ 64 <375000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-514000000 {
|
||||
opp-hz = /bits/ 64 <514000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -14,6 +14,7 @@ $ref: /schemas/display/msm/dpu-common.yaml#
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sa8775p-dpu
|
||||
- qcom,sm8650-dpu
|
||||
- qcom,x1e80100-dpu
|
||||
|
||||
|
99
Documentation/gpu/msm-preemption.rst
Normal file
99
Documentation/gpu/msm-preemption.rst
Normal file
@ -0,0 +1,99 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
:orphan:
|
||||
|
||||
==============
|
||||
MSM Preemption
|
||||
==============
|
||||
|
||||
Preemption allows Adreno GPUs to switch to a higher priority ring when work is
|
||||
pushed to it, reducing latency for high priority submissions.
|
||||
|
||||
When preemption is enabled 4 rings are initialized, corresponding to different
|
||||
priority levels. Having multiple rings is purely a software concept as the GPU
|
||||
only has registers to keep track of one graphics ring.
|
||||
The kernel is able to switch which ring is currently being processed by
|
||||
requesting preemption. When certain conditions are met, depending on the
|
||||
priority level, the GPU will save its current state in a series of buffers,
|
||||
then restores state from a similar set of buffers specified by the kernel. It
|
||||
then resumes execution and fires an IRQ to let the kernel know the context
|
||||
switch has completed.
|
||||
|
||||
This mechanism can be used by the kernel to switch between rings. Whenever a
|
||||
submission occurs the kernel finds the highest priority ring which isn't empty
|
||||
and preempts to it if said ring is not the one being currently executed. This is
|
||||
also done whenever a submission completes to make sure execution resumes on a
|
||||
lower priority ring when a higher priority ring is done.
|
||||
|
||||
Preemption levels
|
||||
-----------------
|
||||
|
||||
Preemption can only occur at certain boundaries. The exact conditions can be
|
||||
configured by changing the preemption level, this allows to compromise between
|
||||
latency (ie. the time that passes between when the kernel requests preemption
|
||||
and when the SQE begins saving state) and overhead (the amount of state that
|
||||
needs to be saved).
|
||||
|
||||
The GPU offers 3 levels:
|
||||
|
||||
Level 0
|
||||
Preemption only occurs at the submission level. This requires the least amount
|
||||
of state to be saved as the execution of userspace submitted IBs is never
|
||||
interrupted, however it offers very little benefit compared to not enabling
|
||||
preemption of any kind.
|
||||
|
||||
Level 1
|
||||
Preemption occurs at either bin level, if using GMEM rendering, or draw level
|
||||
in the sysmem rendering case.
|
||||
|
||||
Level 2
|
||||
Preemption occurs at draw level.
|
||||
|
||||
Level 1 is the mode that is used by the msm driver.
|
||||
|
||||
Additionally the GPU allows to specify a `skip_save_restore` option. This
|
||||
disables the saving and restoring of all registers except those relating to the
|
||||
operation of the SQE itself, reducing overhead. Saving and restoring is only
|
||||
skipped when using GMEM with Level 1 preemption. When enabling this userspace is
|
||||
expected to set the state that isn't preserved whenever preemption occurs which
|
||||
is done by specifying preamble and postambles. Those are IBs that are executed
|
||||
before and after preemption.
|
||||
|
||||
Preemption buffers
|
||||
------------------
|
||||
|
||||
A series of buffers are necessary to store the state of rings while they are not
|
||||
being executed. There are different kinds of preemption records and most of
|
||||
those require one buffer per ring. This is because preemption never occurs
|
||||
between submissions on the same ring, which always run in sequence when the ring
|
||||
is active. This means that only one context per ring is effectively active.
|
||||
|
||||
SMMU_INFO
|
||||
This buffer contains info about the current SMMU configuration such as the
|
||||
ttbr0 register. The SQE firmware isn't actually able to save this record.
|
||||
As a result SMMU info must be saved manually from the CP to a buffer and the
|
||||
SMMU record updated with info from said buffer before triggering
|
||||
preemption.
|
||||
|
||||
NON_SECURE
|
||||
This is the main preemption record where most state is saved. It is mostly
|
||||
opaque to the kernel except for the first few words that must be initialized
|
||||
by the kernel.
|
||||
|
||||
SECURE
|
||||
This saves state related to the GPU's secure mode.
|
||||
|
||||
NON_PRIV
|
||||
The intended purpose of this record is unknown. The SQE firmware actually
|
||||
ignores it and therefore msm doesn't handle it.
|
||||
|
||||
COUNTER
|
||||
This record is used to save and restore performance counters.
|
||||
|
||||
Handling the permissions of those buffers is critical for security. All but the
|
||||
NON_PRIV records need to be inaccessible from userspace, so they must be mapped
|
||||
in the kernel address space with the MSM_BO_MAP_PRIV flag.
|
||||
For example, making the NON_SECURE record accessible from userspace would allow
|
||||
any process to manipulate a saved ring's RPTR which can be used to skip the
|
||||
execution of some packets in a ring and execute user commands with higher
|
||||
privileges.
|
@ -23,6 +23,7 @@ adreno-y := \
|
||||
adreno/a6xx_gpu.o \
|
||||
adreno/a6xx_gmu.o \
|
||||
adreno/a6xx_hfi.o \
|
||||
adreno/a6xx_preempt.o \
|
||||
|
||||
adreno-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \
|
||||
|
||||
|
@ -22,7 +22,7 @@ static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
break;
|
||||
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
|
||||
/* ignore if there has not been a ctx switch: */
|
||||
if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
break;
|
||||
fallthrough;
|
||||
case MSM_SUBMIT_CMD_BUF:
|
||||
|
@ -40,7 +40,7 @@ static void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
break;
|
||||
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
|
||||
/* ignore if there has not been a ctx switch: */
|
||||
if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
break;
|
||||
fallthrough;
|
||||
case MSM_SUBMIT_CMD_BUF:
|
||||
|
@ -34,7 +34,7 @@ static void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
break;
|
||||
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
|
||||
/* ignore if there has not been a ctx switch: */
|
||||
if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
break;
|
||||
fallthrough;
|
||||
case MSM_SUBMIT_CMD_BUF:
|
||||
|
@ -77,7 +77,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
|
||||
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
|
||||
break;
|
||||
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
|
||||
if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
break;
|
||||
fallthrough;
|
||||
case MSM_SUBMIT_CMD_BUF:
|
||||
@ -132,7 +132,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
unsigned int i, ibs = 0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
|
||||
gpu->cur_ctx_seqno = 0;
|
||||
ring->cur_ctx_seqno = 0;
|
||||
a5xx_submit_in_rb(gpu, submit);
|
||||
return;
|
||||
}
|
||||
@ -171,7 +171,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
|
||||
break;
|
||||
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
|
||||
if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
break;
|
||||
fallthrough;
|
||||
case MSM_SUBMIT_CMD_BUF:
|
||||
|
@ -307,7 +307,7 @@ int a5xx_power_init(struct msm_gpu *gpu)
|
||||
else if (adreno_is_a540(adreno_gpu))
|
||||
a540_lm_setup(gpu);
|
||||
|
||||
/* Set up SP/TP power collpase */
|
||||
/* Set up SP/TP power collapse */
|
||||
a5xx_pc_init(gpu);
|
||||
|
||||
/* Start the GPMU */
|
||||
|
@ -972,6 +972,25 @@ static const struct adreno_info a6xx_gpus[] = {
|
||||
.prim_fifo_threshold = 0x00300200,
|
||||
},
|
||||
.address_space_size = SZ_16G,
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x06060300),
|
||||
.family = ADRENO_6XX_GEN4,
|
||||
.fw = {
|
||||
[ADRENO_FW_SQE] = "a660_sqe.fw",
|
||||
[ADRENO_FW_GMU] = "a663_gmu.bin",
|
||||
},
|
||||
.gmem = SZ_1M + SZ_512K,
|
||||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV,
|
||||
.init = a6xx_gpu_init,
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.hwcg = a690_hwcg,
|
||||
.protect = &a660_protect,
|
||||
.gmu_cgc_mode = 0x00020200,
|
||||
.prim_fifo_threshold = 0x00300200,
|
||||
},
|
||||
.address_space_size = SZ_16G,
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x06030500),
|
||||
.family = ADRENO_6XX_GEN4,
|
||||
@ -1281,6 +1300,28 @@ static const u32 a730_protect_regs[] = {
|
||||
};
|
||||
DECLARE_ADRENO_PROTECT(a730_protect, 48);
|
||||
|
||||
static const uint32_t a7xx_pwrup_reglist_regs[] = {
|
||||
REG_A6XX_UCHE_TRAP_BASE,
|
||||
REG_A6XX_UCHE_TRAP_BASE + 1,
|
||||
REG_A6XX_UCHE_WRITE_THRU_BASE,
|
||||
REG_A6XX_UCHE_WRITE_THRU_BASE + 1,
|
||||
REG_A6XX_UCHE_GMEM_RANGE_MIN,
|
||||
REG_A6XX_UCHE_GMEM_RANGE_MIN + 1,
|
||||
REG_A6XX_UCHE_GMEM_RANGE_MAX,
|
||||
REG_A6XX_UCHE_GMEM_RANGE_MAX + 1,
|
||||
REG_A6XX_UCHE_CACHE_WAYS,
|
||||
REG_A6XX_UCHE_MODE_CNTL,
|
||||
REG_A6XX_RB_NC_MODE_CNTL,
|
||||
REG_A6XX_RB_CMP_DBG_ECO_CNTL,
|
||||
REG_A7XX_GRAS_NC_MODE_CNTL,
|
||||
REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE,
|
||||
REG_A6XX_UCHE_GBIF_GX_CONFIG,
|
||||
REG_A6XX_UCHE_CLIENT_PF,
|
||||
REG_A6XX_TPL1_DBG_ECO_CNTL1,
|
||||
};
|
||||
|
||||
DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist);
|
||||
|
||||
static const struct adreno_info a7xx_gpus[] = {
|
||||
{
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x07000200),
|
||||
@ -1315,15 +1356,18 @@ static const struct adreno_info a7xx_gpus[] = {
|
||||
.gmem = SZ_2M,
|
||||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV,
|
||||
ADRENO_QUIRK_HAS_HW_APRIV |
|
||||
ADRENO_QUIRK_PREEMPTION,
|
||||
.init = a6xx_gpu_init,
|
||||
.zapfw = "a730_zap.mdt",
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.hwcg = a730_hwcg,
|
||||
.protect = &a730_protect,
|
||||
.pwrup_reglist = &a7xx_pwrup_reglist,
|
||||
.gmu_cgc_mode = 0x00020000,
|
||||
},
|
||||
.address_space_size = SZ_16G,
|
||||
.preempt_record_size = 2860 * SZ_1K,
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */
|
||||
.family = ADRENO_7XX_GEN2,
|
||||
@ -1334,16 +1378,19 @@ static const struct adreno_info a7xx_gpus[] = {
|
||||
.gmem = 3 * SZ_1M,
|
||||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV,
|
||||
ADRENO_QUIRK_HAS_HW_APRIV |
|
||||
ADRENO_QUIRK_PREEMPTION,
|
||||
.init = a6xx_gpu_init,
|
||||
.zapfw = "a740_zap.mdt",
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.hwcg = a740_hwcg,
|
||||
.protect = &a730_protect,
|
||||
.pwrup_reglist = &a7xx_pwrup_reglist,
|
||||
.gmu_chipid = 0x7020100,
|
||||
.gmu_cgc_mode = 0x00020202,
|
||||
},
|
||||
.address_space_size = SZ_16G,
|
||||
.preempt_record_size = 4192 * SZ_1K,
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x43050c01), /* "C512v2" */
|
||||
.family = ADRENO_7XX_GEN2,
|
||||
@ -1354,15 +1401,18 @@ static const struct adreno_info a7xx_gpus[] = {
|
||||
.gmem = 3 * SZ_1M,
|
||||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV,
|
||||
ADRENO_QUIRK_HAS_HW_APRIV |
|
||||
ADRENO_QUIRK_PREEMPTION,
|
||||
.init = a6xx_gpu_init,
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.hwcg = a740_hwcg,
|
||||
.protect = &a730_protect,
|
||||
.pwrup_reglist = &a7xx_pwrup_reglist,
|
||||
.gmu_chipid = 0x7050001,
|
||||
.gmu_cgc_mode = 0x00020202,
|
||||
},
|
||||
.address_space_size = SZ_256G,
|
||||
.preempt_record_size = 4192 * SZ_1K,
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */
|
||||
.family = ADRENO_7XX_GEN3,
|
||||
@ -1373,15 +1423,18 @@ static const struct adreno_info a7xx_gpus[] = {
|
||||
.gmem = 3 * SZ_1M,
|
||||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV,
|
||||
ADRENO_QUIRK_HAS_HW_APRIV |
|
||||
ADRENO_QUIRK_PREEMPTION,
|
||||
.init = a6xx_gpu_init,
|
||||
.zapfw = "gen70900_zap.mbn",
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.protect = &a730_protect,
|
||||
.pwrup_reglist = &a7xx_pwrup_reglist,
|
||||
.gmu_chipid = 0x7090100,
|
||||
.gmu_cgc_mode = 0x00020202,
|
||||
},
|
||||
.address_space_size = SZ_16G,
|
||||
.preempt_record_size = 3572 * SZ_1K,
|
||||
}
|
||||
};
|
||||
DECLARE_ADRENO_GPULIST(a7xx);
|
||||
|
@ -1522,15 +1522,13 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
|
||||
|
||||
irq = platform_get_irq_byname(pdev, name);
|
||||
|
||||
ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH, name, gmu);
|
||||
ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, name, gmu);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s %d\n",
|
||||
name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
disable_irq(irq);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,7 @@ struct a6xx_gmu {
|
||||
struct completion pd_gate;
|
||||
|
||||
struct qmp *qmp;
|
||||
struct a6xx_hfi_msg_bw_table *bw_table;
|
||||
};
|
||||
|
||||
static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
|
||||
|
@ -68,6 +68,8 @@ static void update_shadow_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
||||
|
||||
static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
uint32_t wptr;
|
||||
unsigned long flags;
|
||||
|
||||
@ -81,12 +83,17 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
||||
/* Make sure to wrap wptr if we need to */
|
||||
wptr = get_wptr(ring);
|
||||
|
||||
/* Update HW if this is the current ring and we are not in preempt*/
|
||||
if (!a6xx_in_preempt(a6xx_gpu)) {
|
||||
if (a6xx_gpu->cur_ring == ring)
|
||||
gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
|
||||
else
|
||||
ring->restore_wptr = true;
|
||||
} else {
|
||||
ring->restore_wptr = true;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ring->preempt_lock, flags);
|
||||
|
||||
/* Make sure everything is posted before making a decision */
|
||||
mb();
|
||||
|
||||
gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
|
||||
}
|
||||
|
||||
static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter,
|
||||
@ -110,7 +117,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
||||
u32 asid;
|
||||
u64 memptr = rbmemptr(ring, ttbr0);
|
||||
|
||||
if (ctx->seqno == a6xx_gpu->base.base.cur_ctx_seqno)
|
||||
if (ctx->seqno == ring->cur_ctx_seqno)
|
||||
return;
|
||||
|
||||
if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid))
|
||||
@ -148,12 +155,14 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
||||
|
||||
/*
|
||||
* Write the new TTBR0 to the memstore. This is good for debugging.
|
||||
* Needed for preemption
|
||||
*/
|
||||
OUT_PKT7(ring, CP_MEM_WRITE, 4);
|
||||
OUT_PKT7(ring, CP_MEM_WRITE, 5);
|
||||
OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr)));
|
||||
OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr)));
|
||||
OUT_RING(ring, lower_32_bits(ttbr));
|
||||
OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr));
|
||||
OUT_RING(ring, upper_32_bits(ttbr));
|
||||
OUT_RING(ring, ctx->seqno);
|
||||
|
||||
/*
|
||||
* Sync both threads after switching pagetables and enable BR only
|
||||
@ -229,7 +238,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
|
||||
break;
|
||||
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
|
||||
if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
break;
|
||||
fallthrough;
|
||||
case MSM_SUBMIT_CMD_BUF:
|
||||
@ -278,6 +287,46 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
a6xx_flush(gpu, ring);
|
||||
}
|
||||
|
||||
static void a6xx_emit_set_pseudo_reg(struct msm_ringbuffer *ring,
|
||||
struct a6xx_gpu *a6xx_gpu, struct msm_gpu_submitqueue *queue)
|
||||
{
|
||||
u64 preempt_postamble;
|
||||
|
||||
OUT_PKT7(ring, CP_SET_PSEUDO_REG, 12);
|
||||
|
||||
OUT_RING(ring, SMMU_INFO);
|
||||
/* don't save SMMU, we write the record from the kernel instead */
|
||||
OUT_RING(ring, 0);
|
||||
OUT_RING(ring, 0);
|
||||
|
||||
/* privileged and non secure buffer save */
|
||||
OUT_RING(ring, NON_SECURE_SAVE_ADDR);
|
||||
OUT_RING(ring, lower_32_bits(
|
||||
a6xx_gpu->preempt_iova[ring->id]));
|
||||
OUT_RING(ring, upper_32_bits(
|
||||
a6xx_gpu->preempt_iova[ring->id]));
|
||||
|
||||
/* user context buffer save, seems to be unnused by fw */
|
||||
OUT_RING(ring, NON_PRIV_SAVE_ADDR);
|
||||
OUT_RING(ring, 0);
|
||||
OUT_RING(ring, 0);
|
||||
|
||||
OUT_RING(ring, COUNTER);
|
||||
/* seems OK to set to 0 to disable it */
|
||||
OUT_RING(ring, 0);
|
||||
OUT_RING(ring, 0);
|
||||
|
||||
/* Emit postamble to clear perfcounters */
|
||||
preempt_postamble = a6xx_gpu->preempt_postamble_iova;
|
||||
|
||||
OUT_PKT7(ring, CP_SET_AMBLE, 3);
|
||||
OUT_RING(ring, lower_32_bits(preempt_postamble));
|
||||
OUT_RING(ring, upper_32_bits(preempt_postamble));
|
||||
OUT_RING(ring, CP_SET_AMBLE_2_DWORDS(
|
||||
a6xx_gpu->preempt_postamble_len) |
|
||||
CP_SET_AMBLE_2_TYPE(KMD_AMBLE_TYPE));
|
||||
}
|
||||
|
||||
static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
{
|
||||
unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT;
|
||||
@ -295,6 +344,13 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
|
||||
a6xx_set_pagetable(a6xx_gpu, ring, submit);
|
||||
|
||||
/*
|
||||
* If preemption is enabled, then set the pseudo register for the save
|
||||
* sequence
|
||||
*/
|
||||
if (gpu->nr_rings > 1)
|
||||
a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, submit->queue);
|
||||
|
||||
get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0),
|
||||
rbmemptr_stats(ring, index, cpcycles_start));
|
||||
get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER,
|
||||
@ -306,8 +362,10 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
OUT_PKT7(ring, CP_SET_MARKER, 1);
|
||||
OUT_RING(ring, 0x101); /* IFPC disable */
|
||||
|
||||
OUT_PKT7(ring, CP_SET_MARKER, 1);
|
||||
OUT_RING(ring, 0x00d); /* IB1LIST start */
|
||||
if (submit->queue->flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT) {
|
||||
OUT_PKT7(ring, CP_SET_MARKER, 1);
|
||||
OUT_RING(ring, 0x00d); /* IB1LIST start */
|
||||
}
|
||||
|
||||
/* Submit the commands */
|
||||
for (i = 0; i < submit->nr_cmds; i++) {
|
||||
@ -315,7 +373,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
|
||||
break;
|
||||
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
|
||||
if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
|
||||
break;
|
||||
fallthrough;
|
||||
case MSM_SUBMIT_CMD_BUF:
|
||||
@ -338,8 +396,10 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
update_shadow_rptr(gpu, ring);
|
||||
}
|
||||
|
||||
OUT_PKT7(ring, CP_SET_MARKER, 1);
|
||||
OUT_RING(ring, 0x00e); /* IB1LIST end */
|
||||
if (submit->queue->flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT) {
|
||||
OUT_PKT7(ring, CP_SET_MARKER, 1);
|
||||
OUT_RING(ring, 0x00e); /* IB1LIST end */
|
||||
}
|
||||
|
||||
get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0),
|
||||
rbmemptr_stats(ring, index, cpcycles_end));
|
||||
@ -386,6 +446,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
OUT_RING(ring, upper_32_bits(rbmemptr(ring, bv_fence)));
|
||||
OUT_RING(ring, submit->seqno);
|
||||
|
||||
a6xx_gpu->last_seqno[ring->id] = submit->seqno;
|
||||
|
||||
/* write the ringbuffer timestamp */
|
||||
OUT_PKT7(ring, CP_EVENT_WRITE, 4);
|
||||
OUT_RING(ring, CACHE_CLEAN | CP_EVENT_WRITE_0_IRQ | BIT(27));
|
||||
@ -399,10 +461,32 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
OUT_PKT7(ring, CP_SET_MARKER, 1);
|
||||
OUT_RING(ring, 0x100); /* IFPC enable */
|
||||
|
||||
/* If preemption is enabled */
|
||||
if (gpu->nr_rings > 1) {
|
||||
/* Yield the floor on command completion */
|
||||
OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4);
|
||||
|
||||
/*
|
||||
* If dword[2:1] are non zero, they specify an address for
|
||||
* the CP to write the value of dword[3] to on preemption
|
||||
* complete. Write 0 to skip the write
|
||||
*/
|
||||
OUT_RING(ring, 0x00);
|
||||
OUT_RING(ring, 0x00);
|
||||
/* Data value - not used if the address above is 0 */
|
||||
OUT_RING(ring, 0x01);
|
||||
/* generate interrupt on preemption completion */
|
||||
OUT_RING(ring, 0x00);
|
||||
}
|
||||
|
||||
|
||||
trace_msm_gpu_submit_flush(submit,
|
||||
gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER));
|
||||
|
||||
a6xx_flush(gpu, ring);
|
||||
|
||||
/* Check to see if we need to start preemption */
|
||||
a6xx_preempt_trigger(gpu);
|
||||
}
|
||||
|
||||
static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
|
||||
@ -551,6 +635,15 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
|
||||
gpu->ubwc_config.macrotile_mode = 1;
|
||||
}
|
||||
|
||||
if (adreno_is_a663(gpu)) {
|
||||
gpu->ubwc_config.highest_bank_bit = 13;
|
||||
gpu->ubwc_config.amsbc = 1;
|
||||
gpu->ubwc_config.rgb565_predicator = 1;
|
||||
gpu->ubwc_config.uavflagprd_inv = 2;
|
||||
gpu->ubwc_config.macrotile_mode = 1;
|
||||
gpu->ubwc_config.ubwc_swizzle = 0x4;
|
||||
}
|
||||
|
||||
if (adreno_is_7c3(gpu)) {
|
||||
gpu->ubwc_config.highest_bank_bit = 14;
|
||||
gpu->ubwc_config.amsbc = 1;
|
||||
@ -609,6 +702,77 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
|
||||
adreno_gpu->ubwc_config.macrotile_mode);
|
||||
}
|
||||
|
||||
static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
const struct adreno_reglist_list *reglist;
|
||||
void *ptr = a6xx_gpu->pwrup_reglist_ptr;
|
||||
struct cpu_gpu_lock *lock = ptr;
|
||||
u32 *dest = (u32 *)&lock->regs[0];
|
||||
int i;
|
||||
|
||||
reglist = adreno_gpu->info->a6xx->pwrup_reglist;
|
||||
|
||||
lock->gpu_req = lock->cpu_req = lock->turn = 0;
|
||||
lock->ifpc_list_len = 0;
|
||||
lock->preemption_list_len = reglist->count;
|
||||
|
||||
/*
|
||||
* For each entry in each of the lists, write the offset and the current
|
||||
* register value into the GPU buffer
|
||||
*/
|
||||
for (i = 0; i < reglist->count; i++) {
|
||||
*dest++ = reglist->regs[i];
|
||||
*dest++ = gpu_read(gpu, reglist->regs[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The overall register list is composed of
|
||||
* 1. Static IFPC-only registers
|
||||
* 2. Static IFPC + preemption registers
|
||||
* 3. Dynamic IFPC + preemption registers (ex: perfcounter selects)
|
||||
*
|
||||
* The first two lists are static. Size of these lists are stored as
|
||||
* number of pairs in ifpc_list_len and preemption_list_len
|
||||
* respectively. With concurrent binning, Some of the perfcounter
|
||||
* registers being virtualized, CP needs to know the pipe id to program
|
||||
* the aperture inorder to restore the same. Thus, third list is a
|
||||
* dynamic list with triplets as
|
||||
* (<aperture, shifted 12 bits> <address> <data>), and the length is
|
||||
* stored as number for triplets in dynamic_list_len.
|
||||
*/
|
||||
lock->dynamic_list_len = 0;
|
||||
}
|
||||
|
||||
static int a7xx_preempt_start(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct msm_ringbuffer *ring = gpu->rb[0];
|
||||
|
||||
if (gpu->nr_rings <= 1)
|
||||
return 0;
|
||||
|
||||
/* Turn CP protection off */
|
||||
OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
|
||||
OUT_RING(ring, 0);
|
||||
|
||||
a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, NULL);
|
||||
|
||||
/* Yield the floor on command completion */
|
||||
OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4);
|
||||
OUT_RING(ring, 0x00);
|
||||
OUT_RING(ring, 0x00);
|
||||
OUT_RING(ring, 0x00);
|
||||
/* Generate interrupt on preemption completion */
|
||||
OUT_RING(ring, 0x00);
|
||||
|
||||
a6xx_flush(gpu, ring);
|
||||
|
||||
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int a6xx_cp_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_ringbuffer *ring = gpu->rb[0];
|
||||
@ -640,6 +804,8 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
|
||||
|
||||
static int a7xx_cp_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct msm_ringbuffer *ring = gpu->rb[0];
|
||||
u32 mask;
|
||||
|
||||
@ -677,11 +843,11 @@ static int a7xx_cp_init(struct msm_gpu *gpu)
|
||||
|
||||
/* *Don't* send a power up reg list for concurrent binning (TODO) */
|
||||
/* Lo address */
|
||||
OUT_RING(ring, 0x00000000);
|
||||
OUT_RING(ring, lower_32_bits(a6xx_gpu->pwrup_reglist_iova));
|
||||
/* Hi address */
|
||||
OUT_RING(ring, 0x00000000);
|
||||
OUT_RING(ring, upper_32_bits(a6xx_gpu->pwrup_reglist_iova));
|
||||
/* BIT(31) set => read the regs from the list */
|
||||
OUT_RING(ring, 0x00000000);
|
||||
OUT_RING(ring, BIT(31));
|
||||
|
||||
a6xx_flush(gpu, ring);
|
||||
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
|
||||
@ -805,6 +971,16 @@ static int a6xx_ucode_load(struct msm_gpu *gpu)
|
||||
msm_gem_object_set_name(a6xx_gpu->shadow_bo, "shadow");
|
||||
}
|
||||
|
||||
a6xx_gpu->pwrup_reglist_ptr = msm_gem_kernel_new(gpu->dev, PAGE_SIZE,
|
||||
MSM_BO_WC | MSM_BO_MAP_PRIV,
|
||||
gpu->aspace, &a6xx_gpu->pwrup_reglist_bo,
|
||||
&a6xx_gpu->pwrup_reglist_iova);
|
||||
|
||||
if (IS_ERR(a6xx_gpu->pwrup_reglist_ptr))
|
||||
return PTR_ERR(a6xx_gpu->pwrup_reglist_ptr);
|
||||
|
||||
msm_gem_object_set_name(a6xx_gpu->pwrup_reglist_bo, "pwrup_reglist");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -864,6 +1040,7 @@ static int hw_init(struct msm_gpu *gpu)
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
|
||||
u64 gmem_range_min;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (!adreno_has_gmu_wrapper(adreno_gpu)) {
|
||||
@ -1072,7 +1249,7 @@ static int hw_init(struct msm_gpu *gpu)
|
||||
if (adreno_is_a690(adreno_gpu))
|
||||
gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x90);
|
||||
/* Set dualQ + disable afull for A660 GPU */
|
||||
else if (adreno_is_a660(adreno_gpu))
|
||||
else if (adreno_is_a660(adreno_gpu) || adreno_is_a663(adreno_gpu))
|
||||
gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x66906);
|
||||
else if (adreno_is_a7xx(adreno_gpu))
|
||||
gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG,
|
||||
@ -1134,22 +1311,32 @@ static int hw_init(struct msm_gpu *gpu)
|
||||
if (a6xx_gpu->shadow_bo) {
|
||||
gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR,
|
||||
shadowptr(a6xx_gpu, gpu->rb[0]));
|
||||
for (unsigned int i = 0; i < gpu->nr_rings; i++)
|
||||
a6xx_gpu->shadow[i] = 0;
|
||||
}
|
||||
|
||||
/* ..which means "always" on A7xx, also for BV shadow */
|
||||
if (adreno_is_a7xx(adreno_gpu)) {
|
||||
gpu_write64(gpu, REG_A7XX_CP_BV_RB_RPTR_ADDR,
|
||||
rbmemptr(gpu->rb[0], bv_fence));
|
||||
rbmemptr(gpu->rb[0], bv_rptr));
|
||||
}
|
||||
|
||||
a6xx_preempt_hw_init(gpu);
|
||||
|
||||
/* Always come up on rb 0 */
|
||||
a6xx_gpu->cur_ring = gpu->rb[0];
|
||||
|
||||
gpu->cur_ctx_seqno = 0;
|
||||
for (i = 0; i < gpu->nr_rings; i++)
|
||||
gpu->rb[i]->cur_ctx_seqno = 0;
|
||||
|
||||
/* Enable the SQE_to start the CP engine */
|
||||
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1);
|
||||
|
||||
if (adreno_is_a7xx(adreno_gpu) && !a6xx_gpu->pwrup_reglist_emitted) {
|
||||
a7xx_patch_pwrup_reglist(gpu);
|
||||
a6xx_gpu->pwrup_reglist_emitted = true;
|
||||
}
|
||||
|
||||
ret = adreno_is_a7xx(adreno_gpu) ? a7xx_cp_init(gpu) : a6xx_cp_init(gpu);
|
||||
if (ret)
|
||||
goto out;
|
||||
@ -1187,6 +1374,10 @@ static int hw_init(struct msm_gpu *gpu)
|
||||
out:
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
return ret;
|
||||
|
||||
/* Last step - yield the ringbuffer */
|
||||
a7xx_preempt_start(gpu);
|
||||
|
||||
/*
|
||||
* Tell the GMU that we are done touching the GPU and it can start power
|
||||
* management
|
||||
@ -1564,8 +1755,13 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
|
||||
if (status & A6XX_RBBM_INT_0_MASK_SWFUSEVIOLATION)
|
||||
a7xx_sw_fuse_violation_irq(gpu);
|
||||
|
||||
if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
|
||||
if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) {
|
||||
msm_gpu_retire(gpu);
|
||||
a6xx_preempt_trigger(gpu);
|
||||
}
|
||||
|
||||
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
|
||||
a6xx_preempt_irq(gpu);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -2259,6 +2455,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
|
||||
struct a6xx_gpu *a6xx_gpu;
|
||||
struct adreno_gpu *adreno_gpu;
|
||||
struct msm_gpu *gpu;
|
||||
extern int enable_preemption;
|
||||
bool is_a7xx;
|
||||
int ret;
|
||||
|
||||
@ -2297,7 +2494,10 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (is_a7xx)
|
||||
if ((enable_preemption == 1) || (enable_preemption == -1 &&
|
||||
(config->info->quirks & ADRENO_QUIRK_PREEMPTION)))
|
||||
ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 4);
|
||||
else if (is_a7xx)
|
||||
ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 1);
|
||||
else if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_gmuwrapper, 1);
|
||||
@ -2338,6 +2538,8 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
|
||||
a6xx_fault_handler);
|
||||
|
||||
a6xx_calc_ubwc_config(adreno_gpu);
|
||||
/* Set up the preemption specific bits and pieces for each ringbuffer */
|
||||
a6xx_preempt_init(gpu);
|
||||
|
||||
return gpu;
|
||||
}
|
||||
|
@ -12,15 +12,35 @@
|
||||
|
||||
extern bool hang_debug;
|
||||
|
||||
struct cpu_gpu_lock {
|
||||
uint32_t gpu_req;
|
||||
uint32_t cpu_req;
|
||||
uint32_t turn;
|
||||
union {
|
||||
struct {
|
||||
uint16_t list_length;
|
||||
uint16_t list_offset;
|
||||
};
|
||||
struct {
|
||||
uint8_t ifpc_list_len;
|
||||
uint8_t preemption_list_len;
|
||||
uint16_t dynamic_list_len;
|
||||
};
|
||||
};
|
||||
uint64_t regs[62];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct a6xx_info - a6xx specific information from device table
|
||||
*
|
||||
* @hwcg: hw clock gating register sequence
|
||||
* @protect: CP_PROTECT settings
|
||||
* @pwrup_reglist pwrup reglist for preemption
|
||||
*/
|
||||
struct a6xx_info {
|
||||
const struct adreno_reglist *hwcg;
|
||||
const struct adreno_protect *protect;
|
||||
const struct adreno_reglist_list *pwrup_reglist;
|
||||
u32 gmu_chipid;
|
||||
u32 gmu_cgc_mode;
|
||||
u32 prim_fifo_threshold;
|
||||
@ -33,6 +53,29 @@ struct a6xx_gpu {
|
||||
uint64_t sqe_iova;
|
||||
|
||||
struct msm_ringbuffer *cur_ring;
|
||||
struct msm_ringbuffer *next_ring;
|
||||
|
||||
struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS];
|
||||
void *preempt[MSM_GPU_MAX_RINGS];
|
||||
uint64_t preempt_iova[MSM_GPU_MAX_RINGS];
|
||||
struct drm_gem_object *preempt_smmu_bo[MSM_GPU_MAX_RINGS];
|
||||
void *preempt_smmu[MSM_GPU_MAX_RINGS];
|
||||
uint64_t preempt_smmu_iova[MSM_GPU_MAX_RINGS];
|
||||
uint32_t last_seqno[MSM_GPU_MAX_RINGS];
|
||||
|
||||
atomic_t preempt_state;
|
||||
spinlock_t eval_lock;
|
||||
struct timer_list preempt_timer;
|
||||
|
||||
unsigned int preempt_level;
|
||||
bool uses_gmem;
|
||||
bool skip_save_restore;
|
||||
|
||||
struct drm_gem_object *preempt_postamble_bo;
|
||||
void *preempt_postamble_ptr;
|
||||
uint64_t preempt_postamble_iova;
|
||||
uint64_t preempt_postamble_len;
|
||||
bool postamble_enabled;
|
||||
|
||||
struct a6xx_gmu gmu;
|
||||
|
||||
@ -40,6 +83,11 @@ struct a6xx_gpu {
|
||||
uint64_t shadow_iova;
|
||||
uint32_t *shadow;
|
||||
|
||||
struct drm_gem_object *pwrup_reglist_bo;
|
||||
void *pwrup_reglist_ptr;
|
||||
uint64_t pwrup_reglist_iova;
|
||||
bool pwrup_reglist_emitted;
|
||||
|
||||
bool has_whereami;
|
||||
|
||||
void __iomem *llc_mmio;
|
||||
@ -51,6 +99,100 @@ struct a6xx_gpu {
|
||||
|
||||
#define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base)
|
||||
|
||||
/*
|
||||
* In order to do lockless preemption we use a simple state machine to progress
|
||||
* through the process.
|
||||
*
|
||||
* PREEMPT_NONE - no preemption in progress. Next state START.
|
||||
* PREEMPT_START - The trigger is evaluating if preemption is possible. Next
|
||||
* states: TRIGGERED, NONE
|
||||
* PREEMPT_FINISH - An intermediate state before moving back to NONE. Next
|
||||
* state: NONE.
|
||||
* PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next
|
||||
* states: FAULTED, PENDING
|
||||
* PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger
|
||||
* recovery. Next state: N/A
|
||||
* PREEMPT_PENDING: Preemption complete interrupt fired - the callback is
|
||||
* checking the success of the operation. Next state: FAULTED, NONE.
|
||||
*/
|
||||
|
||||
enum a6xx_preempt_state {
|
||||
PREEMPT_NONE = 0,
|
||||
PREEMPT_START,
|
||||
PREEMPT_FINISH,
|
||||
PREEMPT_TRIGGERED,
|
||||
PREEMPT_FAULTED,
|
||||
PREEMPT_PENDING,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct a6xx_preempt_record is a shared buffer between the microcode and the
|
||||
* CPU to store the state for preemption. The record itself is much larger
|
||||
* (2112k) but most of that is used by the CP for storage.
|
||||
*
|
||||
* There is a preemption record assigned per ringbuffer. When the CPU triggers a
|
||||
* preemption, it fills out the record with the useful information (wptr, ring
|
||||
* base, etc) and the microcode uses that information to set up the CP following
|
||||
* the preemption. When a ring is switched out, the CP will save the ringbuffer
|
||||
* state back to the record. In this way, once the records are properly set up
|
||||
* the CPU can quickly switch back and forth between ringbuffers by only
|
||||
* updating a few registers (often only the wptr).
|
||||
*
|
||||
* These are the CPU aware registers in the record:
|
||||
* @magic: Must always be 0xAE399D6EUL
|
||||
* @info: Type of the record - written 0 by the CPU, updated by the CP
|
||||
* @errno: preemption error record
|
||||
* @data: Data field in YIELD and SET_MARKER packets, Written and used by CP
|
||||
* @cntl: Value of RB_CNTL written by CPU, save/restored by CP
|
||||
* @rptr: Value of RB_RPTR written by CPU, save/restored by CP
|
||||
* @wptr: Value of RB_WPTR written by CPU, save/restored by CP
|
||||
* @_pad: Reserved/padding
|
||||
* @rptr_addr: Value of RB_RPTR_ADDR_LO|HI written by CPU, save/restored by CP
|
||||
* @rbase: Value of RB_BASE written by CPU, save/restored by CP
|
||||
* @counter: GPU address of the storage area for the preemption counters
|
||||
* @bv_rptr_addr: Value of BV_RB_RPTR_ADDR_LO|HI written by CPU, save/restored by CP
|
||||
*/
|
||||
struct a6xx_preempt_record {
|
||||
u32 magic;
|
||||
u32 info;
|
||||
u32 errno;
|
||||
u32 data;
|
||||
u32 cntl;
|
||||
u32 rptr;
|
||||
u32 wptr;
|
||||
u32 _pad;
|
||||
u64 rptr_addr;
|
||||
u64 rbase;
|
||||
u64 counter;
|
||||
u64 bv_rptr_addr;
|
||||
};
|
||||
|
||||
#define A6XX_PREEMPT_RECORD_MAGIC 0xAE399D6EUL
|
||||
|
||||
#define PREEMPT_SMMU_INFO_SIZE 4096
|
||||
|
||||
#define PREEMPT_RECORD_SIZE(adreno_gpu) \
|
||||
((adreno_gpu->info->preempt_record_size) == 0 ? \
|
||||
4192 * SZ_1K : (adreno_gpu->info->preempt_record_size))
|
||||
|
||||
/*
|
||||
* The preemption counter block is a storage area for the value of the
|
||||
* preemption counters that are saved immediately before context switch. We
|
||||
* append it on to the end of the allocation for the preemption record.
|
||||
*/
|
||||
#define A6XX_PREEMPT_COUNTER_SIZE (16 * 4)
|
||||
|
||||
struct a7xx_cp_smmu_info {
|
||||
u32 magic;
|
||||
u32 _pad4;
|
||||
u64 ttbr0;
|
||||
u32 asid;
|
||||
u32 context_idr;
|
||||
u32 context_bank;
|
||||
};
|
||||
|
||||
#define GEN7_CP_SMMU_INFO_MAGIC 0x241350d5UL
|
||||
|
||||
/*
|
||||
* Given a register and a count, return a value to program into
|
||||
* REG_CP_PROTECT_REG(n) - this will block both reads and writes for
|
||||
@ -108,6 +250,34 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
|
||||
int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
|
||||
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
|
||||
|
||||
void a6xx_preempt_init(struct msm_gpu *gpu);
|
||||
void a6xx_preempt_hw_init(struct msm_gpu *gpu);
|
||||
void a6xx_preempt_trigger(struct msm_gpu *gpu);
|
||||
void a6xx_preempt_irq(struct msm_gpu *gpu);
|
||||
void a6xx_preempt_fini(struct msm_gpu *gpu);
|
||||
int a6xx_preempt_submitqueue_setup(struct msm_gpu *gpu,
|
||||
struct msm_gpu_submitqueue *queue);
|
||||
void a6xx_preempt_submitqueue_close(struct msm_gpu *gpu,
|
||||
struct msm_gpu_submitqueue *queue);
|
||||
|
||||
/* Return true if we are in a preempt state */
|
||||
static inline bool a6xx_in_preempt(struct a6xx_gpu *a6xx_gpu)
|
||||
{
|
||||
/*
|
||||
* Make sure the read to preempt_state is ordered with respect to reads
|
||||
* of other variables before ...
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
int preempt_state = atomic_read(&a6xx_gpu->preempt_state);
|
||||
|
||||
/* ... and after. */
|
||||
smp_rmb();
|
||||
|
||||
return !(preempt_state == PREEMPT_NONE ||
|
||||
preempt_state == PREEMPT_FINISH);
|
||||
}
|
||||
|
||||
void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
|
||||
bool suspended);
|
||||
unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu);
|
||||
|
@ -478,6 +478,37 @@ static void a660_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
|
||||
msg->cnoc_cmds_data[1][0] = 0x60000001;
|
||||
}
|
||||
|
||||
static void a663_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
|
||||
{
|
||||
/*
|
||||
* Send a single "off" entry just to get things running
|
||||
* TODO: bus scaling
|
||||
*/
|
||||
msg->bw_level_num = 1;
|
||||
|
||||
msg->ddr_cmds_num = 3;
|
||||
msg->ddr_wait_bitmask = 0x07;
|
||||
|
||||
msg->ddr_cmds_addrs[0] = 0x50004;
|
||||
msg->ddr_cmds_addrs[1] = 0x50000;
|
||||
msg->ddr_cmds_addrs[2] = 0x500b4;
|
||||
|
||||
msg->ddr_cmds_data[0][0] = 0x40000000;
|
||||
msg->ddr_cmds_data[0][1] = 0x40000000;
|
||||
msg->ddr_cmds_data[0][2] = 0x40000000;
|
||||
|
||||
/*
|
||||
* These are the CX (CNOC) votes - these are used by the GMU but the
|
||||
* votes are known and fixed for the target
|
||||
*/
|
||||
msg->cnoc_cmds_num = 1;
|
||||
msg->cnoc_wait_bitmask = 0x01;
|
||||
|
||||
msg->cnoc_cmds_addrs[0] = 0x50058;
|
||||
msg->cnoc_cmds_data[0][0] = 0x40000000;
|
||||
msg->cnoc_cmds_data[1][0] = 0x60000001;
|
||||
}
|
||||
|
||||
static void adreno_7c3_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
|
||||
{
|
||||
/*
|
||||
@ -630,32 +661,44 @@ static void a6xx_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
|
||||
|
||||
static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
|
||||
{
|
||||
struct a6xx_hfi_msg_bw_table msg = { 0 };
|
||||
struct a6xx_hfi_msg_bw_table *msg;
|
||||
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
|
||||
if (adreno_is_a618(adreno_gpu))
|
||||
a618_build_bw_table(&msg);
|
||||
else if (adreno_is_a619(adreno_gpu))
|
||||
a619_build_bw_table(&msg);
|
||||
else if (adreno_is_a640_family(adreno_gpu))
|
||||
a640_build_bw_table(&msg);
|
||||
else if (adreno_is_a650(adreno_gpu))
|
||||
a650_build_bw_table(&msg);
|
||||
else if (adreno_is_7c3(adreno_gpu))
|
||||
adreno_7c3_build_bw_table(&msg);
|
||||
else if (adreno_is_a660(adreno_gpu))
|
||||
a660_build_bw_table(&msg);
|
||||
else if (adreno_is_a690(adreno_gpu))
|
||||
a690_build_bw_table(&msg);
|
||||
else if (adreno_is_a730(adreno_gpu))
|
||||
a730_build_bw_table(&msg);
|
||||
else if (adreno_is_a740_family(adreno_gpu))
|
||||
a740_build_bw_table(&msg);
|
||||
else
|
||||
a6xx_build_bw_table(&msg);
|
||||
if (gmu->bw_table)
|
||||
goto send;
|
||||
|
||||
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, &msg, sizeof(msg),
|
||||
msg = devm_kzalloc(gmu->dev, sizeof(*msg), GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
if (adreno_is_a618(adreno_gpu))
|
||||
a618_build_bw_table(msg);
|
||||
else if (adreno_is_a619(adreno_gpu))
|
||||
a619_build_bw_table(msg);
|
||||
else if (adreno_is_a640_family(adreno_gpu))
|
||||
a640_build_bw_table(msg);
|
||||
else if (adreno_is_a650(adreno_gpu))
|
||||
a650_build_bw_table(msg);
|
||||
else if (adreno_is_7c3(adreno_gpu))
|
||||
adreno_7c3_build_bw_table(msg);
|
||||
else if (adreno_is_a660(adreno_gpu))
|
||||
a660_build_bw_table(msg);
|
||||
else if (adreno_is_a663(adreno_gpu))
|
||||
a663_build_bw_table(msg);
|
||||
else if (adreno_is_a690(adreno_gpu))
|
||||
a690_build_bw_table(msg);
|
||||
else if (adreno_is_a730(adreno_gpu))
|
||||
a730_build_bw_table(msg);
|
||||
else if (adreno_is_a740_family(adreno_gpu))
|
||||
a740_build_bw_table(msg);
|
||||
else
|
||||
a6xx_build_bw_table(msg);
|
||||
|
||||
gmu->bw_table = msg;
|
||||
|
||||
send:
|
||||
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, gmu->bw_table, sizeof(*(gmu->bw_table)),
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
|
456
drivers/gpu/drm/msm/adreno/a6xx_preempt.c
Normal file
456
drivers/gpu/drm/msm/adreno/a6xx_preempt.c
Normal file
@ -0,0 +1,456 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2023 Collabora, Ltd. */
|
||||
/* Copyright (c) 2024 Valve Corporation */
|
||||
|
||||
#include "msm_gem.h"
|
||||
#include "a6xx_gpu.h"
|
||||
#include "a6xx_gmu.xml.h"
|
||||
#include "msm_mmu.h"
|
||||
#include "msm_gpu_trace.h"
|
||||
|
||||
/*
|
||||
* Try to transition the preemption state from old to new. Return
|
||||
* true on success or false if the original state wasn't 'old'
|
||||
*/
|
||||
static inline bool try_preempt_state(struct a6xx_gpu *a6xx_gpu,
|
||||
enum a6xx_preempt_state old, enum a6xx_preempt_state new)
|
||||
{
|
||||
enum a6xx_preempt_state cur = atomic_cmpxchg(&a6xx_gpu->preempt_state,
|
||||
old, new);
|
||||
|
||||
return (cur == old);
|
||||
}
|
||||
|
||||
/*
|
||||
* Force the preemption state to the specified state. This is used in cases
|
||||
* where the current state is known and won't change
|
||||
*/
|
||||
static inline void set_preempt_state(struct a6xx_gpu *gpu,
|
||||
enum a6xx_preempt_state new)
|
||||
{
|
||||
/*
|
||||
* preempt_state may be read by other cores trying to trigger a
|
||||
* preemption or in the interrupt handler so barriers are needed
|
||||
* before...
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
atomic_set(&gpu->preempt_state, new);
|
||||
/* ... and after*/
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
/* Write the most recent wptr for the given ring into the hardware */
|
||||
static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint32_t wptr;
|
||||
|
||||
spin_lock_irqsave(&ring->preempt_lock, flags);
|
||||
|
||||
if (ring->restore_wptr) {
|
||||
wptr = get_wptr(ring);
|
||||
|
||||
gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
|
||||
|
||||
ring->restore_wptr = false;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ring->preempt_lock, flags);
|
||||
}
|
||||
|
||||
/* Return the highest priority ringbuffer with something in it */
|
||||
static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gpu->nr_rings; i++) {
|
||||
bool empty;
|
||||
struct msm_ringbuffer *ring = gpu->rb[i];
|
||||
|
||||
spin_lock_irqsave(&ring->preempt_lock, flags);
|
||||
empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring));
|
||||
if (!empty && ring == a6xx_gpu->cur_ring)
|
||||
empty = ring->memptrs->fence == a6xx_gpu->last_seqno[i];
|
||||
spin_unlock_irqrestore(&ring->preempt_lock, flags);
|
||||
|
||||
if (!empty)
|
||||
return ring;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void a6xx_preempt_timer(struct timer_list *t)
|
||||
{
|
||||
struct a6xx_gpu *a6xx_gpu = from_timer(a6xx_gpu, t, preempt_timer);
|
||||
struct msm_gpu *gpu = &a6xx_gpu->base.base;
|
||||
struct drm_device *dev = gpu->dev;
|
||||
|
||||
if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_FAULTED))
|
||||
return;
|
||||
|
||||
dev_err(dev->dev, "%s: preemption timed out\n", gpu->name);
|
||||
kthread_queue_work(gpu->worker, &gpu->recover_work);
|
||||
}
|
||||
|
||||
static void preempt_prepare_postamble(struct a6xx_gpu *a6xx_gpu)
|
||||
{
|
||||
u32 *postamble = a6xx_gpu->preempt_postamble_ptr;
|
||||
u32 count = 0;
|
||||
|
||||
postamble[count++] = PKT7(CP_REG_RMW, 3);
|
||||
postamble[count++] = REG_A6XX_RBBM_PERFCTR_SRAM_INIT_CMD;
|
||||
postamble[count++] = 0;
|
||||
postamble[count++] = 1;
|
||||
|
||||
postamble[count++] = PKT7(CP_WAIT_REG_MEM, 6);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_1_POLL_ADDR_LO(
|
||||
REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_2_POLL_ADDR_HI(0);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_3_REF(0x1);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_4_MASK(0x1);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0);
|
||||
|
||||
a6xx_gpu->preempt_postamble_len = count;
|
||||
|
||||
a6xx_gpu->postamble_enabled = true;
|
||||
}
|
||||
|
||||
static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu)
|
||||
{
|
||||
u32 *postamble = a6xx_gpu->preempt_postamble_ptr;
|
||||
|
||||
/*
|
||||
* Disable the postamble by replacing the first packet header with a NOP
|
||||
* that covers the whole buffer.
|
||||
*/
|
||||
*postamble = PKT7(CP_NOP, (a6xx_gpu->preempt_postamble_len - 1));
|
||||
|
||||
a6xx_gpu->postamble_enabled = false;
|
||||
}
|
||||
|
||||
void a6xx_preempt_irq(struct msm_gpu *gpu)
|
||||
{
|
||||
uint32_t status;
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct drm_device *dev = gpu->dev;
|
||||
|
||||
if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_PENDING))
|
||||
return;
|
||||
|
||||
/* Delete the preemption watchdog timer */
|
||||
del_timer(&a6xx_gpu->preempt_timer);
|
||||
|
||||
/*
|
||||
* The hardware should be setting the stop bit of CP_CONTEXT_SWITCH_CNTL
|
||||
* to zero before firing the interrupt, but there is a non zero chance
|
||||
* of a hardware condition or a software race that could set it again
|
||||
* before we have a chance to finish. If that happens, log and go for
|
||||
* recovery
|
||||
*/
|
||||
status = gpu_read(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL);
|
||||
if (unlikely(status & A6XX_CP_CONTEXT_SWITCH_CNTL_STOP)) {
|
||||
DRM_DEV_ERROR(&gpu->pdev->dev,
|
||||
"!!!!!!!!!!!!!!!! preemption faulted !!!!!!!!!!!!!! irq\n");
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_FAULTED);
|
||||
dev_err(dev->dev, "%s: Preemption failed to complete\n",
|
||||
gpu->name);
|
||||
kthread_queue_work(gpu->worker, &gpu->recover_work);
|
||||
return;
|
||||
}
|
||||
|
||||
a6xx_gpu->cur_ring = a6xx_gpu->next_ring;
|
||||
a6xx_gpu->next_ring = NULL;
|
||||
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
|
||||
|
||||
update_wptr(gpu, a6xx_gpu->cur_ring);
|
||||
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
|
||||
|
||||
trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id);
|
||||
|
||||
/*
|
||||
* Retrigger preemption to avoid a deadlock that might occur when preemption
|
||||
* is skipped due to it being already in flight when requested.
|
||||
*/
|
||||
a6xx_preempt_trigger(gpu);
|
||||
}
|
||||
|
||||
void a6xx_preempt_hw_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
int i;
|
||||
|
||||
/* No preemption if we only have one ring */
|
||||
if (gpu->nr_rings == 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < gpu->nr_rings; i++) {
|
||||
struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[i];
|
||||
|
||||
record_ptr->wptr = 0;
|
||||
record_ptr->rptr = 0;
|
||||
record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]);
|
||||
record_ptr->info = 0;
|
||||
record_ptr->data = 0;
|
||||
record_ptr->rbase = gpu->rb[i]->iova;
|
||||
}
|
||||
|
||||
/* Write a 0 to signal that we aren't switching pagetables */
|
||||
gpu_write64(gpu, REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, 0);
|
||||
|
||||
/* Enable the GMEM save/restore feature for preemption */
|
||||
gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, 0x1);
|
||||
|
||||
/* Reset the preemption state */
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
|
||||
|
||||
spin_lock_init(&a6xx_gpu->eval_lock);
|
||||
|
||||
/* Always come up on rb 0 */
|
||||
a6xx_gpu->cur_ring = gpu->rb[0];
|
||||
}
|
||||
|
||||
void a6xx_preempt_trigger(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
unsigned long flags;
|
||||
struct msm_ringbuffer *ring;
|
||||
unsigned int cntl;
|
||||
bool sysprof;
|
||||
|
||||
if (gpu->nr_rings == 1)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Lock to make sure another thread attempting preemption doesn't skip it
|
||||
* while we are still evaluating the next ring. This makes sure the other
|
||||
* thread does start preemption if we abort it and avoids a soft lock.
|
||||
*/
|
||||
spin_lock_irqsave(&a6xx_gpu->eval_lock, flags);
|
||||
|
||||
/*
|
||||
* Try to start preemption by moving from NONE to START. If
|
||||
* unsuccessful, a preemption is already in flight
|
||||
*/
|
||||
if (!try_preempt_state(a6xx_gpu, PREEMPT_NONE, PREEMPT_START)) {
|
||||
spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
cntl = A6XX_CP_CONTEXT_SWITCH_CNTL_LEVEL(a6xx_gpu->preempt_level);
|
||||
|
||||
if (a6xx_gpu->skip_save_restore)
|
||||
cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_SKIP_SAVE_RESTORE;
|
||||
|
||||
if (a6xx_gpu->uses_gmem)
|
||||
cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_USES_GMEM;
|
||||
|
||||
cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_STOP;
|
||||
|
||||
/* Get the next ring to preempt to */
|
||||
ring = get_next_ring(gpu);
|
||||
|
||||
/*
|
||||
* If no ring is populated or the highest priority ring is the current
|
||||
* one do nothing except to update the wptr to the latest and greatest
|
||||
*/
|
||||
if (!ring || (a6xx_gpu->cur_ring == ring)) {
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
|
||||
update_wptr(gpu, a6xx_gpu->cur_ring);
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
|
||||
spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&ring->preempt_lock, flags);
|
||||
|
||||
struct a7xx_cp_smmu_info *smmu_info_ptr =
|
||||
a6xx_gpu->preempt_smmu[ring->id];
|
||||
struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[ring->id];
|
||||
u64 ttbr0 = ring->memptrs->ttbr0;
|
||||
u32 context_idr = ring->memptrs->context_idr;
|
||||
|
||||
smmu_info_ptr->ttbr0 = ttbr0;
|
||||
smmu_info_ptr->context_idr = context_idr;
|
||||
record_ptr->wptr = get_wptr(ring);
|
||||
|
||||
/*
|
||||
* The GPU will write the wptr we set above when we preempt. Reset
|
||||
* restore_wptr to make sure that we don't write WPTR to the same
|
||||
* thing twice. It's still possible subsequent submissions will update
|
||||
* wptr again, in which case they will set the flag to true. This has
|
||||
* to be protected by the lock for setting the flag and updating wptr
|
||||
* to be atomic.
|
||||
*/
|
||||
ring->restore_wptr = false;
|
||||
|
||||
trace_msm_gpu_preemption_trigger(a6xx_gpu->cur_ring->id, ring->id);
|
||||
|
||||
spin_unlock_irqrestore(&ring->preempt_lock, flags);
|
||||
|
||||
gpu_write64(gpu,
|
||||
REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO,
|
||||
a6xx_gpu->preempt_smmu_iova[ring->id]);
|
||||
|
||||
gpu_write64(gpu,
|
||||
REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR,
|
||||
a6xx_gpu->preempt_iova[ring->id]);
|
||||
|
||||
a6xx_gpu->next_ring = ring;
|
||||
|
||||
/* Start a timer to catch a stuck preemption */
|
||||
mod_timer(&a6xx_gpu->preempt_timer, jiffies + msecs_to_jiffies(10000));
|
||||
|
||||
/* Enable or disable postamble as needed */
|
||||
sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1;
|
||||
|
||||
if (!sysprof && !a6xx_gpu->postamble_enabled)
|
||||
preempt_prepare_postamble(a6xx_gpu);
|
||||
|
||||
if (sysprof && a6xx_gpu->postamble_enabled)
|
||||
preempt_disable_postamble(a6xx_gpu);
|
||||
|
||||
/* Set the preemption state to triggered */
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
|
||||
|
||||
/* Trigger the preemption */
|
||||
gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl);
|
||||
}
|
||||
|
||||
static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
|
||||
struct msm_ringbuffer *ring)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
struct msm_gpu *gpu = &adreno_gpu->base;
|
||||
struct drm_gem_object *bo = NULL;
|
||||
phys_addr_t ttbr;
|
||||
u64 iova = 0;
|
||||
void *ptr;
|
||||
int asid;
|
||||
|
||||
ptr = msm_gem_kernel_new(gpu->dev,
|
||||
PREEMPT_RECORD_SIZE(adreno_gpu),
|
||||
MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova);
|
||||
|
||||
if (IS_ERR(ptr))
|
||||
return PTR_ERR(ptr);
|
||||
|
||||
memset(ptr, 0, PREEMPT_RECORD_SIZE(adreno_gpu));
|
||||
|
||||
msm_gem_object_set_name(bo, "preempt_record ring%d", ring->id);
|
||||
|
||||
a6xx_gpu->preempt_bo[ring->id] = bo;
|
||||
a6xx_gpu->preempt_iova[ring->id] = iova;
|
||||
a6xx_gpu->preempt[ring->id] = ptr;
|
||||
|
||||
struct a6xx_preempt_record *record_ptr = ptr;
|
||||
|
||||
ptr = msm_gem_kernel_new(gpu->dev,
|
||||
PREEMPT_SMMU_INFO_SIZE,
|
||||
MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY,
|
||||
gpu->aspace, &bo, &iova);
|
||||
|
||||
if (IS_ERR(ptr))
|
||||
return PTR_ERR(ptr);
|
||||
|
||||
memset(ptr, 0, PREEMPT_SMMU_INFO_SIZE);
|
||||
|
||||
msm_gem_object_set_name(bo, "preempt_smmu_info ring%d", ring->id);
|
||||
|
||||
a6xx_gpu->preempt_smmu_bo[ring->id] = bo;
|
||||
a6xx_gpu->preempt_smmu_iova[ring->id] = iova;
|
||||
a6xx_gpu->preempt_smmu[ring->id] = ptr;
|
||||
|
||||
struct a7xx_cp_smmu_info *smmu_info_ptr = ptr;
|
||||
|
||||
msm_iommu_pagetable_params(gpu->aspace->mmu, &ttbr, &asid);
|
||||
|
||||
smmu_info_ptr->magic = GEN7_CP_SMMU_INFO_MAGIC;
|
||||
smmu_info_ptr->ttbr0 = ttbr;
|
||||
smmu_info_ptr->asid = 0xdecafbad;
|
||||
smmu_info_ptr->context_idr = 0;
|
||||
|
||||
/* Set up the defaults on the preemption record */
|
||||
record_ptr->magic = A6XX_PREEMPT_RECORD_MAGIC;
|
||||
record_ptr->info = 0;
|
||||
record_ptr->data = 0;
|
||||
record_ptr->rptr = 0;
|
||||
record_ptr->wptr = 0;
|
||||
record_ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT;
|
||||
record_ptr->rbase = ring->iova;
|
||||
record_ptr->counter = 0;
|
||||
record_ptr->bv_rptr_addr = rbmemptr(ring, bv_rptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void a6xx_preempt_fini(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gpu->nr_rings; i++)
|
||||
msm_gem_kernel_put(a6xx_gpu->preempt_bo[i], gpu->aspace);
|
||||
}
|
||||
|
||||
void a6xx_preempt_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
int i;
|
||||
|
||||
/* No preemption if we only have one ring */
|
||||
if (gpu->nr_rings <= 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < gpu->nr_rings; i++) {
|
||||
if (preempt_init_ring(a6xx_gpu, gpu->rb[i]))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* TODO: make this configurable? */
|
||||
a6xx_gpu->preempt_level = 1;
|
||||
a6xx_gpu->uses_gmem = 1;
|
||||
a6xx_gpu->skip_save_restore = 1;
|
||||
|
||||
a6xx_gpu->preempt_postamble_ptr = msm_gem_kernel_new(gpu->dev,
|
||||
PAGE_SIZE,
|
||||
MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY,
|
||||
gpu->aspace, &a6xx_gpu->preempt_postamble_bo,
|
||||
&a6xx_gpu->preempt_postamble_iova);
|
||||
|
||||
preempt_prepare_postamble(a6xx_gpu);
|
||||
|
||||
if (IS_ERR(a6xx_gpu->preempt_postamble_ptr))
|
||||
goto fail;
|
||||
|
||||
timer_setup(&a6xx_gpu->preempt_timer, a6xx_preempt_timer, 0);
|
||||
|
||||
return;
|
||||
fail:
|
||||
/*
|
||||
* On any failure our adventure is over. Clean up and
|
||||
* set nr_rings to 1 to force preemption off
|
||||
*/
|
||||
a6xx_preempt_fini(gpu);
|
||||
gpu->nr_rings = 1;
|
||||
|
||||
DRM_DEV_ERROR(&gpu->pdev->dev,
|
||||
"preemption init failed, disabling preemption\n");
|
||||
|
||||
return;
|
||||
}
|
@ -20,6 +20,10 @@ bool allow_vram_carveout = false;
|
||||
MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU");
|
||||
module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600);
|
||||
|
||||
int enable_preemption = -1;
|
||||
MODULE_PARM_DESC(enable_preemption, "Enable preemption (A7xx only) (1=on , 0=disable, -1=auto (default))");
|
||||
module_param(enable_preemption, int, 0600);
|
||||
|
||||
extern const struct adreno_gpulist a2xx_gpulist;
|
||||
extern const struct adreno_gpulist a3xx_gpulist;
|
||||
extern const struct adreno_gpulist a4xx_gpulist;
|
||||
|
@ -533,7 +533,7 @@ int adreno_load_fw(struct adreno_gpu *adreno_gpu)
|
||||
if (!adreno_gpu->info->fw[i])
|
||||
continue;
|
||||
|
||||
/* Skip loading GMU firwmare with GMU Wrapper */
|
||||
/* Skip loading GMU firmware with GMU Wrapper */
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu) && i == ADRENO_FW_GMU)
|
||||
continue;
|
||||
|
||||
|
@ -56,6 +56,7 @@ enum adreno_family {
|
||||
#define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2)
|
||||
#define ADRENO_QUIRK_HAS_HW_APRIV BIT(3)
|
||||
#define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4)
|
||||
#define ADRENO_QUIRK_PREEMPTION BIT(5)
|
||||
|
||||
/* Helper for formating the chip_id in the way that userspace tools like
|
||||
* crashdec expect.
|
||||
@ -111,6 +112,7 @@ struct adreno_info {
|
||||
* {SHRT_MAX, 0} sentinal.
|
||||
*/
|
||||
struct adreno_speedbin *speedbins;
|
||||
u64 preempt_record_size;
|
||||
};
|
||||
|
||||
#define ADRENO_CHIP_IDS(tbl...) (uint32_t[]) { tbl, 0 }
|
||||
@ -156,6 +158,19 @@ static const struct adreno_protect name = { \
|
||||
.count_max = __count_max, \
|
||||
};
|
||||
|
||||
struct adreno_reglist_list {
|
||||
/** @reg: List of register **/
|
||||
const u32 *regs;
|
||||
/** @count: Number of registers in the list **/
|
||||
u32 count;
|
||||
};
|
||||
|
||||
#define DECLARE_ADRENO_REGLIST_LIST(name) \
|
||||
static const struct adreno_reglist_list name = { \
|
||||
.regs = name ## _regs, \
|
||||
.count = ARRAY_SIZE(name ## _regs), \
|
||||
};
|
||||
|
||||
struct adreno_gpu {
|
||||
struct msm_gpu base;
|
||||
const struct adreno_info *info;
|
||||
@ -455,6 +470,11 @@ static inline int adreno_is_a680(const struct adreno_gpu *gpu)
|
||||
return adreno_is_revn(gpu, 680);
|
||||
}
|
||||
|
||||
static inline int adreno_is_a663(const struct adreno_gpu *gpu)
|
||||
{
|
||||
return gpu->info->chip_ids[0] == 0x06060300;
|
||||
}
|
||||
|
||||
static inline int adreno_is_a690(const struct adreno_gpu *gpu)
|
||||
{
|
||||
return gpu->info->chip_ids[0] == 0x06090000;
|
||||
@ -656,12 +676,15 @@ OUT_PKT4(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
|
||||
OUT_RING(ring, PKT4(regindx, cnt));
|
||||
}
|
||||
|
||||
#define PKT7(opcode, cnt) \
|
||||
(CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) | \
|
||||
((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23))
|
||||
|
||||
static inline void
|
||||
OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
|
||||
{
|
||||
adreno_wait_ring(ring, cnt + 1);
|
||||
OUT_RING(ring, CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) |
|
||||
((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23));
|
||||
OUT_RING(ring, PKT7(opcode, cnt));
|
||||
}
|
||||
|
||||
struct msm_gpu *a2xx_gpu_init(struct drm_device *dev);
|
||||
|
210
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
Normal file
210
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
Normal file
@ -0,0 +1,210 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
*/
|
||||
|
||||
#ifndef _DPU_1_14_MSM8937_H
|
||||
#define _DPU_1_14_MSM8937_H
|
||||
|
||||
static const struct dpu_caps msm8937_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0x4,
|
||||
.max_linewidth = DEFAULT_DPU_LINE_WIDTH,
|
||||
.pixel_ram_size = 40 * 1024,
|
||||
.max_hdeci_exp = MAX_HORZ_DECIMATION,
|
||||
.max_vdeci_exp = MAX_VERT_DECIMATION,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg msm8937_mdp[] = {
|
||||
{
|
||||
.name = "top_0",
|
||||
.base = 0x0, .len = 0x454,
|
||||
.features = BIT(DPU_MDP_VSYNC_SEL),
|
||||
.clk_ctrls = {
|
||||
[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_ctl_cfg msm8937_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x1000, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x1200, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x1400, .len = 0x64,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg msm8937_sspp[] = {
|
||||
{
|
||||
.name = "sspp_0", .id = SSPP_VIG0,
|
||||
.base = 0x4000, .len = 0x150,
|
||||
.features = VIG_MSM8953_MASK,
|
||||
.sblk = &dpu_vig_sblk_qseed2,
|
||||
.xin_id = 0,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG0,
|
||||
}, {
|
||||
.name = "sspp_4", .id = SSPP_RGB0,
|
||||
.base = 0x14000, .len = 0x150,
|
||||
.features = RGB_MSM8953_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 1,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB0,
|
||||
}, {
|
||||
.name = "sspp_5", .id = SSPP_RGB1,
|
||||
.base = 0x16000, .len = 0x150,
|
||||
.features = RGB_MSM8953_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 5,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB1,
|
||||
}, {
|
||||
.name = "sspp_8", .id = SSPP_DMA0,
|
||||
.base = 0x24000, .len = 0x150,
|
||||
.features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR),
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 2,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA0,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg msm8937_lm[] = {
|
||||
{
|
||||
.name = "lm_0", .id = LM_0,
|
||||
.base = 0x44000, .len = 0x320,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_1,
|
||||
.pingpong = PINGPONG_0,
|
||||
.dspp = DSPP_0,
|
||||
}, {
|
||||
.name = "lm_1", .id = LM_1,
|
||||
.base = 0x45000, .len = 0x320,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_0,
|
||||
.pingpong = PINGPONG_1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_cfg msm8937_pp[] = {
|
||||
{
|
||||
.name = "pingpong_0", .id = PINGPONG_0,
|
||||
.base = 0x70000, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_MASK,
|
||||
.sblk = &msm8996_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
|
||||
}, {
|
||||
.name = "pingpong_1", .id = PINGPONG_1,
|
||||
.base = 0x70800, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_MASK,
|
||||
.sblk = &msm8996_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg msm8937_dspp[] = {
|
||||
{
|
||||
.name = "dspp_0", .id = DSPP_0,
|
||||
.base = 0x54000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &msm8998_dspp_sblk,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_intf_cfg msm8937_intf[] = {
|
||||
{
|
||||
.name = "intf_1", .id = INTF_1,
|
||||
.base = 0x6a800, .len = 0x268,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_0,
|
||||
.prog_fetch_lines_worst_case = 14,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
}, {
|
||||
.name = "intf_2", .id = INTF_2,
|
||||
.base = 0x6b000, .len = 0x268,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_1,
|
||||
.prog_fetch_lines_worst_case = 14,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg msm8937_perf_data = {
|
||||
.max_bw_low = 3100000,
|
||||
.max_bw_high = 3100000,
|
||||
.min_core_ib = 2400000,
|
||||
.min_llcc_ib = 0, /* No LLCC on this SoC */
|
||||
.min_dram_ib = 800000,
|
||||
.undersized_prefill_lines = 2,
|
||||
.xtra_prefill_lines = 2,
|
||||
.dest_scale_prefill_lines = 3,
|
||||
.macrotile_prefill_lines = 4,
|
||||
.yuv_nv12_prefill_lines = 8,
|
||||
.linear_prefill_lines = 1,
|
||||
.downscaling_prefill_lines = 1,
|
||||
.amortizable_threshold = 25,
|
||||
.min_prefill_lines = 14,
|
||||
.danger_lut_tbl = {0xf, 0xffff, 0x0},
|
||||
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
|
||||
.entries = msm8998_qos_linear
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
|
||||
.entries = msm8998_qos_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
|
||||
.entries = msm8998_qos_nrt
|
||||
},
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 105,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_mdss_version msm8937_mdss_ver = {
|
||||
.core_major_ver = 1,
|
||||
.core_minor_ver = 14,
|
||||
};
|
||||
|
||||
const struct dpu_mdss_cfg dpu_msm8937_cfg = {
|
||||
.mdss_ver = &msm8937_mdss_ver,
|
||||
.caps = &msm8937_dpu_caps,
|
||||
.mdp = msm8937_mdp,
|
||||
.ctl_count = ARRAY_SIZE(msm8937_ctl),
|
||||
.ctl = msm8937_ctl,
|
||||
.sspp_count = ARRAY_SIZE(msm8937_sspp),
|
||||
.sspp = msm8937_sspp,
|
||||
.mixer_count = ARRAY_SIZE(msm8937_lm),
|
||||
.mixer = msm8937_lm,
|
||||
.dspp_count = ARRAY_SIZE(msm8937_dspp),
|
||||
.dspp = msm8937_dspp,
|
||||
.pingpong_count = ARRAY_SIZE(msm8937_pp),
|
||||
.pingpong = msm8937_pp,
|
||||
.intf_count = ARRAY_SIZE(msm8937_intf),
|
||||
.intf = msm8937_intf,
|
||||
.vbif_count = ARRAY_SIZE(msm8996_vbif),
|
||||
.vbif = msm8996_vbif,
|
||||
.perf = &msm8937_perf_data,
|
||||
};
|
||||
|
||||
#endif
|
187
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
Normal file
187
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
Normal file
@ -0,0 +1,187 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
*/
|
||||
|
||||
#ifndef _DPU_1_14_MSM8917_H
|
||||
#define _DPU_1_14_MSM8917_H
|
||||
|
||||
static const struct dpu_caps msm8917_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0x4,
|
||||
.max_linewidth = DEFAULT_DPU_LINE_WIDTH,
|
||||
.pixel_ram_size = 16 * 1024,
|
||||
.max_hdeci_exp = MAX_HORZ_DECIMATION,
|
||||
.max_vdeci_exp = MAX_VERT_DECIMATION,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg msm8917_mdp[] = {
|
||||
{
|
||||
.name = "top_0",
|
||||
.base = 0x0, .len = 0x454,
|
||||
.features = BIT(DPU_MDP_VSYNC_SEL),
|
||||
.clk_ctrls = {
|
||||
[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_ctl_cfg msm8917_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x1000, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x1200, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x1400, .len = 0x64,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg msm8917_sspp[] = {
|
||||
{
|
||||
.name = "sspp_0", .id = SSPP_VIG0,
|
||||
.base = 0x4000, .len = 0x150,
|
||||
.features = VIG_MSM8953_MASK,
|
||||
.sblk = &dpu_vig_sblk_qseed2,
|
||||
.xin_id = 0,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG0,
|
||||
}, {
|
||||
.name = "sspp_4", .id = SSPP_RGB0,
|
||||
.base = 0x14000, .len = 0x150,
|
||||
.features = RGB_MSM8953_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 1,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB0,
|
||||
}, {
|
||||
.name = "sspp_5", .id = SSPP_RGB1,
|
||||
.base = 0x16000, .len = 0x150,
|
||||
.features = RGB_MSM8953_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 5,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB1,
|
||||
}, {
|
||||
.name = "sspp_8", .id = SSPP_DMA0,
|
||||
.base = 0x24000, .len = 0x150,
|
||||
.features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR),
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 2,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA0,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg msm8917_lm[] = {
|
||||
{
|
||||
.name = "lm_0", .id = LM_0,
|
||||
.base = 0x44000, .len = 0x320,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.pingpong = PINGPONG_0,
|
||||
.dspp = DSPP_0,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_cfg msm8917_pp[] = {
|
||||
{
|
||||
.name = "pingpong_0", .id = PINGPONG_0,
|
||||
.base = 0x70000, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_MASK,
|
||||
.sblk = &msm8996_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg msm8917_dspp[] = {
|
||||
{
|
||||
.name = "dspp_0", .id = DSPP_0,
|
||||
.base = 0x54000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &msm8998_dspp_sblk,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_intf_cfg msm8917_intf[] = {
|
||||
{
|
||||
.name = "intf_1", .id = INTF_1,
|
||||
.base = 0x6a800, .len = 0x268,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_0,
|
||||
.prog_fetch_lines_worst_case = 14,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg msm8917_perf_data = {
|
||||
.max_bw_low = 1800000,
|
||||
.max_bw_high = 1800000,
|
||||
.min_core_ib = 2400000,
|
||||
.min_llcc_ib = 0, /* No LLCC on this SoC */
|
||||
.min_dram_ib = 800000,
|
||||
.undersized_prefill_lines = 2,
|
||||
.xtra_prefill_lines = 2,
|
||||
.dest_scale_prefill_lines = 3,
|
||||
.macrotile_prefill_lines = 4,
|
||||
.yuv_nv12_prefill_lines = 8,
|
||||
.linear_prefill_lines = 1,
|
||||
.downscaling_prefill_lines = 1,
|
||||
.amortizable_threshold = 25,
|
||||
.min_prefill_lines = 21,
|
||||
.danger_lut_tbl = {0xf, 0xffff, 0x0},
|
||||
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
|
||||
.entries = msm8998_qos_linear
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
|
||||
.entries = msm8998_qos_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
|
||||
.entries = msm8998_qos_nrt
|
||||
},
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 105,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_mdss_version msm8917_mdss_ver = {
|
||||
.core_major_ver = 1,
|
||||
.core_minor_ver = 15,
|
||||
};
|
||||
|
||||
const struct dpu_mdss_cfg dpu_msm8917_cfg = {
|
||||
.mdss_ver = &msm8917_mdss_ver,
|
||||
.caps = &msm8917_dpu_caps,
|
||||
.mdp = msm8917_mdp,
|
||||
.ctl_count = ARRAY_SIZE(msm8917_ctl),
|
||||
.ctl = msm8917_ctl,
|
||||
.sspp_count = ARRAY_SIZE(msm8917_sspp),
|
||||
.sspp = msm8917_sspp,
|
||||
.mixer_count = ARRAY_SIZE(msm8917_lm),
|
||||
.mixer = msm8917_lm,
|
||||
.dspp_count = ARRAY_SIZE(msm8917_dspp),
|
||||
.dspp = msm8917_dspp,
|
||||
.pingpong_count = ARRAY_SIZE(msm8917_pp),
|
||||
.pingpong = msm8917_pp,
|
||||
.intf_count = ARRAY_SIZE(msm8917_intf),
|
||||
.intf = msm8917_intf,
|
||||
.vbif_count = ARRAY_SIZE(msm8996_vbif),
|
||||
.vbif = msm8996_vbif,
|
||||
.perf = &msm8917_perf_data,
|
||||
};
|
||||
|
||||
#endif
|
218
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
Normal file
218
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
Normal file
@ -0,0 +1,218 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
*/
|
||||
|
||||
#ifndef _DPU_1_16_MSM8953_H
|
||||
#define _DPU_1_16_MSM8953_H
|
||||
|
||||
static const struct dpu_caps msm8953_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0x4,
|
||||
.max_linewidth = DEFAULT_DPU_LINE_WIDTH,
|
||||
.pixel_ram_size = 40 * 1024,
|
||||
.max_hdeci_exp = MAX_HORZ_DECIMATION,
|
||||
.max_vdeci_exp = MAX_VERT_DECIMATION,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg msm8953_mdp[] = {
|
||||
{
|
||||
.name = "top_0",
|
||||
.base = 0x0, .len = 0x454,
|
||||
.features = BIT(DPU_MDP_VSYNC_SEL),
|
||||
.clk_ctrls = {
|
||||
[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_ctl_cfg msm8953_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x1000, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x1200, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x1400, .len = 0x64,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg msm8953_sspp[] = {
|
||||
{
|
||||
.name = "sspp_0", .id = SSPP_VIG0,
|
||||
.base = 0x4000, .len = 0x150,
|
||||
.features = VIG_MSM8953_MASK,
|
||||
.sblk = &dpu_vig_sblk_qseed2,
|
||||
.xin_id = 0,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG0,
|
||||
}, {
|
||||
.name = "sspp_4", .id = SSPP_RGB0,
|
||||
.base = 0x14000, .len = 0x150,
|
||||
.features = RGB_MSM8953_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 1,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB0,
|
||||
}, {
|
||||
.name = "sspp_5", .id = SSPP_RGB1,
|
||||
.base = 0x16000, .len = 0x150,
|
||||
.features = RGB_MSM8953_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 5,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB1,
|
||||
}, {
|
||||
.name = "sspp_8", .id = SSPP_DMA0,
|
||||
.base = 0x24000, .len = 0x150,
|
||||
.features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR),
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 2,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA0,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg msm8953_lm[] = {
|
||||
{
|
||||
.name = "lm_0", .id = LM_0,
|
||||
.base = 0x44000, .len = 0x320,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_1,
|
||||
.pingpong = PINGPONG_0,
|
||||
.dspp = DSPP_0,
|
||||
}, {
|
||||
.name = "lm_1", .id = LM_1,
|
||||
.base = 0x45000, .len = 0x320,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_0,
|
||||
.pingpong = PINGPONG_1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_cfg msm8953_pp[] = {
|
||||
{
|
||||
.name = "pingpong_0", .id = PINGPONG_0,
|
||||
.base = 0x70000, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_MASK,
|
||||
.sblk = &msm8996_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
|
||||
}, {
|
||||
.name = "pingpong_1", .id = PINGPONG_1,
|
||||
.base = 0x70800, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_MASK,
|
||||
.sblk = &msm8996_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg msm8953_dspp[] = {
|
||||
{
|
||||
.name = "dspp_0", .id = DSPP_0,
|
||||
.base = 0x54000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &msm8998_dspp_sblk,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_intf_cfg msm8953_intf[] = {
|
||||
{
|
||||
.name = "intf_0", .id = INTF_0,
|
||||
.base = 0x6a000, .len = 0x268,
|
||||
.type = INTF_NONE,
|
||||
.prog_fetch_lines_worst_case = 14,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
}, {
|
||||
.name = "intf_1", .id = INTF_1,
|
||||
.base = 0x6a800, .len = 0x268,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_0,
|
||||
.prog_fetch_lines_worst_case = 14,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
}, {
|
||||
.name = "intf_2", .id = INTF_2,
|
||||
.base = 0x6b000, .len = 0x268,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_1,
|
||||
.prog_fetch_lines_worst_case = 14,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg msm8953_perf_data = {
|
||||
.max_bw_low = 3400000,
|
||||
.max_bw_high = 3400000,
|
||||
.min_core_ib = 2400000,
|
||||
.min_llcc_ib = 0, /* No LLCC on this SoC */
|
||||
.min_dram_ib = 800000,
|
||||
.undersized_prefill_lines = 2,
|
||||
.xtra_prefill_lines = 2,
|
||||
.dest_scale_prefill_lines = 3,
|
||||
.macrotile_prefill_lines = 4,
|
||||
.yuv_nv12_prefill_lines = 8,
|
||||
.linear_prefill_lines = 1,
|
||||
.downscaling_prefill_lines = 1,
|
||||
.amortizable_threshold = 25,
|
||||
.min_prefill_lines = 14,
|
||||
.danger_lut_tbl = {0xf, 0xffff, 0x0},
|
||||
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
|
||||
.entries = msm8998_qos_linear
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
|
||||
.entries = msm8998_qos_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
|
||||
.entries = msm8998_qos_nrt
|
||||
},
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 105,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_mdss_version msm8953_mdss_ver = {
|
||||
.core_major_ver = 1,
|
||||
.core_minor_ver = 16,
|
||||
};
|
||||
|
||||
const struct dpu_mdss_cfg dpu_msm8953_cfg = {
|
||||
.mdss_ver = &msm8953_mdss_ver,
|
||||
.caps = &msm8953_dpu_caps,
|
||||
.mdp = msm8953_mdp,
|
||||
.ctl_count = ARRAY_SIZE(msm8953_ctl),
|
||||
.ctl = msm8953_ctl,
|
||||
.sspp_count = ARRAY_SIZE(msm8953_sspp),
|
||||
.sspp = msm8953_sspp,
|
||||
.mixer_count = ARRAY_SIZE(msm8953_lm),
|
||||
.mixer = msm8953_lm,
|
||||
.dspp_count = ARRAY_SIZE(msm8953_dspp),
|
||||
.dspp = msm8953_dspp,
|
||||
.pingpong_count = ARRAY_SIZE(msm8953_pp),
|
||||
.pingpong = msm8953_pp,
|
||||
.intf_count = ARRAY_SIZE(msm8953_intf),
|
||||
.intf = msm8953_intf,
|
||||
.vbif_count = ARRAY_SIZE(msm8996_vbif),
|
||||
.vbif = msm8996_vbif,
|
||||
.perf = &msm8953_perf_data,
|
||||
};
|
||||
|
||||
#endif
|
338
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
Normal file
338
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
Normal file
@ -0,0 +1,338 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
* Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DPU_1_7_MSM8996_H
|
||||
#define _DPU_1_7_MSM8996_H
|
||||
|
||||
static const struct dpu_caps msm8996_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0x7,
|
||||
.has_src_split = true,
|
||||
.max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
|
||||
.max_hdeci_exp = MAX_HORZ_DECIMATION,
|
||||
.max_vdeci_exp = MAX_VERT_DECIMATION,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg msm8996_mdp[] = {
|
||||
{
|
||||
.name = "top_0",
|
||||
.base = 0x0, .len = 0x454,
|
||||
.features = BIT(DPU_MDP_VSYNC_SEL),
|
||||
.clk_ctrls = {
|
||||
[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_RGB2] = { .reg_off = 0x2bc, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_RGB3] = { .reg_off = 0x2c4, .bit_off = 4 },
|
||||
[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
|
||||
[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 16 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_ctl_cfg msm8996_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x1000, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x1200, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x1400, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_3", .id = CTL_3,
|
||||
.base = 0x1600, .len = 0x64,
|
||||
}, {
|
||||
.name = "ctl_4", .id = CTL_4,
|
||||
.base = 0x1800, .len = 0x64,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg msm8996_sspp[] = {
|
||||
{
|
||||
.name = "sspp_0", .id = SSPP_VIG0,
|
||||
.base = 0x4000, .len = 0x150,
|
||||
.features = VIG_MSM8996_MASK,
|
||||
.sblk = &dpu_vig_sblk_qseed2,
|
||||
.xin_id = 0,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG0,
|
||||
}, {
|
||||
.name = "sspp_1", .id = SSPP_VIG1,
|
||||
.base = 0x6000, .len = 0x150,
|
||||
.features = VIG_MSM8996_MASK,
|
||||
.sblk = &dpu_vig_sblk_qseed2,
|
||||
.xin_id = 4,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG1,
|
||||
}, {
|
||||
.name = "sspp_2", .id = SSPP_VIG2,
|
||||
.base = 0x8000, .len = 0x150,
|
||||
.features = VIG_MSM8996_MASK,
|
||||
.sblk = &dpu_vig_sblk_qseed2,
|
||||
.xin_id = 8,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG2,
|
||||
}, {
|
||||
.name = "sspp_3", .id = SSPP_VIG3,
|
||||
.base = 0xa000, .len = 0x150,
|
||||
.features = VIG_MSM8996_MASK,
|
||||
.sblk = &dpu_vig_sblk_qseed2,
|
||||
.xin_id = 12,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG3,
|
||||
}, {
|
||||
.name = "sspp_4", .id = SSPP_RGB0,
|
||||
.base = 0x14000, .len = 0x150,
|
||||
.features = RGB_MSM8996_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 1,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB0,
|
||||
}, {
|
||||
.name = "sspp_5", .id = SSPP_RGB1,
|
||||
.base = 0x16000, .len = 0x150,
|
||||
.features = RGB_MSM8996_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 5,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB1,
|
||||
}, {
|
||||
.name = "sspp_6", .id = SSPP_RGB2,
|
||||
.base = 0x18000, .len = 0x150,
|
||||
.features = RGB_MSM8996_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 9,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB2,
|
||||
}, {
|
||||
.name = "sspp_7", .id = SSPP_RGB3,
|
||||
.base = 0x1a000, .len = 0x150,
|
||||
.features = RGB_MSM8996_MASK,
|
||||
.sblk = &dpu_rgb_sblk,
|
||||
.xin_id = 13,
|
||||
.type = SSPP_TYPE_RGB,
|
||||
.clk_ctrl = DPU_CLK_CTRL_RGB3,
|
||||
}, {
|
||||
.name = "sspp_8", .id = SSPP_DMA0,
|
||||
.base = 0x24000, .len = 0x150,
|
||||
.features = DMA_MSM8996_MASK,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 2,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA0,
|
||||
}, {
|
||||
.name = "sspp_9", .id = SSPP_DMA1,
|
||||
.base = 0x26000, .len = 0x150,
|
||||
.features = DMA_MSM8996_MASK,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 10,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg msm8996_lm[] = {
|
||||
{
|
||||
.name = "lm_0", .id = LM_0,
|
||||
.base = 0x44000, .len = 0x320,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_1,
|
||||
.pingpong = PINGPONG_0,
|
||||
.dspp = DSPP_0,
|
||||
}, {
|
||||
.name = "lm_1", .id = LM_1,
|
||||
.base = 0x45000, .len = 0x320,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_0,
|
||||
.pingpong = PINGPONG_1,
|
||||
.dspp = DSPP_1,
|
||||
}, {
|
||||
.name = "lm_2", .id = LM_2,
|
||||
.base = 0x46000, .len = 0x320,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_5,
|
||||
.pingpong = PINGPONG_2,
|
||||
}, {
|
||||
.name = "lm_5", .id = LM_5,
|
||||
.base = 0x49000, .len = 0x320,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_2,
|
||||
.pingpong = PINGPONG_3,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_cfg msm8996_pp[] = {
|
||||
{
|
||||
.name = "pingpong_0", .id = PINGPONG_0,
|
||||
.base = 0x70000, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_TE2_MASK,
|
||||
.sblk = &msm8996_pp_sblk_te,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
|
||||
}, {
|
||||
.name = "pingpong_1", .id = PINGPONG_1,
|
||||
.base = 0x70800, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_TE2_MASK,
|
||||
.sblk = &msm8996_pp_sblk_te,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
|
||||
}, {
|
||||
.name = "pingpong_2", .id = PINGPONG_2,
|
||||
.base = 0x71000, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_MASK,
|
||||
.sblk = &msm8996_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14),
|
||||
}, {
|
||||
.name = "pingpong_3", .id = PINGPONG_3,
|
||||
.base = 0x71800, .len = 0xd4,
|
||||
.features = PINGPONG_MSM8996_MASK,
|
||||
.sblk = &msm8996_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
|
||||
.intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_dsc_cfg msm8996_dsc[] = {
|
||||
{
|
||||
.name = "dsc_0", .id = DSC_0,
|
||||
.base = 0x80000, .len = 0x140,
|
||||
}, {
|
||||
.name = "dsc_1", .id = DSC_1,
|
||||
.base = 0x80400, .len = 0x140,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg msm8996_dspp[] = {
|
||||
{
|
||||
.name = "dspp_0", .id = DSPP_0,
|
||||
.base = 0x54000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &msm8998_dspp_sblk,
|
||||
}, {
|
||||
.name = "dspp_1", .id = DSPP_1,
|
||||
.base = 0x56000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &msm8998_dspp_sblk,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_intf_cfg msm8996_intf[] = {
|
||||
{
|
||||
.name = "intf_0", .id = INTF_0,
|
||||
.base = 0x6a000, .len = 0x268,
|
||||
.type = INTF_NONE,
|
||||
.prog_fetch_lines_worst_case = 25,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
}, {
|
||||
.name = "intf_1", .id = INTF_1,
|
||||
.base = 0x6a800, .len = 0x268,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_0,
|
||||
.prog_fetch_lines_worst_case = 25,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
}, {
|
||||
.name = "intf_2", .id = INTF_2,
|
||||
.base = 0x6b000, .len = 0x268,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_1,
|
||||
.prog_fetch_lines_worst_case = 25,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
}, {
|
||||
.name = "intf_3", .id = INTF_3,
|
||||
.base = 0x6b800, .len = 0x268,
|
||||
.type = INTF_HDMI,
|
||||
.prog_fetch_lines_worst_case = 25,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
|
||||
.intr_tear_rd_ptr = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg msm8996_perf_data = {
|
||||
.max_bw_low = 9600000,
|
||||
.max_bw_high = 9600000,
|
||||
.min_core_ib = 2400000,
|
||||
.min_llcc_ib = 0, /* No LLCC on this SoC */
|
||||
.min_dram_ib = 800000,
|
||||
.undersized_prefill_lines = 2,
|
||||
.xtra_prefill_lines = 2,
|
||||
.dest_scale_prefill_lines = 3,
|
||||
.macrotile_prefill_lines = 4,
|
||||
.yuv_nv12_prefill_lines = 8,
|
||||
.linear_prefill_lines = 1,
|
||||
.downscaling_prefill_lines = 1,
|
||||
.amortizable_threshold = 25,
|
||||
.min_prefill_lines = 21,
|
||||
.danger_lut_tbl = {0xf, 0xffff, 0x0},
|
||||
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
|
||||
.entries = msm8998_qos_linear
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
|
||||
.entries = msm8998_qos_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
|
||||
.entries = msm8998_qos_nrt
|
||||
},
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 105,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_mdss_version msm8996_mdss_ver = {
|
||||
.core_major_ver = 1,
|
||||
.core_minor_ver = 7,
|
||||
};
|
||||
|
||||
const struct dpu_mdss_cfg dpu_msm8996_cfg = {
|
||||
.mdss_ver = &msm8996_mdss_ver,
|
||||
.caps = &msm8996_dpu_caps,
|
||||
.mdp = msm8996_mdp,
|
||||
.ctl_count = ARRAY_SIZE(msm8996_ctl),
|
||||
.ctl = msm8996_ctl,
|
||||
.sspp_count = ARRAY_SIZE(msm8996_sspp),
|
||||
.sspp = msm8996_sspp,
|
||||
.mixer_count = ARRAY_SIZE(msm8996_lm),
|
||||
.mixer = msm8996_lm,
|
||||
.dspp_count = ARRAY_SIZE(msm8996_dspp),
|
||||
.dspp = msm8996_dspp,
|
||||
.pingpong_count = ARRAY_SIZE(msm8996_pp),
|
||||
.pingpong = msm8996_pp,
|
||||
.dsc_count = ARRAY_SIZE(msm8996_dsc),
|
||||
.dsc = msm8996_dsc,
|
||||
.intf_count = ARRAY_SIZE(msm8996_intf),
|
||||
.intf = msm8996_intf,
|
||||
.vbif_count = ARRAY_SIZE(msm8996_vbif),
|
||||
.vbif = msm8996_vbif,
|
||||
.perf = &msm8996_perf_data,
|
||||
};
|
||||
|
||||
#endif
|
@ -156,18 +156,6 @@ static const struct dpu_lm_cfg msm8998_lm[] = {
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.lm_pair = LM_5,
|
||||
.pingpong = PINGPONG_2,
|
||||
}, {
|
||||
.name = "lm_3", .id = LM_3,
|
||||
.base = 0x47000, .len = 0x320,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.pingpong = PINGPONG_NONE,
|
||||
}, {
|
||||
.name = "lm_4", .id = LM_4,
|
||||
.base = 0x48000, .len = 0x320,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &msm8998_lm_sblk,
|
||||
.pingpong = PINGPONG_NONE,
|
||||
}, {
|
||||
.name = "lm_5", .id = LM_5,
|
||||
.base = 0x49000, .len = 0x320,
|
||||
|
@ -155,19 +155,6 @@ static const struct dpu_lm_cfg sdm845_lm[] = {
|
||||
.lm_pair = LM_5,
|
||||
.pingpong = PINGPONG_2,
|
||||
.dspp = DSPP_2,
|
||||
}, {
|
||||
.name = "lm_3", .id = LM_3,
|
||||
.base = 0x0, .len = 0x320,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.pingpong = PINGPONG_NONE,
|
||||
.dspp = DSPP_3,
|
||||
}, {
|
||||
.name = "lm_4", .id = LM_4,
|
||||
.base = 0x0, .len = 0x320,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.pingpong = PINGPONG_NONE,
|
||||
}, {
|
||||
.name = "lm_5", .id = LM_5,
|
||||
.base = 0x49000, .len = 0x320,
|
||||
@ -175,6 +162,7 @@ static const struct dpu_lm_cfg sdm845_lm[] = {
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_2,
|
||||
.pingpong = PINGPONG_3,
|
||||
.dspp = DSPP_3,
|
||||
},
|
||||
};
|
||||
|
||||
|
485
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
Normal file
485
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
Normal file
@ -0,0 +1,485 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DPU_8_4_SA8775P_H
|
||||
#define _DPU_8_4_SA8775P_H
|
||||
|
||||
static const struct dpu_caps sa8775p_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0xb,
|
||||
.has_src_split = true,
|
||||
.has_dim_layer = true,
|
||||
.has_idle_pc = true,
|
||||
.has_3d_merge = true,
|
||||
.max_linewidth = 5120,
|
||||
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg sa8775p_mdp = {
|
||||
.name = "top_0",
|
||||
.base = 0x0, .len = 0x494,
|
||||
.features = BIT(DPU_MDP_PERIPH_0_REMOVED),
|
||||
.clk_ctrls = {
|
||||
[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0 },
|
||||
[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8 },
|
||||
[DPU_CLK_CTRL_WB2] = { .reg_off = 0x2bc, .bit_off = 16 },
|
||||
[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
|
||||
},
|
||||
};
|
||||
|
||||
/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */
|
||||
static const struct dpu_ctl_cfg sa8775p_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x15000, .len = 0x204,
|
||||
.features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
|
||||
}, {
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x16000, .len = 0x204,
|
||||
.features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
|
||||
}, {
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x17000, .len = 0x204,
|
||||
.features = CTL_SC7280_MASK,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
|
||||
}, {
|
||||
.name = "ctl_3", .id = CTL_3,
|
||||
.base = 0x18000, .len = 0x204,
|
||||
.features = CTL_SC7280_MASK,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
|
||||
}, {
|
||||
.name = "ctl_4", .id = CTL_4,
|
||||
.base = 0x19000, .len = 0x204,
|
||||
.features = CTL_SC7280_MASK,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
|
||||
}, {
|
||||
.name = "ctl_5", .id = CTL_5,
|
||||
.base = 0x1a000, .len = 0x204,
|
||||
.features = CTL_SC7280_MASK,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg sa8775p_sspp[] = {
|
||||
{
|
||||
.name = "sspp_0", .id = SSPP_VIG0,
|
||||
.base = 0x4000, .len = 0x32c,
|
||||
.features = VIG_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_vig_sblk_qseed3_3_1,
|
||||
.xin_id = 0,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG0,
|
||||
}, {
|
||||
.name = "sspp_1", .id = SSPP_VIG1,
|
||||
.base = 0x6000, .len = 0x32c,
|
||||
.features = VIG_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_vig_sblk_qseed3_3_1,
|
||||
.xin_id = 4,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG1,
|
||||
}, {
|
||||
.name = "sspp_2", .id = SSPP_VIG2,
|
||||
.base = 0x8000, .len = 0x32c,
|
||||
.features = VIG_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_vig_sblk_qseed3_3_1,
|
||||
.xin_id = 8,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG2,
|
||||
}, {
|
||||
.name = "sspp_3", .id = SSPP_VIG3,
|
||||
.base = 0xa000, .len = 0x32c,
|
||||
.features = VIG_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_vig_sblk_qseed3_3_1,
|
||||
.xin_id = 12,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
.clk_ctrl = DPU_CLK_CTRL_VIG3,
|
||||
}, {
|
||||
.name = "sspp_8", .id = SSPP_DMA0,
|
||||
.base = 0x24000, .len = 0x32c,
|
||||
.features = DMA_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 1,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA0,
|
||||
}, {
|
||||
.name = "sspp_9", .id = SSPP_DMA1,
|
||||
.base = 0x26000, .len = 0x32c,
|
||||
.features = DMA_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 5,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA1,
|
||||
}, {
|
||||
.name = "sspp_10", .id = SSPP_DMA2,
|
||||
.base = 0x28000, .len = 0x32c,
|
||||
.features = DMA_CURSOR_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 9,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA2,
|
||||
}, {
|
||||
.name = "sspp_11", .id = SSPP_DMA3,
|
||||
.base = 0x2a000, .len = 0x32c,
|
||||
.features = DMA_CURSOR_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 13,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
.clk_ctrl = DPU_CLK_CTRL_DMA3,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg sa8775p_lm[] = {
|
||||
{
|
||||
.name = "lm_0", .id = LM_0,
|
||||
.base = 0x44000, .len = 0x400,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_1,
|
||||
.pingpong = PINGPONG_0,
|
||||
.dspp = DSPP_0,
|
||||
}, {
|
||||
.name = "lm_1", .id = LM_1,
|
||||
.base = 0x45000, .len = 0x400,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_0,
|
||||
.pingpong = PINGPONG_1,
|
||||
.dspp = DSPP_1,
|
||||
}, {
|
||||
.name = "lm_2", .id = LM_2,
|
||||
.base = 0x46000, .len = 0x400,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_3,
|
||||
.pingpong = PINGPONG_2,
|
||||
.dspp = DSPP_2,
|
||||
}, {
|
||||
.name = "lm_3", .id = LM_3,
|
||||
.base = 0x47000, .len = 0x400,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_2,
|
||||
.pingpong = PINGPONG_3,
|
||||
.dspp = DSPP_3,
|
||||
}, {
|
||||
.name = "lm_4", .id = LM_4,
|
||||
.base = 0x48000, .len = 0x400,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_5,
|
||||
.pingpong = PINGPONG_4,
|
||||
}, {
|
||||
.name = "lm_5", .id = LM_5,
|
||||
.base = 0x49000, .len = 0x400,
|
||||
.features = MIXER_SDM845_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_4,
|
||||
.pingpong = PINGPONG_5,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg sa8775p_dspp[] = {
|
||||
{
|
||||
.name = "dspp_0", .id = DSPP_0,
|
||||
.base = 0x54000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &sdm845_dspp_sblk,
|
||||
}, {
|
||||
.name = "dspp_1", .id = DSPP_1,
|
||||
.base = 0x56000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &sdm845_dspp_sblk,
|
||||
}, {
|
||||
.name = "dspp_2", .id = DSPP_2,
|
||||
.base = 0x58000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &sdm845_dspp_sblk,
|
||||
}, {
|
||||
.name = "dspp_3", .id = DSPP_3,
|
||||
.base = 0x5a000, .len = 0x1800,
|
||||
.features = DSPP_SC7180_MASK,
|
||||
.sblk = &sdm845_dspp_sblk,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_cfg sa8775p_pp[] = {
|
||||
{
|
||||
.name = "pingpong_0", .id = PINGPONG_0,
|
||||
.base = 0x69000, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_0,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
|
||||
}, {
|
||||
.name = "pingpong_1", .id = PINGPONG_1,
|
||||
.base = 0x6a000, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_0,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
|
||||
}, {
|
||||
.name = "pingpong_2", .id = PINGPONG_2,
|
||||
.base = 0x6b000, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_1,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
|
||||
}, {
|
||||
.name = "pingpong_3", .id = PINGPONG_3,
|
||||
.base = 0x6c000, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_1,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
|
||||
}, {
|
||||
.name = "pingpong_4", .id = PINGPONG_4,
|
||||
.base = 0x6d000, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_2,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
|
||||
}, {
|
||||
.name = "pingpong_5", .id = PINGPONG_5,
|
||||
.base = 0x6e000, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_2,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
|
||||
}, {
|
||||
.name = "pingpong_6", .id = PINGPONG_6,
|
||||
.base = 0x65800, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_3,
|
||||
}, {
|
||||
.name = "pingpong_7", .id = PINGPONG_7,
|
||||
.base = 0x65c00, .len = 0,
|
||||
.features = BIT(DPU_PINGPONG_DITHER),
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_3,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_merge_3d_cfg sa8775p_merge_3d[] = {
|
||||
{
|
||||
.name = "merge_3d_0", .id = MERGE_3D_0,
|
||||
.base = 0x4e000, .len = 0x8,
|
||||
}, {
|
||||
.name = "merge_3d_1", .id = MERGE_3D_1,
|
||||
.base = 0x4f000, .len = 0x8,
|
||||
}, {
|
||||
.name = "merge_3d_2", .id = MERGE_3D_2,
|
||||
.base = 0x50000, .len = 0x8,
|
||||
}, {
|
||||
.name = "merge_3d_3", .id = MERGE_3D_3,
|
||||
.base = 0x65f00, .len = 0x8,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* NOTE: Each display compression engine (DCE) contains dual hard
|
||||
* slice DSC encoders so both share same base address but with
|
||||
* its own different sub block address.
|
||||
*/
|
||||
static const struct dpu_dsc_cfg sa8775p_dsc[] = {
|
||||
{
|
||||
.name = "dce_0_0", .id = DSC_0,
|
||||
.base = 0x80000, .len = 0x4,
|
||||
.features = BIT(DPU_DSC_HW_REV_1_2),
|
||||
.sblk = &dsc_sblk_0,
|
||||
}, {
|
||||
.name = "dce_0_1", .id = DSC_1,
|
||||
.base = 0x80000, .len = 0x4,
|
||||
.features = BIT(DPU_DSC_HW_REV_1_2),
|
||||
.sblk = &dsc_sblk_1,
|
||||
}, {
|
||||
.name = "dce_1_0", .id = DSC_2,
|
||||
.base = 0x81000, .len = 0x4,
|
||||
.features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
|
||||
.sblk = &dsc_sblk_0,
|
||||
}, {
|
||||
.name = "dce_1_1", .id = DSC_3,
|
||||
.base = 0x81000, .len = 0x4,
|
||||
.features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
|
||||
.sblk = &dsc_sblk_1,
|
||||
}, {
|
||||
.name = "dce_2_0", .id = DSC_4,
|
||||
.base = 0x82000, .len = 0x4,
|
||||
.features = BIT(DPU_DSC_HW_REV_1_2),
|
||||
.sblk = &dsc_sblk_0,
|
||||
}, {
|
||||
.name = "dce_2_1", .id = DSC_5,
|
||||
.base = 0x82000, .len = 0x4,
|
||||
.features = BIT(DPU_DSC_HW_REV_1_2),
|
||||
.sblk = &dsc_sblk_1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_wb_cfg sa8775p_wb[] = {
|
||||
{
|
||||
.name = "wb_2", .id = WB_2,
|
||||
.base = 0x65000, .len = 0x2c8,
|
||||
.features = WB_SM8250_MASK,
|
||||
.format_list = wb2_formats_rgb_yuv,
|
||||
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
|
||||
.clk_ctrl = DPU_CLK_CTRL_WB2,
|
||||
.xin_id = 6,
|
||||
.vbif_idx = VBIF_RT,
|
||||
.maxlinewidth = 4096,
|
||||
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
|
||||
},
|
||||
};
|
||||
|
||||
/* TODO: INTF 3, 6, 7 and 8 are used for MST, marked as INTF_NONE for now */
|
||||
static const struct dpu_intf_cfg sa8775p_intf[] = {
|
||||
{
|
||||
.name = "intf_0", .id = INTF_0,
|
||||
.base = 0x34000, .len = 0x280,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_DP,
|
||||
.controller_id = MSM_DP_CONTROLLER_0,
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
|
||||
}, {
|
||||
.name = "intf_1", .id = INTF_1,
|
||||
.base = 0x35000, .len = 0x300,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_0,
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
|
||||
.intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2),
|
||||
}, {
|
||||
.name = "intf_2", .id = INTF_2,
|
||||
.base = 0x36000, .len = 0x300,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_DSI,
|
||||
.controller_id = MSM_DSI_CONTROLLER_1,
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
|
||||
.intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2),
|
||||
}, {
|
||||
.name = "intf_3", .id = INTF_3,
|
||||
.base = 0x37000, .len = 0x280,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_NONE,
|
||||
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
|
||||
}, {
|
||||
.name = "intf_4", .id = INTF_4,
|
||||
.base = 0x38000, .len = 0x280,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_DP,
|
||||
.controller_id = MSM_DP_CONTROLLER_1,
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21),
|
||||
}, {
|
||||
.name = "intf_6", .id = INTF_6,
|
||||
.base = 0x3A000, .len = 0x280,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_NONE,
|
||||
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16),
|
||||
}, {
|
||||
.name = "intf_7", .id = INTF_7,
|
||||
.base = 0x3b000, .len = 0x280,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_NONE,
|
||||
.controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19),
|
||||
}, {
|
||||
.name = "intf_8", .id = INTF_8,
|
||||
.base = 0x3c000, .len = 0x280,
|
||||
.features = INTF_SC7280_MASK,
|
||||
.type = INTF_NONE,
|
||||
.controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */
|
||||
.prog_fetch_lines_worst_case = 24,
|
||||
.intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
|
||||
.intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg sa8775p_perf_data = {
|
||||
.max_bw_low = 13600000,
|
||||
.max_bw_high = 18200000,
|
||||
.min_core_ib = 2500000,
|
||||
.min_llcc_ib = 0,
|
||||
.min_dram_ib = 800000,
|
||||
.min_prefill_lines = 35,
|
||||
/* FIXME: lut tables */
|
||||
.danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0},
|
||||
.safe_lut_tbl = {0xfff0, 0xfff0, 0x1},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
|
||||
.entries = sm6350_qos_linear_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
|
||||
.entries = sm6350_qos_linear_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(sc7180_qos_nrt),
|
||||
.entries = sc7180_qos_nrt
|
||||
},
|
||||
/* TODO: macrotile-qseed is different from macrotile */
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 105,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_mdss_version sa8775p_mdss_ver = {
|
||||
.core_major_ver = 8,
|
||||
.core_minor_ver = 4,
|
||||
};
|
||||
|
||||
const struct dpu_mdss_cfg dpu_sa8775p_cfg = {
|
||||
.mdss_ver = &sa8775p_mdss_ver,
|
||||
.caps = &sa8775p_dpu_caps,
|
||||
.mdp = &sa8775p_mdp,
|
||||
.cdm = &sc7280_cdm,
|
||||
.ctl_count = ARRAY_SIZE(sa8775p_ctl),
|
||||
.ctl = sa8775p_ctl,
|
||||
.sspp_count = ARRAY_SIZE(sa8775p_sspp),
|
||||
.sspp = sa8775p_sspp,
|
||||
.mixer_count = ARRAY_SIZE(sa8775p_lm),
|
||||
.mixer = sa8775p_lm,
|
||||
.dspp_count = ARRAY_SIZE(sa8775p_dspp),
|
||||
.dspp = sa8775p_dspp,
|
||||
.pingpong_count = ARRAY_SIZE(sa8775p_pp),
|
||||
.pingpong = sa8775p_pp,
|
||||
.dsc_count = ARRAY_SIZE(sa8775p_dsc),
|
||||
.dsc = sa8775p_dsc,
|
||||
.merge_3d_count = ARRAY_SIZE(sa8775p_merge_3d),
|
||||
.merge_3d = sa8775p_merge_3d,
|
||||
.wb_count = ARRAY_SIZE(sa8775p_wb),
|
||||
.wb = sa8775p_wb,
|
||||
.intf_count = ARRAY_SIZE(sa8775p_intf),
|
||||
.intf = sa8775p_intf,
|
||||
.vbif_count = ARRAY_SIZE(sdm845_vbif),
|
||||
.vbif = sdm845_vbif,
|
||||
.perf = &sa8775p_perf_data,
|
||||
};
|
||||
|
||||
#endif
|
@ -1230,6 +1230,19 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
|
||||
|
||||
/*
|
||||
* max crtc width is equal to the max mixer width * 2 and max height is 4K
|
||||
*/
|
||||
return drm_mode_validate_size(mode,
|
||||
2 * dpu_kms->catalog->caps->max_mixer_width,
|
||||
4096);
|
||||
}
|
||||
|
||||
int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
|
||||
{
|
||||
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
|
||||
@ -1445,6 +1458,7 @@ static const struct drm_crtc_helper_funcs dpu_crtc_helper_funcs = {
|
||||
.atomic_check = dpu_crtc_atomic_check,
|
||||
.atomic_begin = dpu_crtc_atomic_begin,
|
||||
.atomic_flush = dpu_crtc_atomic_flush,
|
||||
.mode_valid = dpu_crtc_mode_valid,
|
||||
.get_scanout_position = dpu_crtc_get_scanout_position,
|
||||
};
|
||||
|
||||
|
@ -166,10 +166,10 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
|
||||
/**
|
||||
* dpu_encoder_phys_wb_setup_fb - setup output framebuffer
|
||||
* @phys_enc: Pointer to physical encoder
|
||||
* @fb: Pointer to output framebuffer
|
||||
* @format: Format of the framebuffer
|
||||
*/
|
||||
static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
|
||||
struct drm_framebuffer *fb)
|
||||
const struct msm_format *format)
|
||||
{
|
||||
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
|
||||
struct dpu_hw_wb *hw_wb;
|
||||
@ -193,12 +193,12 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
|
||||
hw_wb->ops.setup_roi(hw_wb, wb_cfg);
|
||||
|
||||
if (hw_wb->ops.setup_outformat)
|
||||
hw_wb->ops.setup_outformat(hw_wb, wb_cfg);
|
||||
hw_wb->ops.setup_outformat(hw_wb, wb_cfg, format);
|
||||
|
||||
if (hw_wb->ops.setup_cdp) {
|
||||
const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf;
|
||||
|
||||
hw_wb->ops.setup_cdp(hw_wb, wb_cfg->dest.format,
|
||||
hw_wb->ops.setup_cdp(hw_wb, format,
|
||||
perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable);
|
||||
}
|
||||
|
||||
@ -321,15 +321,10 @@ static void dpu_encoder_phys_wb_setup(
|
||||
{
|
||||
struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
|
||||
struct drm_display_mode mode = phys_enc->cached_mode;
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
|
||||
struct drm_writeback_job *wb_job;
|
||||
const struct msm_format *format;
|
||||
const struct msm_format *dpu_fmt;
|
||||
|
||||
wb_job = wb_enc->wb_job;
|
||||
format = msm_framebuffer_format(wb_enc->wb_job->fb);
|
||||
dpu_fmt = mdp_get_format(&phys_enc->dpu_kms->base, format->pixel_format, wb_job->fb->modifier);
|
||||
|
||||
DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n",
|
||||
hw_wb->idx - WB_0, mode.name,
|
||||
@ -341,9 +336,9 @@ static void dpu_encoder_phys_wb_setup(
|
||||
|
||||
dpu_encoder_phys_wb_set_qos(phys_enc);
|
||||
|
||||
dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
|
||||
dpu_encoder_phys_wb_setup_fb(phys_enc, format);
|
||||
|
||||
dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
|
||||
dpu_encoder_helper_phys_setup_cdm(phys_enc, format, CDM_CDWN_OUTPUT_WB);
|
||||
|
||||
dpu_encoder_phys_wb_setup_ctl(phys_enc);
|
||||
}
|
||||
@ -587,26 +582,20 @@ static void dpu_encoder_phys_wb_prepare_wb_job(struct dpu_encoder_phys *phys_enc
|
||||
|
||||
format = msm_framebuffer_format(job->fb);
|
||||
|
||||
wb_cfg->dest.format = mdp_get_format(&phys_enc->dpu_kms->base,
|
||||
format->pixel_format, job->fb->modifier);
|
||||
if (!wb_cfg->dest.format) {
|
||||
/* this error should be detected during atomic_check */
|
||||
DPU_ERROR("failed to get format %p4cc\n", &format->pixel_format);
|
||||
ret = dpu_format_populate_plane_sizes(job->fb, &wb_cfg->dest);
|
||||
if (ret) {
|
||||
DPU_DEBUG("failed to populate plane sizes%d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = dpu_format_populate_layout(aspace, job->fb, &wb_cfg->dest);
|
||||
if (ret) {
|
||||
DPU_DEBUG("failed to populate layout %d\n", ret);
|
||||
return;
|
||||
}
|
||||
dpu_format_populate_addrs(aspace, job->fb, &wb_cfg->dest);
|
||||
|
||||
wb_cfg->dest.width = job->fb->width;
|
||||
wb_cfg->dest.height = job->fb->height;
|
||||
wb_cfg->dest.num_planes = wb_cfg->dest.format->num_planes;
|
||||
wb_cfg->dest.num_planes = format->num_planes;
|
||||
|
||||
if ((wb_cfg->dest.format->fetch_type == MDP_PLANE_PLANAR) &&
|
||||
(wb_cfg->dest.format->element[0] == C1_B_Cb))
|
||||
if ((format->fetch_type == MDP_PLANE_PLANAR) &&
|
||||
(format->element[0] == C1_B_Cb))
|
||||
swap(wb_cfg->dest.plane_addr[1], wb_cfg->dest.plane_addr[2]);
|
||||
|
||||
DPU_DEBUG("[fb_offset:%8.8x,%8.8x,%8.8x,%8.8x]\n",
|
||||
|
@ -13,9 +13,6 @@
|
||||
|
||||
#define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096
|
||||
|
||||
#define DPU_MAX_IMG_WIDTH 0x3FFF
|
||||
#define DPU_MAX_IMG_HEIGHT 0x3FFF
|
||||
|
||||
/*
|
||||
* struct dpu_media_color_map - maps drm format to media format
|
||||
* @format: DRM base pixel format
|
||||
@ -93,10 +90,9 @@ static int _dpu_format_get_media_color_ubwc(const struct msm_format *fmt)
|
||||
return color_fmt;
|
||||
}
|
||||
|
||||
static int _dpu_format_get_plane_sizes_ubwc(
|
||||
static int _dpu_format_populate_plane_sizes_ubwc(
|
||||
const struct msm_format *fmt,
|
||||
const uint32_t width,
|
||||
const uint32_t height,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
{
|
||||
int i;
|
||||
@ -104,9 +100,8 @@ static int _dpu_format_get_plane_sizes_ubwc(
|
||||
bool meta = MSM_FORMAT_IS_UBWC(fmt);
|
||||
|
||||
memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
|
||||
layout->format = fmt;
|
||||
layout->width = width;
|
||||
layout->height = height;
|
||||
layout->width = fb->width;
|
||||
layout->height = fb->height;
|
||||
layout->num_planes = fmt->num_planes;
|
||||
|
||||
color = _dpu_format_get_media_color_ubwc(fmt);
|
||||
@ -116,19 +111,19 @@ static int _dpu_format_get_plane_sizes_ubwc(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (MSM_FORMAT_IS_YUV(layout->format)) {
|
||||
if (MSM_FORMAT_IS_YUV(fmt)) {
|
||||
uint32_t y_sclines, uv_sclines;
|
||||
uint32_t y_meta_scanlines = 0;
|
||||
uint32_t uv_meta_scanlines = 0;
|
||||
|
||||
layout->num_planes = 2;
|
||||
layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
|
||||
y_sclines = VENUS_Y_SCANLINES(color, height);
|
||||
layout->plane_pitch[0] = VENUS_Y_STRIDE(color, fb->width);
|
||||
y_sclines = VENUS_Y_SCANLINES(color, fb->height);
|
||||
layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
|
||||
y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
|
||||
|
||||
layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
|
||||
uv_sclines = VENUS_UV_SCANLINES(color, height);
|
||||
layout->plane_pitch[1] = VENUS_UV_STRIDE(color, fb->width);
|
||||
uv_sclines = VENUS_UV_SCANLINES(color, fb->height);
|
||||
layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
|
||||
uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
|
||||
|
||||
@ -136,13 +131,13 @@ static int _dpu_format_get_plane_sizes_ubwc(
|
||||
goto done;
|
||||
|
||||
layout->num_planes += 2;
|
||||
layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
|
||||
y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
|
||||
layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, fb->width);
|
||||
y_meta_scanlines = VENUS_Y_META_SCANLINES(color, fb->height);
|
||||
layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
|
||||
y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
|
||||
|
||||
layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
|
||||
uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
|
||||
layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, fb->width);
|
||||
uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, fb->height);
|
||||
layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
|
||||
uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
|
||||
|
||||
@ -151,16 +146,16 @@ static int _dpu_format_get_plane_sizes_ubwc(
|
||||
|
||||
layout->num_planes = 1;
|
||||
|
||||
layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
|
||||
rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
|
||||
layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, fb->width);
|
||||
rgb_scanlines = VENUS_RGB_SCANLINES(color, fb->height);
|
||||
layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
|
||||
rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
|
||||
|
||||
if (!meta)
|
||||
goto done;
|
||||
layout->num_planes += 2;
|
||||
layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
|
||||
rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
|
||||
layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, fb->width);
|
||||
rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, fb->height);
|
||||
layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
|
||||
rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
|
||||
}
|
||||
@ -172,26 +167,23 @@ static int _dpu_format_get_plane_sizes_ubwc(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dpu_format_get_plane_sizes_linear(
|
||||
static int _dpu_format_populate_plane_sizes_linear(
|
||||
const struct msm_format *fmt,
|
||||
const uint32_t width,
|
||||
const uint32_t height,
|
||||
struct dpu_hw_fmt_layout *layout,
|
||||
const uint32_t *pitches)
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
|
||||
layout->format = fmt;
|
||||
layout->width = width;
|
||||
layout->height = height;
|
||||
layout->width = fb->width;
|
||||
layout->height = fb->height;
|
||||
layout->num_planes = fmt->num_planes;
|
||||
|
||||
/* Due to memset above, only need to set planes of interest */
|
||||
if (fmt->fetch_type == MDP_PLANE_INTERLEAVED) {
|
||||
layout->num_planes = 1;
|
||||
layout->plane_size[0] = width * height * layout->format->bpp;
|
||||
layout->plane_pitch[0] = width * layout->format->bpp;
|
||||
layout->plane_size[0] = fb->width * fb->height * fmt->bpp;
|
||||
layout->plane_pitch[0] = fb->width * fmt->bpp;
|
||||
} else {
|
||||
uint32_t v_subsample, h_subsample;
|
||||
uint32_t chroma_samp;
|
||||
@ -201,7 +193,7 @@ static int _dpu_format_get_plane_sizes_linear(
|
||||
_dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
|
||||
&h_subsample);
|
||||
|
||||
if (width % h_subsample || height % v_subsample) {
|
||||
if (fb->width % h_subsample || fb->height % v_subsample) {
|
||||
DRM_ERROR("mismatch in subsample vs dimensions\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -209,11 +201,11 @@ static int _dpu_format_get_plane_sizes_linear(
|
||||
if ((fmt->pixel_format == DRM_FORMAT_NV12) &&
|
||||
(MSM_FORMAT_IS_DX(fmt)))
|
||||
bpp = 2;
|
||||
layout->plane_pitch[0] = width * bpp;
|
||||
layout->plane_pitch[0] = fb->width * bpp;
|
||||
layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
|
||||
layout->plane_size[0] = layout->plane_pitch[0] * height;
|
||||
layout->plane_size[0] = layout->plane_pitch[0] * fb->height;
|
||||
layout->plane_size[1] = layout->plane_pitch[1] *
|
||||
(height / v_subsample);
|
||||
(fb->height / v_subsample);
|
||||
|
||||
if (fmt->fetch_type == MDP_PLANE_PSEUDO_PLANAR) {
|
||||
layout->num_planes = 2;
|
||||
@ -234,8 +226,13 @@ static int _dpu_format_get_plane_sizes_linear(
|
||||
* all the components based on ubwc specifications.
|
||||
*/
|
||||
for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) {
|
||||
if (pitches && layout->plane_pitch[i] < pitches[i])
|
||||
layout->plane_pitch[i] = pitches[i];
|
||||
if (layout->plane_pitch[i] <= fb->pitches[i]) {
|
||||
layout->plane_pitch[i] = fb->pitches[i];
|
||||
} else {
|
||||
DRM_DEBUG("plane %u expected pitch %u, fb %u\n",
|
||||
i, layout->plane_pitch[i], fb->pitches[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < DPU_MAX_PLANES; i++)
|
||||
@ -244,53 +241,54 @@ static int _dpu_format_get_plane_sizes_linear(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dpu_format_get_plane_sizes(
|
||||
const struct msm_format *fmt,
|
||||
const uint32_t w,
|
||||
const uint32_t h,
|
||||
struct dpu_hw_fmt_layout *layout,
|
||||
const uint32_t *pitches)
|
||||
/*
|
||||
* dpu_format_populate_addrs - populate non-address part of the layout based on
|
||||
* fb, and format found in the fb
|
||||
* @fb: framebuffer pointer
|
||||
* @layout: format layout structure to populate
|
||||
*
|
||||
* Return: error code on failure or 0 if new addresses were populated
|
||||
*/
|
||||
int dpu_format_populate_plane_sizes(
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
{
|
||||
if (!layout || !fmt) {
|
||||
const struct msm_format *fmt;
|
||||
|
||||
if (!layout || !fb) {
|
||||
DRM_ERROR("invalid pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
|
||||
if (fb->width > DPU_MAX_IMG_WIDTH ||
|
||||
fb->height > DPU_MAX_IMG_HEIGHT) {
|
||||
DRM_ERROR("image dimensions outside max range\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (MSM_FORMAT_IS_UBWC(fmt) || MSM_FORMAT_IS_TILE(fmt))
|
||||
return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
|
||||
fmt = msm_framebuffer_format(fb);
|
||||
|
||||
return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
|
||||
if (MSM_FORMAT_IS_UBWC(fmt) || MSM_FORMAT_IS_TILE(fmt))
|
||||
return _dpu_format_populate_plane_sizes_ubwc(fmt, fb, layout);
|
||||
|
||||
return _dpu_format_populate_plane_sizes_linear(fmt, fb, layout);
|
||||
}
|
||||
|
||||
static int _dpu_format_populate_addrs_ubwc(
|
||||
struct msm_gem_address_space *aspace,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
static void _dpu_format_populate_addrs_ubwc(struct msm_gem_address_space *aspace,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
{
|
||||
const struct msm_format *fmt;
|
||||
uint32_t base_addr = 0;
|
||||
bool meta;
|
||||
|
||||
if (!fb || !layout) {
|
||||
DRM_ERROR("invalid pointers\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
base_addr = msm_framebuffer_iova(fb, aspace, 0);
|
||||
|
||||
if (aspace)
|
||||
base_addr = msm_framebuffer_iova(fb, aspace, 0);
|
||||
if (!base_addr) {
|
||||
DRM_ERROR("failed to retrieve base addr\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
meta = MSM_FORMAT_IS_UBWC(layout->format);
|
||||
fmt = msm_framebuffer_format(fb);
|
||||
meta = MSM_FORMAT_IS_UBWC(fmt);
|
||||
|
||||
/* Per-format logic for verifying active planes */
|
||||
if (MSM_FORMAT_IS_YUV(layout->format)) {
|
||||
if (MSM_FORMAT_IS_YUV(fmt)) {
|
||||
/************************************************/
|
||||
/* UBWC ** */
|
||||
/* buffer ** DPU PLANE */
|
||||
@ -319,7 +317,7 @@ static int _dpu_format_populate_addrs_ubwc(
|
||||
+ layout->plane_size[2] + layout->plane_size[3];
|
||||
|
||||
if (!meta)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* configure Y metadata plane */
|
||||
layout->plane_addr[2] = base_addr;
|
||||
@ -350,119 +348,36 @@ static int _dpu_format_populate_addrs_ubwc(
|
||||
layout->plane_addr[1] = 0;
|
||||
|
||||
if (!meta)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
layout->plane_addr[2] = base_addr;
|
||||
layout->plane_addr[3] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dpu_format_populate_addrs_linear(
|
||||
struct msm_gem_address_space *aspace,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
static void _dpu_format_populate_addrs_linear(struct msm_gem_address_space *aspace,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Can now check the pitches given vs pitches expected */
|
||||
for (i = 0; i < layout->num_planes; ++i) {
|
||||
if (layout->plane_pitch[i] > fb->pitches[i]) {
|
||||
DRM_ERROR("plane %u expected pitch %u, fb %u\n",
|
||||
i, layout->plane_pitch[i], fb->pitches[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Populate addresses for simple formats here */
|
||||
for (i = 0; i < layout->num_planes; ++i) {
|
||||
if (aspace)
|
||||
layout->plane_addr[i] =
|
||||
msm_framebuffer_iova(fb, aspace, i);
|
||||
if (!layout->plane_addr[i]) {
|
||||
DRM_ERROR("failed to retrieve base addr\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
for (i = 0; i < layout->num_planes; ++i)
|
||||
layout->plane_addr[i] = msm_framebuffer_iova(fb, aspace, i);
|
||||
}
|
||||
|
||||
int dpu_format_populate_layout(
|
||||
struct msm_gem_address_space *aspace,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
void dpu_format_populate_addrs(struct msm_gem_address_space *aspace,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout)
|
||||
{
|
||||
int ret;
|
||||
const struct msm_format *fmt;
|
||||
|
||||
if (!fb || !layout) {
|
||||
DRM_ERROR("invalid arguments\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((fb->width > DPU_MAX_IMG_WIDTH) ||
|
||||
(fb->height > DPU_MAX_IMG_HEIGHT)) {
|
||||
DRM_ERROR("image dimensions outside max range\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
layout->format = msm_framebuffer_format(fb);
|
||||
|
||||
/* Populate the plane sizes etc via get_format */
|
||||
ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
|
||||
layout, fb->pitches);
|
||||
if (ret)
|
||||
return ret;
|
||||
fmt = msm_framebuffer_format(fb);
|
||||
|
||||
/* Populate the addresses given the fb */
|
||||
if (MSM_FORMAT_IS_UBWC(layout->format) ||
|
||||
MSM_FORMAT_IS_TILE(layout->format))
|
||||
ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
|
||||
if (MSM_FORMAT_IS_UBWC(fmt) ||
|
||||
MSM_FORMAT_IS_TILE(fmt))
|
||||
_dpu_format_populate_addrs_ubwc(aspace, fb, layout);
|
||||
else
|
||||
ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dpu_format_check_modified_format(
|
||||
const struct msm_kms *kms,
|
||||
const struct msm_format *fmt,
|
||||
const struct drm_mode_fb_cmd2 *cmd,
|
||||
struct drm_gem_object **bos)
|
||||
{
|
||||
const struct drm_format_info *info;
|
||||
struct dpu_hw_fmt_layout layout;
|
||||
uint32_t bos_total_size = 0;
|
||||
int ret, i;
|
||||
|
||||
if (!fmt || !cmd || !bos) {
|
||||
DRM_ERROR("invalid arguments\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = drm_format_info(fmt->pixel_format);
|
||||
if (!info)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
|
||||
&layout, cmd->pitches);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < info->num_planes; i++) {
|
||||
if (!bos[i]) {
|
||||
DRM_ERROR("invalid handle for plane %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((i == 0) || (bos[i] != bos[0]))
|
||||
bos_total_size += bos[i]->size;
|
||||
}
|
||||
|
||||
if (bos_total_size < layout.total_size) {
|
||||
DRM_ERROR("buffers total size too small %u expected %u\n",
|
||||
bos_total_size, layout.total_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
_dpu_format_populate_addrs_linear(aspace, fb, layout);
|
||||
}
|
||||
|
@ -32,34 +32,18 @@ static inline bool dpu_find_format(u32 format, const u32 *supported_formats,
|
||||
}
|
||||
|
||||
/**
|
||||
* dpu_format_check_modified_format - validate format and buffers for
|
||||
* dpu non-standard, i.e. modified format
|
||||
* @kms: kms driver
|
||||
* @msm_fmt: pointer to the msm_fmt base pointer of an msm_format
|
||||
* @cmd: fb_cmd2 structure user request
|
||||
* @bos: gem buffer object list
|
||||
*
|
||||
* Return: error code on failure, 0 on success
|
||||
*/
|
||||
int dpu_format_check_modified_format(
|
||||
const struct msm_kms *kms,
|
||||
const struct msm_format *msm_fmt,
|
||||
const struct drm_mode_fb_cmd2 *cmd,
|
||||
struct drm_gem_object **bos);
|
||||
|
||||
/**
|
||||
* dpu_format_populate_layout - populate the given format layout based on
|
||||
* dpu_format_populate_addrs - populate buffer addresses based on
|
||||
* mmu, fb, and format found in the fb
|
||||
* @aspace: address space pointer
|
||||
* @fb: framebuffer pointer
|
||||
* @fmtl: format layout structure to populate
|
||||
*
|
||||
* Return: error code on failure, -EAGAIN if success but the addresses
|
||||
* are the same as before or 0 if new addresses were populated
|
||||
*/
|
||||
int dpu_format_populate_layout(
|
||||
struct msm_gem_address_space *aspace,
|
||||
void dpu_format_populate_addrs(struct msm_gem_address_space *aspace,
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *layout);
|
||||
|
||||
int dpu_format_populate_plane_sizes(
|
||||
struct drm_framebuffer *fb,
|
||||
struct dpu_hw_fmt_layout *fmtl);
|
||||
struct dpu_hw_fmt_layout *layout);
|
||||
|
||||
#endif /*_DPU_FORMATS_H */
|
||||
|
@ -21,6 +21,16 @@
|
||||
(VIG_BASE_MASK | \
|
||||
BIT(DPU_SSPP_CSC_10BIT))
|
||||
|
||||
#define VIG_MSM8953_MASK \
|
||||
(BIT(DPU_SSPP_QOS) |\
|
||||
BIT(DPU_SSPP_SCALER_QSEED2) |\
|
||||
BIT(DPU_SSPP_CSC))
|
||||
|
||||
#define VIG_MSM8996_MASK \
|
||||
(BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_CDP) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_SCALER_QSEED2) |\
|
||||
BIT(DPU_SSPP_CSC))
|
||||
|
||||
#define VIG_MSM8998_MASK \
|
||||
(VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE))
|
||||
|
||||
@ -32,6 +42,12 @@
|
||||
|
||||
#define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL))
|
||||
|
||||
#define DMA_MSM8953_MASK \
|
||||
(BIT(DPU_SSPP_QOS))
|
||||
|
||||
#define DMA_MSM8996_MASK \
|
||||
(BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_CDP))
|
||||
|
||||
#define DMA_MSM8998_MASK \
|
||||
(BIT(DPU_SSPP_QOS) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
|
||||
@ -57,9 +73,19 @@
|
||||
#define DMA_CURSOR_SDM845_MASK_SDMA \
|
||||
(DMA_CURSOR_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
|
||||
|
||||
#define DMA_CURSOR_MSM8996_MASK \
|
||||
(DMA_MSM8996_MASK | BIT(DPU_SSPP_CURSOR))
|
||||
|
||||
#define DMA_CURSOR_MSM8998_MASK \
|
||||
(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
|
||||
|
||||
#define RGB_MSM8953_MASK \
|
||||
(BIT(DPU_SSPP_QOS))
|
||||
|
||||
#define RGB_MSM8996_MASK \
|
||||
(BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_CDP) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_SCALER_RGB))
|
||||
|
||||
#define MIXER_MSM8998_MASK \
|
||||
(BIT(DPU_MIXER_SOURCESPLIT))
|
||||
|
||||
@ -69,6 +95,12 @@
|
||||
#define MIXER_QCM2290_MASK \
|
||||
(BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA))
|
||||
|
||||
#define PINGPONG_MSM8996_MASK \
|
||||
(BIT(DPU_PINGPONG_DSC))
|
||||
|
||||
#define PINGPONG_MSM8996_TE2_MASK \
|
||||
(PINGPONG_MSM8996_MASK | BIT(DPU_PINGPONG_TE2))
|
||||
|
||||
#define PINGPONG_SDM845_MASK \
|
||||
(BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC))
|
||||
|
||||
@ -316,6 +348,35 @@ static const u32 wb2_formats_rgb_yuv[] = {
|
||||
.virt_num_formats = ARRAY_SIZE(plane_formats), \
|
||||
}
|
||||
|
||||
/* qseed2 is not supported, so disabled scaling */
|
||||
#define _VIG_SBLK_QSEED2() \
|
||||
{ \
|
||||
.maxdwnscale = SSPP_UNITY_SCALE, \
|
||||
.maxupscale = SSPP_UNITY_SCALE, \
|
||||
.scaler_blk = {.name = "scaler", \
|
||||
/* no version for qseed2 */ \
|
||||
.base = 0x200, .len = 0xa0,}, \
|
||||
.csc_blk = {.name = "csc", \
|
||||
.base = 0x320, .len = 0x100,}, \
|
||||
.format_list = plane_formats_yuv, \
|
||||
.num_formats = ARRAY_SIZE(plane_formats_yuv), \
|
||||
.virt_format_list = plane_formats, \
|
||||
.virt_num_formats = ARRAY_SIZE(plane_formats), \
|
||||
.rotation_cfg = NULL, \
|
||||
}
|
||||
|
||||
#define _RGB_SBLK() \
|
||||
{ \
|
||||
.maxdwnscale = SSPP_UNITY_SCALE, \
|
||||
.maxupscale = SSPP_UNITY_SCALE, \
|
||||
.scaler_blk = {.name = "scaler", \
|
||||
.base = 0x200, .len = 0x28,}, \
|
||||
.format_list = plane_formats, \
|
||||
.num_formats = ARRAY_SIZE(plane_formats), \
|
||||
.virt_format_list = plane_formats, \
|
||||
.virt_num_formats = ARRAY_SIZE(plane_formats), \
|
||||
}
|
||||
|
||||
#define _DMA_SBLK() \
|
||||
{ \
|
||||
.maxdwnscale = SSPP_UNITY_SCALE, \
|
||||
@ -332,6 +393,9 @@ static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = {
|
||||
.rot_format_list = rotation_v2_formats,
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed2 =
|
||||
_VIG_SBLK_QSEED2();
|
||||
|
||||
static const struct dpu_sspp_sub_blks dpu_vig_sblk_noscale =
|
||||
_VIG_SBLK_NOSCALE();
|
||||
|
||||
@ -363,6 +427,8 @@ static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_2 =
|
||||
static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_3 =
|
||||
_VIG_SBLK(SSPP_SCALER_VER(3, 3));
|
||||
|
||||
static const struct dpu_sspp_sub_blks dpu_rgb_sblk = _RGB_SBLK();
|
||||
|
||||
static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK();
|
||||
|
||||
/*************************************************************
|
||||
@ -427,6 +493,15 @@ static const struct dpu_dspp_sub_blks sdm845_dspp_sblk = {
|
||||
/*************************************************************
|
||||
* PINGPONG sub blocks config
|
||||
*************************************************************/
|
||||
static const struct dpu_pingpong_sub_blks msm8996_pp_sblk_te = {
|
||||
.te2 = {.name = "te2", .base = 0x2000, .len = 0x0,
|
||||
.version = 0x1},
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_sub_blks msm8996_pp_sblk = {
|
||||
/* No dither block */
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = {
|
||||
.te2 = {.name = "te2", .base = 0x2000, .len = 0x0,
|
||||
.version = 0x1},
|
||||
@ -492,6 +567,34 @@ static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg msm8996_vbif[] = {
|
||||
{
|
||||
.name = "vbif_rt", .id = VBIF_RT,
|
||||
.base = 0, .len = 0x1040,
|
||||
.default_ot_rd_limit = 32,
|
||||
.default_ot_wr_limit = 16,
|
||||
.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,
|
||||
},
|
||||
.dynamic_ot_wr_tbl = {
|
||||
.count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
|
||||
.cfg = msm8998_ot_rdwr_cfg,
|
||||
},
|
||||
.qos_rt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl),
|
||||
.priority_lvl = msm8998_rt_pri_lvl,
|
||||
},
|
||||
.qos_nrt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl),
|
||||
.priority_lvl = msm8998_nrt_pri_lvl,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg msm8998_vbif[] = {
|
||||
{
|
||||
.name = "vbif_rt", .id = VBIF_RT,
|
||||
@ -675,6 +778,11 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
|
||||
* Hardware catalog
|
||||
*************************************************************/
|
||||
|
||||
#include "catalog/dpu_1_7_msm8996.h"
|
||||
#include "catalog/dpu_1_14_msm8937.h"
|
||||
#include "catalog/dpu_1_15_msm8917.h"
|
||||
#include "catalog/dpu_1_16_msm8953.h"
|
||||
|
||||
#include "catalog/dpu_3_0_msm8998.h"
|
||||
#include "catalog/dpu_3_2_sdm660.h"
|
||||
#include "catalog/dpu_3_3_sdm630.h"
|
||||
@ -699,6 +807,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
|
||||
|
||||
#include "catalog/dpu_8_0_sc8280xp.h"
|
||||
#include "catalog/dpu_8_1_sm8450.h"
|
||||
#include "catalog/dpu_8_4_sa8775p.h"
|
||||
|
||||
#include "catalog/dpu_9_0_sm8550.h"
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
#define DPU_HW_BLK_NAME_LEN 16
|
||||
|
||||
#define MAX_IMG_WIDTH 0x3fff
|
||||
#define MAX_IMG_HEIGHT 0x3fff
|
||||
#define DPU_MAX_IMG_WIDTH 0x3fff
|
||||
#define DPU_MAX_IMG_HEIGHT 0x3fff
|
||||
|
||||
#define CRTC_DUAL_MIXERS 2
|
||||
|
||||
@ -831,6 +831,10 @@ struct dpu_mdss_cfg {
|
||||
const struct dpu_format_extended *vig_formats;
|
||||
};
|
||||
|
||||
extern const struct dpu_mdss_cfg dpu_msm8917_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_msm8937_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_msm8953_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_msm8996_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_msm8998_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sdm630_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sdm660_cfg;
|
||||
@ -850,6 +854,7 @@ extern const struct dpu_mdss_cfg dpu_sm8350_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sc7280_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sc8280xp_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sm8450_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sa8775p_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sm8550_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_sm8650_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_x1e80100_cfg;
|
||||
|
@ -293,7 +293,6 @@ enum dpu_3d_blend_mode {
|
||||
|
||||
/**
|
||||
* struct dpu_hw_fmt_layout - format information of the source pixel data
|
||||
* @format: pixel format parameters
|
||||
* @num_planes: number of planes (including meta data planes)
|
||||
* @width: image width
|
||||
* @height: image height
|
||||
@ -303,7 +302,6 @@ enum dpu_3d_blend_mode {
|
||||
* @plane_pitch: pitch of each plane
|
||||
*/
|
||||
struct dpu_hw_fmt_layout {
|
||||
const struct msm_format *format;
|
||||
uint32_t num_planes;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
struct dpu_hw_sspp;
|
||||
|
||||
#define DPU_SSPP_MAX_PITCH_SIZE 0xffff
|
||||
|
||||
/**
|
||||
* Flags
|
||||
*/
|
||||
|
@ -64,10 +64,10 @@ static void dpu_hw_wb_setup_outaddress(struct dpu_hw_wb *ctx,
|
||||
}
|
||||
|
||||
static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
|
||||
struct dpu_hw_wb_cfg *data)
|
||||
struct dpu_hw_wb_cfg *data,
|
||||
const struct msm_format *fmt)
|
||||
{
|
||||
struct dpu_hw_blk_reg_map *c = &ctx->hw;
|
||||
const struct msm_format *fmt = data->dest.format;
|
||||
u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp;
|
||||
u32 write_config = 0;
|
||||
u32 opmode = 0;
|
||||
|
@ -37,7 +37,8 @@ struct dpu_hw_wb_ops {
|
||||
struct dpu_hw_wb_cfg *wb);
|
||||
|
||||
void (*setup_outformat)(struct dpu_hw_wb *ctx,
|
||||
struct dpu_hw_wb_cfg *wb);
|
||||
struct dpu_hw_wb_cfg *wb,
|
||||
const struct msm_format *fmt);
|
||||
|
||||
void (*setup_roi)(struct dpu_hw_wb *ctx,
|
||||
struct dpu_hw_wb_cfg *wb);
|
||||
|
@ -1025,7 +1025,6 @@ static const struct msm_kms_funcs kms_funcs = {
|
||||
.complete_commit = dpu_kms_complete_commit,
|
||||
.enable_vblank = dpu_kms_enable_vblank,
|
||||
.disable_vblank = dpu_kms_disable_vblank,
|
||||
.check_modified_format = dpu_format_check_modified_format,
|
||||
.destroy = dpu_kms_destroy,
|
||||
.snapshot = dpu_kms_mdp_snapshot,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
@ -1202,13 +1201,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
|
||||
dev->mode_config.min_width = 0;
|
||||
dev->mode_config.min_height = 0;
|
||||
|
||||
/*
|
||||
* max crtc width is equal to the max mixer width * 2 and max height is
|
||||
* is 4K
|
||||
*/
|
||||
dev->mode_config.max_width =
|
||||
dpu_kms->catalog->caps->max_mixer_width * 2;
|
||||
dev->mode_config.max_height = 4096;
|
||||
dev->mode_config.max_width = DPU_MAX_IMG_WIDTH;
|
||||
dev->mode_config.max_height = DPU_MAX_IMG_HEIGHT;
|
||||
|
||||
dev->max_vblank_count = 0xffffffff;
|
||||
/* Disable vblank irqs aggressively for power-saving */
|
||||
@ -1445,8 +1439,13 @@ static const struct dev_pm_ops dpu_pm_ops = {
|
||||
};
|
||||
|
||||
static const struct of_device_id dpu_dt_match[] = {
|
||||
{ .compatible = "qcom,msm8917-mdp5", .data = &dpu_msm8917_cfg, },
|
||||
{ .compatible = "qcom,msm8937-mdp5", .data = &dpu_msm8937_cfg, },
|
||||
{ .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, },
|
||||
{ .compatible = "qcom,msm8996-mdp5", .data = &dpu_msm8996_cfg, },
|
||||
{ .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, },
|
||||
{ .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, },
|
||||
{ .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, },
|
||||
{ .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, },
|
||||
{ .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, },
|
||||
{ .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, },
|
||||
|
@ -648,7 +648,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_framebuffer *fb = new_state->fb;
|
||||
struct dpu_plane *pdpu = to_dpu_plane(plane);
|
||||
struct dpu_plane_state *pstate = to_dpu_plane_state(new_state);
|
||||
struct dpu_hw_fmt_layout layout;
|
||||
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
|
||||
int ret;
|
||||
|
||||
@ -676,17 +675,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
|
||||
}
|
||||
}
|
||||
|
||||
/* validate framebuffer layout before commit */
|
||||
ret = dpu_format_populate_layout(pstate->aspace,
|
||||
new_state->fb, &layout);
|
||||
if (ret) {
|
||||
DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
|
||||
if (pstate->aspace)
|
||||
msm_framebuffer_cleanup(new_state->fb, pstate->aspace,
|
||||
pstate->needs_dirtyfb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -794,7 +782,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
int ret = 0, min_scale;
|
||||
int i, ret = 0, min_scale;
|
||||
struct dpu_plane *pdpu = to_dpu_plane(plane);
|
||||
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
|
||||
u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
|
||||
@ -855,13 +843,23 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
|
||||
fb_rect.y2 = new_plane_state->fb->height;
|
||||
|
||||
/* Ensure fb size is supported */
|
||||
if (drm_rect_width(&fb_rect) > MAX_IMG_WIDTH ||
|
||||
drm_rect_height(&fb_rect) > MAX_IMG_HEIGHT) {
|
||||
if (drm_rect_width(&fb_rect) > DPU_MAX_IMG_WIDTH ||
|
||||
drm_rect_height(&fb_rect) > DPU_MAX_IMG_HEIGHT) {
|
||||
DPU_DEBUG_PLANE(pdpu, "invalid framebuffer " DRM_RECT_FMT "\n",
|
||||
DRM_RECT_ARG(&fb_rect));
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
ret = dpu_format_populate_plane_sizes(new_plane_state->fb, &pstate->layout);
|
||||
if (ret) {
|
||||
DPU_ERROR_PLANE(pdpu, "failed to get format plane sizes, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < pstate->layout.num_planes; i++)
|
||||
if (pstate->layout.plane_pitch[i] > DPU_SSPP_MAX_PITCH_SIZE)
|
||||
return -E2BIG;
|
||||
|
||||
fmt = msm_framebuffer_format(new_plane_state->fb);
|
||||
|
||||
max_linewidth = pdpu->catalog->caps->max_linewidth;
|
||||
@ -1101,7 +1099,8 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane *plane,
|
||||
_dpu_plane_set_qos_remap(plane, pipe);
|
||||
}
|
||||
|
||||
static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
|
||||
static void dpu_plane_sspp_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct dpu_plane *pdpu = to_dpu_plane(plane);
|
||||
struct drm_plane_state *state = plane->state;
|
||||
@ -1115,17 +1114,6 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
|
||||
msm_framebuffer_format(fb);
|
||||
struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
|
||||
struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
|
||||
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
|
||||
struct msm_gem_address_space *aspace = kms->base.aspace;
|
||||
struct dpu_hw_fmt_layout layout;
|
||||
bool layout_valid = false;
|
||||
int ret;
|
||||
|
||||
ret = dpu_format_populate_layout(aspace, fb, &layout);
|
||||
if (ret)
|
||||
DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
|
||||
else
|
||||
layout_valid = true;
|
||||
|
||||
pstate->pending = true;
|
||||
|
||||
@ -1133,6 +1121,8 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
|
||||
pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe);
|
||||
pdpu->is_rt_pipe = is_rt_pipe;
|
||||
|
||||
dpu_format_populate_addrs(pstate->aspace, new_state->fb, &pstate->layout);
|
||||
|
||||
DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT
|
||||
", %p4cc ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src),
|
||||
crtc->base.id, DRM_RECT_ARG(&state->dst),
|
||||
@ -1140,12 +1130,12 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
|
||||
|
||||
dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt,
|
||||
drm_mode_vrefresh(&crtc->mode),
|
||||
layout_valid ? &layout : NULL);
|
||||
&pstate->layout);
|
||||
|
||||
if (r_pipe->sspp) {
|
||||
dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt,
|
||||
drm_mode_vrefresh(&crtc->mode),
|
||||
layout_valid ? &layout : NULL);
|
||||
&pstate->layout);
|
||||
}
|
||||
|
||||
if (pstate->needs_qos_remap)
|
||||
@ -1197,7 +1187,7 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
|
||||
if (!new_state->visible) {
|
||||
_dpu_plane_atomic_disable(plane);
|
||||
} else {
|
||||
dpu_plane_sspp_atomic_update(plane);
|
||||
dpu_plane_sspp_atomic_update(plane, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
* @plane_clk: calculated clk per plane
|
||||
* @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed
|
||||
* @rotation: simplified drm rotation hint
|
||||
* @layout: framebuffer memory layout
|
||||
*/
|
||||
struct dpu_plane_state {
|
||||
struct drm_plane_state base;
|
||||
@ -48,6 +49,8 @@ struct dpu_plane_state {
|
||||
|
||||
bool needs_dirtyfb;
|
||||
unsigned int rotation;
|
||||
|
||||
struct dpu_hw_fmt_layout layout;
|
||||
};
|
||||
|
||||
#define to_dpu_plane_state(x) \
|
||||
|
@ -25,24 +25,21 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
|
||||
addr = base_addr;
|
||||
end_addr = base_addr + aligned_len;
|
||||
|
||||
if (!(*reg))
|
||||
*reg = kvzalloc(len_padded, GFP_KERNEL);
|
||||
|
||||
if (*reg)
|
||||
dump_addr = *reg;
|
||||
*reg = kvzalloc(len_padded, GFP_KERNEL);
|
||||
if (!*reg)
|
||||
return;
|
||||
|
||||
dump_addr = *reg;
|
||||
for (i = 0; i < num_rows; i++) {
|
||||
x0 = (addr < end_addr) ? readl_relaxed(addr + 0x0) : 0;
|
||||
x4 = (addr + 0x4 < end_addr) ? readl_relaxed(addr + 0x4) : 0;
|
||||
x8 = (addr + 0x8 < end_addr) ? readl_relaxed(addr + 0x8) : 0;
|
||||
xc = (addr + 0xc < end_addr) ? readl_relaxed(addr + 0xc) : 0;
|
||||
|
||||
if (dump_addr) {
|
||||
dump_addr[i * 4] = x0;
|
||||
dump_addr[i * 4 + 1] = x4;
|
||||
dump_addr[i * 4 + 2] = x8;
|
||||
dump_addr[i * 4 + 3] = xc;
|
||||
}
|
||||
dump_addr[i * 4] = x0;
|
||||
dump_addr[i * 4 + 1] = x4;
|
||||
dump_addr[i * 4 + 2] = x8;
|
||||
dump_addr[i * 4 + 3] = xc;
|
||||
|
||||
addr += REG_DUMP_ALIGN;
|
||||
}
|
||||
|
@ -118,6 +118,14 @@ struct msm_dp_desc {
|
||||
bool wide_bus_supported;
|
||||
};
|
||||
|
||||
static const struct msm_dp_desc sa8775p_dp_descs[] = {
|
||||
{ .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
|
||||
{ .io_start = 0x0af5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true },
|
||||
{ .io_start = 0x22154000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true },
|
||||
{ .io_start = 0x2215c000, .id = MSM_DP_CONTROLLER_3, .wide_bus_supported = true },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct msm_dp_desc sc7180_dp_descs[] = {
|
||||
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
|
||||
{}
|
||||
@ -162,6 +170,7 @@ static const struct msm_dp_desc x1e80100_dp_descs[] = {
|
||||
};
|
||||
|
||||
static const struct of_device_id dp_dt_match[] = {
|
||||
{ .compatible = "qcom,sa8775p-dp", .data = &sa8775p_dp_descs },
|
||||
{ .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_descs },
|
||||
{ .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_descs },
|
||||
{ .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_descs },
|
||||
|
@ -157,9 +157,8 @@ static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
|
||||
#define HDMI_MHZ_TO_HZ ((u64)1000000)
|
||||
static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk)
|
||||
{
|
||||
u32 const ratio_list[] = {1, 2, 3, 4, 5, 6,
|
||||
9, 10, 12, 15, 25};
|
||||
u32 const band_list[] = {0, 1, 2, 3};
|
||||
static const u32 ratio_list[] = {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25};
|
||||
static const u32 band_list[] = {0, 1, 2, 3};
|
||||
u32 const sz_ratio = ARRAY_SIZE(ratio_list);
|
||||
u32 const sz_band = ARRAY_SIZE(band_list);
|
||||
u32 const cmp_cnt = 1024;
|
||||
@ -270,7 +269,7 @@ static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk)
|
||||
case 25:
|
||||
found_hsclk_divsel = 14;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
pd->vco_freq = found_vco_freq;
|
||||
pd->tx_band_sel = found_tx_band_sel;
|
||||
|
@ -985,6 +985,10 @@ module_param(prefer_mdp5, bool, 0444);
|
||||
|
||||
/* list all platforms supported by both mdp5 and dpu drivers */
|
||||
static const char *const msm_mdp5_dpu_migration[] = {
|
||||
"qcom,msm8917-mdp5",
|
||||
"qcom,msm8937-mdp5",
|
||||
"qcom,msm8953-mdp5",
|
||||
"qcom,msm8996-mdp5",
|
||||
"qcom,sdm630-mdp5",
|
||||
"qcom,sdm660-mdp5",
|
||||
NULL,
|
||||
|
@ -783,7 +783,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
mutex_unlock(&gpu->active_lock);
|
||||
|
||||
gpu->funcs->submit(gpu, submit);
|
||||
gpu->cur_ctx_seqno = submit->queue->ctx->seqno;
|
||||
submit->ring->cur_ctx_seqno = submit->queue->ctx->seqno;
|
||||
|
||||
pm_runtime_put(&gpu->pdev->dev);
|
||||
hangcheck_timer_reset(gpu);
|
||||
|
@ -193,17 +193,6 @@ struct msm_gpu {
|
||||
*/
|
||||
refcount_t sysprof_active;
|
||||
|
||||
/**
|
||||
* cur_ctx_seqno:
|
||||
*
|
||||
* The ctx->seqno value of the last context to submit rendering,
|
||||
* and the one with current pgtables installed (for generations
|
||||
* that support per-context pgtables). Tracked by seqno rather
|
||||
* than pointer value to avoid dangling pointers, and cases where
|
||||
* a ctx can be freed and a new one created with the same address.
|
||||
*/
|
||||
int cur_ctx_seqno;
|
||||
|
||||
/**
|
||||
* lock:
|
||||
*
|
||||
|
@ -140,6 +140,7 @@ void msm_devfreq_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
struct msm_drm_private *priv = gpu->dev->dev_private;
|
||||
int ret;
|
||||
|
||||
/* We need target support to do devfreq */
|
||||
if (!gpu->funcs->gpu_busy)
|
||||
@ -156,8 +157,12 @@ void msm_devfreq_init(struct msm_gpu *gpu)
|
||||
|
||||
mutex_init(&df->lock);
|
||||
|
||||
dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq,
|
||||
DEV_PM_QOS_MIN_FREQUENCY, 0);
|
||||
ret = dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq,
|
||||
DEV_PM_QOS_MIN_FREQUENCY, 0);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize QoS\n");
|
||||
return;
|
||||
}
|
||||
|
||||
msm_devfreq_profile.initial_freq = gpu->fast_rate;
|
||||
|
||||
|
@ -177,6 +177,34 @@ TRACE_EVENT(msm_gpu_resume,
|
||||
TP_printk("%u", __entry->dummy)
|
||||
);
|
||||
|
||||
TRACE_EVENT(msm_gpu_preemption_trigger,
|
||||
TP_PROTO(int ring_id_from, int ring_id_to),
|
||||
TP_ARGS(ring_id_from, ring_id_to),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, ring_id_from)
|
||||
__field(int, ring_id_to)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->ring_id_from = ring_id_from;
|
||||
__entry->ring_id_to = ring_id_to;
|
||||
),
|
||||
TP_printk("preempting %u -> %u",
|
||||
__entry->ring_id_from,
|
||||
__entry->ring_id_to)
|
||||
);
|
||||
|
||||
TRACE_EVENT(msm_gpu_preemption_irq,
|
||||
TP_PROTO(u32 ring_id),
|
||||
TP_ARGS(ring_id),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, ring_id)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->ring_id = ring_id;
|
||||
),
|
||||
TP_printk("preempted to %u", __entry->ring_id)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -92,12 +92,6 @@ struct msm_kms_funcs {
|
||||
* Format handling:
|
||||
*/
|
||||
|
||||
/* do format checking on format modified through fb_cmd2 modifiers */
|
||||
int (*check_modified_format)(const struct msm_kms *kms,
|
||||
const struct msm_format *msm_fmt,
|
||||
const struct drm_mode_fb_cmd2 *cmd,
|
||||
struct drm_gem_object **bos);
|
||||
|
||||
/* misc: */
|
||||
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
|
||||
struct drm_encoder *encoder);
|
||||
|
@ -573,6 +573,16 @@ static const struct msm_mdss_data qcm2290_data = {
|
||||
.reg_bus_bw = 76800,
|
||||
};
|
||||
|
||||
static const struct msm_mdss_data sa8775p_data = {
|
||||
.ubwc_enc_version = UBWC_4_0,
|
||||
.ubwc_dec_version = UBWC_4_0,
|
||||
.ubwc_swizzle = 4,
|
||||
.ubwc_static = 1,
|
||||
.highest_bank_bit = 0,
|
||||
.macrotile_mode = 1,
|
||||
.reg_bus_bw = 74000,
|
||||
};
|
||||
|
||||
static const struct msm_mdss_data sc7180_data = {
|
||||
.ubwc_enc_version = UBWC_2_0,
|
||||
.ubwc_dec_version = UBWC_2_0,
|
||||
@ -710,6 +720,7 @@ static const struct of_device_id mdss_dt_match[] = {
|
||||
{ .compatible = "qcom,mdss" },
|
||||
{ .compatible = "qcom,msm8998-mdss", .data = &msm8998_data },
|
||||
{ .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data },
|
||||
{ .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data },
|
||||
{ .compatible = "qcom,sdm670-mdss", .data = &sdm670_data },
|
||||
{ .compatible = "qcom,sdm845-mdss", .data = &sdm845_data },
|
||||
{ .compatible = "qcom,sc7180-mdss", .data = &sc7180_data },
|
||||
|
@ -64,7 +64,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
|
||||
char name[32];
|
||||
int ret;
|
||||
|
||||
/* We assume everwhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */
|
||||
/* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */
|
||||
BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ));
|
||||
|
||||
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
||||
|
@ -31,10 +31,12 @@ struct msm_rbmemptrs {
|
||||
volatile uint32_t rptr;
|
||||
volatile uint32_t fence;
|
||||
/* Introduced on A7xx */
|
||||
volatile uint32_t bv_rptr;
|
||||
volatile uint32_t bv_fence;
|
||||
|
||||
volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT];
|
||||
volatile u64 ttbr0;
|
||||
volatile u32 context_idr;
|
||||
};
|
||||
|
||||
struct msm_cp_state {
|
||||
@ -99,6 +101,22 @@ struct msm_ringbuffer {
|
||||
* preemption. Can be aquired from irq context.
|
||||
*/
|
||||
spinlock_t preempt_lock;
|
||||
|
||||
/*
|
||||
* Whether we skipped writing wptr and it needs to be updated in the
|
||||
* future when the ring becomes current.
|
||||
*/
|
||||
bool restore_wptr;
|
||||
|
||||
/**
|
||||
* cur_ctx_seqno:
|
||||
*
|
||||
* The ctx->seqno value of the last context to submit to this ring
|
||||
* Tracked by seqno rather than pointer value to avoid dangling
|
||||
* pointers, and cases where a ctx can be freed and a new one created
|
||||
* with the same address.
|
||||
*/
|
||||
int cur_ctx_seqno;
|
||||
};
|
||||
|
||||
struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
|
||||
|
@ -161,6 +161,8 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
|
||||
struct msm_drm_private *priv = drm->dev_private;
|
||||
struct msm_gpu_submitqueue *queue;
|
||||
enum drm_sched_priority sched_prio;
|
||||
extern int enable_preemption;
|
||||
bool preemption_supported;
|
||||
unsigned ring_nr;
|
||||
int ret;
|
||||
|
||||
@ -170,6 +172,11 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
|
||||
if (!priv->gpu)
|
||||
return -ENODEV;
|
||||
|
||||
preemption_supported = priv->gpu->nr_rings == 1 && enable_preemption != 0;
|
||||
|
||||
if (flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT && preemption_supported)
|
||||
return -EINVAL;
|
||||
|
||||
ret = msm_gpu_convert_priority(priv->gpu, prio, &ring_nr, &sched_prio);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -2358,7 +2358,12 @@ to upconvert to 32b float internally?
|
||||
<reg32 offset="0x0" name="REG" type="a6x_cp_protect"/>
|
||||
</array>
|
||||
|
||||
<reg32 offset="0x08A0" name="CP_CONTEXT_SWITCH_CNTL"/>
|
||||
<reg32 offset="0x08A0" name="CP_CONTEXT_SWITCH_CNTL">
|
||||
<bitfield name="STOP" pos="0" type="boolean"/>
|
||||
<bitfield name="LEVEL" low="6" high="7"/>
|
||||
<bitfield name="USES_GMEM" pos="8" type="boolean"/>
|
||||
<bitfield name="SKIP_SAVE_RESTORE" pos="9" type="boolean"/>
|
||||
</reg32>
|
||||
<reg64 offset="0x08A1" name="CP_CONTEXT_SWITCH_SMMU_INFO"/>
|
||||
<reg64 offset="0x08A3" name="CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR"/>
|
||||
<reg64 offset="0x08A5" name="CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR"/>
|
||||
|
@ -581,8 +581,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
||||
and forcibly switch to the indicated context.
|
||||
</doc>
|
||||
<value name="CP_CONTEXT_SWITCH" value="0x54" variants="A6XX"/>
|
||||
<!-- Note, kgsl calls this CP_SET_AMBLE: -->
|
||||
<value name="CP_SET_CTXSWITCH_IB" value="0x55" variants="A6XX-"/>
|
||||
<value name="CP_SET_AMBLE" value="0x55" variants="A6XX-"/>
|
||||
|
||||
<!--
|
||||
Seems to always have the payload:
|
||||
@ -2013,42 +2012,38 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
||||
</reg32>
|
||||
</domain>
|
||||
|
||||
<domain name="CP_SET_CTXSWITCH_IB" width="32">
|
||||
<domain name="CP_SET_AMBLE" width="32">
|
||||
<doc>
|
||||
Used by the userspace driver to set various IB's which are
|
||||
executed during context save/restore for handling
|
||||
state that isn't restored by the
|
||||
context switch routine itself.
|
||||
</doc>
|
||||
<enum name="ctxswitch_ib">
|
||||
<value name="RESTORE_IB" value="0">
|
||||
Used by the userspace and kernel drivers to set various IB's
|
||||
which are executed during context save/restore for handling
|
||||
state that isn't restored by the context switch routine itself.
|
||||
</doc>
|
||||
<enum name="amble_type">
|
||||
<value name="PREAMBLE_AMBLE_TYPE" value="0">
|
||||
<doc>Executed unconditionally when switching back to the context.</doc>
|
||||
</value>
|
||||
<value name="YIELD_RESTORE_IB" value="1">
|
||||
<value name="BIN_PREAMBLE_AMBLE_TYPE" value="1">
|
||||
<doc>
|
||||
Executed when switching back after switching
|
||||
away during execution of
|
||||
a CP_SET_MARKER packet with RM6_YIELD as the
|
||||
payload *and* the normal save routine was
|
||||
bypassed for a shorter one. I think this is
|
||||
connected to the "skipsaverestore" bit set by
|
||||
the kernel when preempting.
|
||||
a CP_SET_MARKER packet with RM6_BIN_RENDER_END as the
|
||||
payload *and* skipsaverestore is set. This is
|
||||
expected to restore static register values not
|
||||
saved when skipsaverestore is set.
|
||||
</doc>
|
||||
</value>
|
||||
<value name="SAVE_IB" value="2">
|
||||
<value name="POSTAMBLE_AMBLE_TYPE" value="2">
|
||||
<doc>
|
||||
Executed when switching away from the context,
|
||||
except for context switches initiated via
|
||||
CP_YIELD.
|
||||
</doc>
|
||||
</value>
|
||||
<value name="RB_SAVE_IB" value="3">
|
||||
<value name="KMD_AMBLE_TYPE" value="3">
|
||||
<doc>
|
||||
This can only be set by the RB (i.e. the kernel)
|
||||
and executes with protected mode off, but
|
||||
is otherwise similar to SAVE_IB.
|
||||
|
||||
Note, kgsl calls this CP_KMD_AMBLE_TYPE
|
||||
is otherwise similar to POSTAMBLE_AMBLE_TYPE.
|
||||
</doc>
|
||||
</value>
|
||||
</enum>
|
||||
@ -2060,7 +2055,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="DWORDS" low="0" high="19" type="uint"/>
|
||||
<bitfield name="TYPE" low="20" high="21" type="ctxswitch_ib"/>
|
||||
<bitfield name="TYPE" low="20" high="21" type="amble_type"/>
|
||||
</reg32>
|
||||
</domain>
|
||||
|
||||
|
@ -347,7 +347,10 @@ struct drm_msm_gem_madvise {
|
||||
* backwards compatibility as a "default" submitqueue
|
||||
*/
|
||||
|
||||
#define MSM_SUBMITQUEUE_FLAGS (0)
|
||||
#define MSM_SUBMITQUEUE_ALLOW_PREEMPT 0x00000001
|
||||
#define MSM_SUBMITQUEUE_FLAGS ( \
|
||||
MSM_SUBMITQUEUE_ALLOW_PREEMPT | \
|
||||
0)
|
||||
|
||||
/*
|
||||
* The submitqueue priority should be between 0 and MSM_PARAM_PRIORITIES-1,
|
||||
|
Loading…
Reference in New Issue
Block a user