mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
Merge tag 'drm-msm-next-2026-05-30' of https://gitlab.freedesktop.org/drm/msm into drm-next
Changes for v7.2 Core: - Fixed documentation for msm_gem_shrinker functions - IFPC related enablement/fixes for gen8 - PERFCNTR_CONFIG ioctl support GPU - Reworked handling of UBWC configuration - a810 suppport MDSS: - Added Milos platform support - Reworked handling of UBWC configuration DisplayPort: - Reworked HPD handling, preparing for the MST support DPU: - Added Milos platform support - Reworked handling of UBWC configuration DSI: - Added Milos platform support Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rob Clark <rob.clark@oss.qualcomm.com> Link: https://patch.msgid.link/CACSVV00DXZcvFH2-C3fouve5DGs0DGa-vvsJPuaRmUZZVNKOfg@mail.gmail.com
This commit is contained in:
commit
44c460d2cc
|
|
@ -16,6 +16,7 @@ properties:
|
|||
- enum:
|
||||
- qcom,apq8064-dsi-ctrl
|
||||
- qcom,kaanapali-dsi-ctrl
|
||||
- qcom,milos-dsi-ctrl
|
||||
- qcom,msm8226-dsi-ctrl
|
||||
- qcom,msm8916-dsi-ctrl
|
||||
- qcom,msm8953-dsi-ctrl
|
||||
|
|
@ -339,6 +340,7 @@ allOf:
|
|||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,milos-dsi-ctrl
|
||||
- qcom,msm8998-dsi-ctrl
|
||||
- qcom,sa8775p-dsi-ctrl
|
||||
- qcom,sar2130p-dsi-ctrl
|
||||
|
|
|
|||
|
|
@ -300,6 +300,36 @@ allOf:
|
|||
required:
|
||||
- qcom,qmp
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,adreno-gmu-810.0
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Core GMU registers
|
||||
reg-names:
|
||||
items:
|
||||
- const: gmu
|
||||
clocks:
|
||||
items:
|
||||
- description: GPU AHB clock
|
||||
- description: GMU clock
|
||||
- description: GPU CX clock
|
||||
- description: GPU AXI clock
|
||||
- description: GPU MEMNOC clock
|
||||
- description: GMU HUB clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: ahb
|
||||
- const: gmu
|
||||
- const: cxo
|
||||
- const: axi
|
||||
- const: memnoc
|
||||
- const: hub
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
|
|
@ -411,6 +411,23 @@ allOf:
|
|||
- clocks
|
||||
- clock-names
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,adreno-44010000
|
||||
- qcom,adreno-44070001
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -434,6 +451,8 @@ allOf:
|
|||
- qcom,adreno-43050a01
|
||||
- qcom,adreno-43050c01
|
||||
- qcom,adreno-43051401
|
||||
- qcom,adreno-44010000
|
||||
- qcom,adreno-44070001
|
||||
|
||||
then: # Starting with A6xx, the clocks are usually defined in the GMU node
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,286 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,milos-mdss.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Milos Display MDSS
|
||||
|
||||
maintainers:
|
||||
- Luca Weiss <luca.weiss@fairphone.com>
|
||||
|
||||
description:
|
||||
Milos MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like
|
||||
DPU display controller, DSI and DP interfaces etc.
|
||||
|
||||
$ref: /schemas/display/msm/mdss-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,milos-mdss
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display AHB
|
||||
- description: Display hf AXI
|
||||
- description: Display core
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
interconnects:
|
||||
items:
|
||||
- description: Interconnect path from mdp0 port to the data bus
|
||||
- description: Interconnect path from CPU to the reg bus
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: mdp0-mem
|
||||
- const: cpu-cfg
|
||||
|
||||
patternProperties:
|
||||
"^display-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,milos-dpu
|
||||
|
||||
"^displayport-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,milos-dp
|
||||
|
||||
"^dsi@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,milos-dsi-ctrl
|
||||
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,milos-dsi-phy-4nm
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,dsi-phy-28nm.h>
|
||||
#include <dt-bindings/clock/qcom,milos-dispcc.h>
|
||||
#include <dt-bindings/clock/qcom,milos-gcc.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
#include <dt-bindings/interconnect/qcom,milos-rpmh.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
|
||||
display-subsystem@ae00000 {
|
||||
compatible = "qcom,milos-mdss";
|
||||
reg = <0x0ae00000 0x1000>;
|
||||
reg-names = "mdss";
|
||||
|
||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>;
|
||||
|
||||
resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;
|
||||
|
||||
interconnects = <&mmss_noc MASTER_MDP QCOM_ICC_TAG_ALWAYS
|
||||
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
|
||||
<&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
|
||||
&cnoc_main SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
|
||||
interconnect-names = "mdp0-mem",
|
||||
"cpu-cfg";
|
||||
|
||||
power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>;
|
||||
|
||||
iommus = <&apps_smmu 0x1c00 0x2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,milos-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x3000>;
|
||||
reg-names = "mdp",
|
||||
"vbif";
|
||||
|
||||
interrupts-extended = <&mdss 0>;
|
||||
|
||||
clocks = <&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 = "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_CX>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
dpu_intf1_out: endpoint {
|
||||
remote-endpoint = <&mdss_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-342000000 {
|
||||
opp-hz = /bits/ 64 <342000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-402000000 {
|
||||
opp-hz = /bits/ 64 <402000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-535000000 {
|
||||
opp-hz = /bits/ 64 <535000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
|
||||
opp-600000000 {
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
required-opps = <&rpmhpd_opp_nom_l1>;
|
||||
};
|
||||
|
||||
opp-630000000 {
|
||||
opp-hz = /bits/ 64 <630000000>;
|
||||
required-opps = <&rpmhpd_opp_turbo>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dsi@ae94000 {
|
||||
compatible = "qcom,milos-dsi-ctrl", "qcom,mdss-dsi-ctrl";
|
||||
reg = <0x0ae94000 0x1000>;
|
||||
reg-names = "dsi_ctrl";
|
||||
|
||||
interrupts-extended = <&mdss 4>;
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_PCLK0_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_ESC0_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>;
|
||||
clock-names = "byte",
|
||||
"byte_intf",
|
||||
"pixel",
|
||||
"core",
|
||||
"iface",
|
||||
"bus";
|
||||
|
||||
assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
|
||||
<&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
|
||||
assigned-clock-parents = <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>,
|
||||
<&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>;
|
||||
|
||||
operating-points-v2 = <&mdss_dsi_opp_table>;
|
||||
|
||||
power-domains = <&rpmhpd RPMHPD_CX>;
|
||||
|
||||
phys = <&mdss_dsi0_phy>;
|
||||
phy-names = "dsi";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
mdss_dsi0_in: endpoint {
|
||||
remote-endpoint = <&dpu_intf1_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
mdss_dsi0_out: endpoint {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdss_dsi_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-187500000 {
|
||||
opp-hz = /bits/ 64 <187500000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-358000000 {
|
||||
opp-hz = /bits/ 64 <358000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdss_dsi0_phy: phy@ae95000 {
|
||||
compatible = "qcom,milos-dsi-phy-4nm";
|
||||
reg = <0x0ae95000 0x200>,
|
||||
<0x0ae95200 0x300>,
|
||||
<0x0ae95500 0x400>;
|
||||
reg-names = "dsi_phy",
|
||||
"dsi_phy_lane",
|
||||
"dsi_pll";
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&rpmhcc RPMH_CXO_CLK>;
|
||||
clock-names = "iface",
|
||||
"ref";
|
||||
|
||||
#clock-cells = <1>;
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -18,6 +18,7 @@ properties:
|
|||
- qcom,eliza-dpu
|
||||
- qcom,glymur-dpu
|
||||
- qcom,kaanapali-dpu
|
||||
- qcom,milos-dpu
|
||||
- qcom,sa8775p-dpu
|
||||
- qcom,sm8650-dpu
|
||||
- qcom,sm8750-dpu
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ properties:
|
|||
- qcom,dsi-phy-7nm
|
||||
- qcom,dsi-phy-7nm-8150
|
||||
- qcom,kaanapali-dsi-phy-3nm
|
||||
- qcom,milos-dsi-phy-4nm
|
||||
- qcom,sa8775p-dsi-phy-5nm
|
||||
- qcom,sar2130p-dsi-phy-5nm
|
||||
- qcom,sc7280-dsi-phy-7nm
|
||||
|
|
|
|||
|
|
@ -386,6 +386,10 @@ linkcheck-docs:
|
|||
rules:
|
||||
- when: never
|
||||
|
||||
mr-label-maker-test:
|
||||
rules:
|
||||
- when: never
|
||||
|
||||
test-docs:
|
||||
rules:
|
||||
- when: never
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ msm-y += \
|
|||
msm_gpu_devfreq.o \
|
||||
msm_io_utils.o \
|
||||
msm_iommu.o \
|
||||
msm_perf.o \
|
||||
msm_perfcntr.o \
|
||||
msm_rd.o \
|
||||
msm_ringbuffer.o \
|
||||
msm_submitqueue.o \
|
||||
|
|
@ -177,6 +177,11 @@ quiet_cmd_headergen = GENHDR $@
|
|||
cmd_headergen = mkdir -p $(obj)/generated && $(PYTHON3) $(src)/registers/gen_header.py \
|
||||
$(headergen-opts) --rnn $(src)/registers --xml $< c-defines > $@
|
||||
|
||||
# TODO how to do this for a2xx/a5xx which have different .xml arg?
|
||||
quiet_cmd_headergen_json = GENHDRJSN $@
|
||||
cmd_headergen_json = mkdir -p $(obj)/generated && $(PYTHON3) $(src)/registers/gen_header.py \
|
||||
$(headergen-opts) --rnn $(src)/registers --xml $(filter %.xml,$^) perfcntrs --json $< > $@
|
||||
|
||||
$(obj)/generated/%.xml.h: $(src)/registers/adreno/%.xml \
|
||||
$(src)/registers/adreno/adreno_common.xml \
|
||||
$(src)/registers/adreno/adreno_pm4.xml \
|
||||
|
|
@ -193,6 +198,24 @@ $(obj)/generated/%.xml.h: $(src)/registers/display/%.xml \
|
|||
FORCE
|
||||
$(call if_changed,headergen)
|
||||
|
||||
ADRENO_PERFCNTRS =
|
||||
|
||||
define adreno_perfcntrs
|
||||
ADRENO_PERFCNTRS += generated/$(1)_perfcntrs.json.c
|
||||
$$(obj)/generated/$(1)_perfcntrs.json.c: $$(src)/registers/adreno/$(1)_perfcntrs.json \
|
||||
$$(src)/registers/adreno/$(2).xml \
|
||||
FORCE
|
||||
$$(call if_changed,headergen_json)
|
||||
endef
|
||||
|
||||
$(eval $(call adreno_perfcntrs,a2xx,a2xx))
|
||||
$(eval $(call adreno_perfcntrs,a5xx,a5xx))
|
||||
$(eval $(call adreno_perfcntrs,a6xx,a6xx))
|
||||
$(eval $(call adreno_perfcntrs,a7xx,a6xx))
|
||||
$(eval $(call adreno_perfcntrs,a8xx,a6xx))
|
||||
|
||||
adreno-y += $(ADRENO_PERFCNTRS:.c=.o)
|
||||
|
||||
ADRENO_HEADERS = \
|
||||
generated/a2xx.xml.h \
|
||||
generated/a3xx.xml.h \
|
||||
|
|
@ -224,7 +247,7 @@ DISPLAY_HEADERS = \
|
|||
generated/mdss.xml.h \
|
||||
generated/sfpb.xml.h
|
||||
|
||||
$(addprefix $(obj)/,$(adreno-y)): $(addprefix $(obj)/,$(ADRENO_HEADERS))
|
||||
$(addprefix $(obj)/,$(msm-y)): $(addprefix $(obj)/,$(ADRENO_HEADERS))
|
||||
$(addprefix $(obj)/,$(msm-display-y)): $(addprefix $(obj)/,$(DISPLAY_HEADERS))
|
||||
|
||||
targets += $(ADRENO_HEADERS) $(DISPLAY_HEADERS)
|
||||
targets += $(ADRENO_HEADERS) $(DISPLAY_HEADERS) $(ADRENO_PERFCNTRS)
|
||||
|
|
|
|||
|
|
@ -489,10 +489,6 @@ static u32 a2xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
return ring->memptrs->rptr;
|
||||
}
|
||||
|
||||
static const struct msm_gpu_perfcntr perfcntrs[] = {
|
||||
/* TODO */
|
||||
};
|
||||
|
||||
static struct msm_gpu *a2xx_gpu_init(struct drm_device *dev)
|
||||
{
|
||||
struct a2xx_gpu *a2xx_gpu = NULL;
|
||||
|
|
@ -518,9 +514,6 @@ static struct msm_gpu *a2xx_gpu_init(struct drm_device *dev)
|
|||
adreno_gpu = &a2xx_gpu->base;
|
||||
gpu = &adreno_gpu->base;
|
||||
|
||||
gpu->perfcntrs = perfcntrs;
|
||||
gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
|
||||
|
||||
ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, 1);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -266,12 +266,6 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
|
|||
/* Turn on performance counters: */
|
||||
gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
|
||||
|
||||
/* Enable the perfcntrs that we use.. */
|
||||
for (i = 0; i < gpu->num_perfcntrs; i++) {
|
||||
const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
|
||||
gpu_write(gpu, perfcntr->select_reg, perfcntr->select_val);
|
||||
}
|
||||
|
||||
gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK);
|
||||
|
||||
ret = adreno_hw_init(gpu);
|
||||
|
|
@ -508,13 +502,6 @@ static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
return ring->memptrs->rptr;
|
||||
}
|
||||
|
||||
static const struct msm_gpu_perfcntr perfcntrs[] = {
|
||||
{ REG_A3XX_SP_PERFCOUNTER6_SELECT, REG_A3XX_RBBM_PERFCTR_SP_6_LO,
|
||||
SP_ALU_ACTIVE_CYCLES, "ALUACTIVE" },
|
||||
{ REG_A3XX_SP_PERFCOUNTER7_SELECT, REG_A3XX_RBBM_PERFCTR_SP_7_LO,
|
||||
SP_FS_FULL_ALU_INSTRUCTIONS, "ALUFULL" },
|
||||
};
|
||||
|
||||
static struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
|
||||
{
|
||||
struct a3xx_gpu *a3xx_gpu = NULL;
|
||||
|
|
@ -542,9 +529,6 @@ static struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
|
|||
adreno_gpu = &a3xx_gpu->base;
|
||||
gpu = &adreno_gpu->base;
|
||||
|
||||
gpu->perfcntrs = perfcntrs;
|
||||
gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
|
||||
|
||||
adreno_gpu->registers = a3xx_registers;
|
||||
|
||||
ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, 1);
|
||||
|
|
|
|||
|
|
@ -652,9 +652,6 @@ static struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
|
|||
adreno_gpu = &a4xx_gpu->base;
|
||||
gpu = &adreno_gpu->base;
|
||||
|
||||
gpu->perfcntrs = NULL;
|
||||
gpu->num_perfcntrs = 0;
|
||||
|
||||
ret = adreno_gpu_init(dev, pdev, adreno_gpu, config->info->funcs, 1);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -752,17 +752,13 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
|
|||
gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
|
||||
|
||||
/* Disable L2 bypass in the UCHE */
|
||||
gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base));
|
||||
gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base));
|
||||
gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, lower_32_bits(adreno_gpu->uche_trap_base));
|
||||
gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, upper_32_bits(adreno_gpu->uche_trap_base));
|
||||
gpu_write64(gpu, REG_A5XX_UCHE_TRAP_BASE, adreno_gpu->uche_trap_base);
|
||||
gpu_write64(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE, adreno_gpu->uche_trap_base);
|
||||
|
||||
/* Set the GMEM VA range (0 to gpu->gmem) */
|
||||
gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
|
||||
gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
|
||||
gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
|
||||
gpu_write64(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN, 0x00100000);
|
||||
gpu_write64(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX,
|
||||
0x00100000 + adreno_gpu->info->gmem - 1);
|
||||
gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
|
||||
|
||||
if (adreno_is_a505(adreno_gpu) || adreno_is_a506(adreno_gpu) ||
|
||||
adreno_is_a508(adreno_gpu) || adreno_is_a510(adreno_gpu)) {
|
||||
|
|
@ -1217,9 +1213,7 @@ static void a5xx_rbbm_err_irq(struct msm_gpu *gpu, u32 status)
|
|||
|
||||
static void a5xx_uche_err_irq(struct msm_gpu *gpu)
|
||||
{
|
||||
uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
|
||||
|
||||
addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
|
||||
uint64_t addr = gpu_read64(gpu, REG_A5XX_UCHE_TRAP_LOG);
|
||||
|
||||
dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
|
||||
addr);
|
||||
|
|
@ -1725,7 +1719,6 @@ static struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
|
|||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct platform_device *pdev = priv->gpu_pdev;
|
||||
struct adreno_platform_config *config = pdev->dev.platform_data;
|
||||
const struct qcom_ubwc_cfg_data *common_cfg;
|
||||
struct a5xx_gpu *a5xx_gpu = NULL;
|
||||
struct adreno_gpu *adreno_gpu;
|
||||
struct msm_gpu *gpu;
|
||||
|
|
@ -1769,13 +1762,9 @@ static struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
|
|||
a5xx_preempt_init(gpu);
|
||||
|
||||
/* Inherit the common config and make some necessary fixups */
|
||||
common_cfg = qcom_ubwc_config_get_data();
|
||||
if (IS_ERR(common_cfg))
|
||||
return ERR_CAST(common_cfg);
|
||||
|
||||
/* Copy the data into the internal struct to drop the const qualifier (temporarily) */
|
||||
adreno_gpu->_ubwc_config = *common_cfg;
|
||||
adreno_gpu->ubwc_config = &adreno_gpu->_ubwc_config;
|
||||
adreno_gpu->ubwc_config = qcom_ubwc_config_get_data();
|
||||
if (IS_ERR(adreno_gpu->ubwc_config))
|
||||
return ERR_CAST(adreno_gpu->ubwc_config);
|
||||
|
||||
adreno_gpu->uche_trap_base = 0x0001ffffffff0000ull;
|
||||
|
||||
|
|
|
|||
|
|
@ -1799,6 +1799,261 @@ static const struct adreno_reglist_pipe x285_dyn_pwrup_reglist_regs[] = {
|
|||
};
|
||||
DECLARE_ADRENO_REGLIST_PIPE_LIST(x285_dyn_pwrup_reglist);
|
||||
|
||||
static const struct adreno_reglist_pipe a810_nonctxt_regs[] = {
|
||||
{ REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_GRAS_DBG_ECO_CNTL, 0x00f80800, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_VIS_STREAM_CNTL, 0x10010000, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0x00000002, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_1, 0x00000003, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_1, 0x00000023, BIT(PIPE_BV) }, /* Avoid partial waves at VFD */
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_2, 0x00000200, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_3, 0x00500000, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_4, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A7XX_RB_CCU_CNTL, 0x00000068, BIT(PIPE_BR) },
|
||||
/* Partially enable perf clear, Disable DINT to c/z be data forwarding */
|
||||
{ REG_A7XX_RB_CCU_DBG_ECO_CNTL, 0x00002200, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0x00000007, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0x00004000, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RBBM_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_RBBM_SLICE_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL, 0x00000030, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL2, 0x00000030, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_UCHE_GBIF_GX_CONFIG, 0x010240e0, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x22122212, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_RBBM_CGC_P2S_CNTL, 0x00000040, BIT(PIPE_NONE) },
|
||||
/*
|
||||
* BIT(22): Disable PS out of order retire
|
||||
* BIT(23): Enable half wave mode and MM instruction src&dst is half precision
|
||||
*/
|
||||
{ REG_A7XX_SP_CHICKEN_BITS_2, BIT(22) | BIT(23), BIT(PIPE_NONE) },
|
||||
{ REG_A7XX_SP_CHICKEN_BITS_3, 0x00300000, BIT(PIPE_NONE) },
|
||||
{ REG_A6XX_SP_PERFCTR_SHADER_MASK, 0x0000003f, BIT(PIPE_NONE) },
|
||||
{ REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP, 0x00000080, BIT(PIPE_NONE) },
|
||||
{ REG_A6XX_TPL1_DBG_ECO_CNTL, 0x10100000, BIT(PIPE_NONE) },
|
||||
{ REG_A6XX_TPL1_DBG_ECO_CNTL1, 0x04000724, BIT(PIPE_NONE) },
|
||||
{ REG_A6XX_UCHE_MODE_CNTL, 0x00020000, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_UCHE_CCHE_MODE_CNTL, 0x00001000, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_UCHE_CCHE_CACHE_WAYS, 0x00000800, BIT(PIPE_NONE) },
|
||||
/* Disable write slow pointer in data phase queue */
|
||||
{ REG_A8XX_UCHE_HW_DBG_CNTL, BIT(8), BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_UCHE_VARB_IDLE_TIMEOUT, 0x00000020, BIT(PIPE_NONE) },
|
||||
{ REG_A7XX_VFD_DBG_ECO_CNTL, 0x00008000, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VFD_CB_BV_THRESHOLD, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VFD_CB_BR_THRESHOLD, 0x00600060, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0x00200020, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VFD_CB_LP_REQ_CNT, 0x00100020, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_GC_GMEM_PROTECT, 0x00900000, BIT(PIPE_BR) },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const u32 a810_protect_regs[] = {
|
||||
A6XX_PROTECT_RDONLY(0x00000, 0x03a3),
|
||||
A6XX_PROTECT_RDONLY(0x003b4, 0x008b),
|
||||
A6XX_PROTECT_NORDWR(0x00440, 0x001f),
|
||||
A6XX_PROTECT_RDONLY(0x00580, 0x005f),
|
||||
A6XX_PROTECT_NORDWR(0x005e0, 0x011f),
|
||||
A6XX_PROTECT_RDONLY(0x0074a, 0x0005),
|
||||
A6XX_PROTECT_RDONLY(0x00759, 0x0026),
|
||||
A6XX_PROTECT_RDONLY(0x00789, 0x0000),
|
||||
A6XX_PROTECT_RDONLY(0x0078c, 0x0013),
|
||||
A6XX_PROTECT_NORDWR(0x00800, 0x0029),
|
||||
A6XX_PROTECT_NORDWR(0x00837, 0x00af),
|
||||
A6XX_PROTECT_RDONLY(0x008e7, 0x00c9),
|
||||
A6XX_PROTECT_NORDWR(0x008ec, 0x00c3),
|
||||
A6XX_PROTECT_NORDWR(0x009b1, 0x0250),
|
||||
A6XX_PROTECT_RDONLY(0x00ce0, 0x0001),
|
||||
A6XX_PROTECT_RDONLY(0x00df0, 0x0000),
|
||||
A6XX_PROTECT_NORDWR(0x00df1, 0x0000),
|
||||
A6XX_PROTECT_NORDWR(0x00e01, 0x0000),
|
||||
A6XX_PROTECT_NORDWR(0x00e03, 0x1fff),
|
||||
A6XX_PROTECT_NORDWR(0x03c00, 0x00c5),
|
||||
A6XX_PROTECT_RDONLY(0x03cc6, 0x1fff),
|
||||
A6XX_PROTECT_NORDWR(0x08600, 0x01ff),
|
||||
A6XX_PROTECT_NORDWR(0x08e00, 0x00ff),
|
||||
A6XX_PROTECT_RDONLY(0x08f00, 0x0000),
|
||||
A6XX_PROTECT_NORDWR(0x08f01, 0x01be),
|
||||
A6XX_PROTECT_NORDWR(0x09600, 0x01ff),
|
||||
A6XX_PROTECT_RDONLY(0x0981a, 0x02e5),
|
||||
A6XX_PROTECT_NORDWR(0x09e00, 0x01ff),
|
||||
A6XX_PROTECT_NORDWR(0x0a600, 0x01ff),
|
||||
A6XX_PROTECT_NORDWR(0x0ae00, 0x0006),
|
||||
A6XX_PROTECT_NORDWR(0x0ae08, 0x0006),
|
||||
A6XX_PROTECT_NORDWR(0x0ae10, 0x036f),
|
||||
A6XX_PROTECT_NORDWR(0x0b600, 0x1fff),
|
||||
A6XX_PROTECT_NORDWR(0x0dc00, 0x1fff),
|
||||
A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
|
||||
A6XX_PROTECT_NORDWR(0x18400, 0x003f),
|
||||
A6XX_PROTECT_RDONLY(0x18440, 0x013f),
|
||||
A6XX_PROTECT_NORDWR(0x18580, 0x1fff),
|
||||
A6XX_PROTECT_NORDWR(0x1b400, 0x1fff),
|
||||
A6XX_PROTECT_NORDWR(0x1f400, 0x0477),
|
||||
A6XX_PROTECT_RDONLY(0x1f878, 0x0787),
|
||||
A6XX_PROTECT_NORDWR(0x1f930, 0x0329),
|
||||
A6XX_PROTECT_NORDWR(0x20000, 0x1fff),
|
||||
A6XX_PROTECT_NORDWR(0x27800, 0x007f),
|
||||
A6XX_PROTECT_RDONLY(0x27880, 0x0381),
|
||||
A6XX_PROTECT_NORDWR(0x27882, 0x0001),
|
||||
A6XX_PROTECT_NORDWR(0x27c02, 0x0000),
|
||||
};
|
||||
DECLARE_ADRENO_PROTECT(a810_protect, 64);
|
||||
|
||||
static const uint32_t a810_pwrup_reglist_regs[] = {
|
||||
REG_A6XX_UCHE_MODE_CNTL,
|
||||
REG_A8XX_UCHE_VARB_IDLE_TIMEOUT,
|
||||
REG_A8XX_UCHE_GBIF_GX_CONFIG,
|
||||
REG_A8XX_UCHE_CACHE_WAYS,
|
||||
REG_A8XX_UCHE_CCHE_MODE_CNTL,
|
||||
REG_A8XX_UCHE_CCHE_CACHE_WAYS,
|
||||
REG_A8XX_UCHE_CCHE_GC_GMEM_RANGE_MIN,
|
||||
REG_A8XX_UCHE_CCHE_GC_GMEM_RANGE_MIN + 1,
|
||||
REG_A8XX_UCHE_CCHE_TRAP_BASE,
|
||||
REG_A8XX_UCHE_CCHE_TRAP_BASE + 1,
|
||||
REG_A8XX_UCHE_CCHE_WRITE_THRU_BASE,
|
||||
REG_A8XX_UCHE_CCHE_WRITE_THRU_BASE + 1,
|
||||
REG_A8XX_UCHE_HW_DBG_CNTL,
|
||||
REG_A8XX_UCHE_WRITE_THRU_BASE,
|
||||
REG_A8XX_UCHE_WRITE_THRU_BASE + 1,
|
||||
REG_A8XX_UCHE_TRAP_BASE,
|
||||
REG_A8XX_UCHE_TRAP_BASE + 1,
|
||||
REG_A8XX_UCHE_CLIENT_PF,
|
||||
REG_A8XX_RB_CMP_NC_MODE_CNTL,
|
||||
REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP,
|
||||
REG_A8XX_SP_HLSQ_GC_GMEM_RANGE_MIN,
|
||||
REG_A8XX_SP_HLSQ_GC_GMEM_RANGE_MIN + 1,
|
||||
REG_A7XX_SP_READ_SEL,
|
||||
REG_A6XX_TPL1_NC_MODE_CNTL,
|
||||
REG_A6XX_TPL1_DBG_ECO_CNTL,
|
||||
REG_A6XX_TPL1_DBG_ECO_CNTL1,
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(1),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(5),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(6),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(7),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(8),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(9),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(10),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(11),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(12),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(13),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(14),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(15),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(16),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(17),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(18),
|
||||
REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(19),
|
||||
};
|
||||
DECLARE_ADRENO_REGLIST_LIST(a810_pwrup_reglist);
|
||||
|
||||
static const u32 a810_ifpc_reglist_regs[] = {
|
||||
REG_A8XX_RBBM_NC_MODE_CNTL,
|
||||
REG_A8XX_RBBM_PERFCTR_CNTL,
|
||||
REG_A8XX_RBBM_SLICE_INTERFACE_HANG_INT_CNTL,
|
||||
REG_A8XX_RBBM_SLICE_NC_MODE_CNTL,
|
||||
REG_A6XX_SP_NC_MODE_CNTL,
|
||||
REG_A7XX_SP_CHICKEN_BITS_2,
|
||||
REG_A7XX_SP_CHICKEN_BITS_3,
|
||||
REG_A6XX_SP_PERFCTR_SHADER_MASK,
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(0),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(1),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(2),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(3),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(4),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(5),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(6),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(7),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(8),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(9),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(10),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(11),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(12),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(13),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(14),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(15),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(16),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(17),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(18),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(19),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(20),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(21),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(22),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(23),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(24),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(25),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(26),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(27),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(28),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(29),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(30),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(31),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(32),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(33),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(34),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(35),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(36),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(37),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(38),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(39),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(40),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(41),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(42),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(43),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(44),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(45),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(46),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(47),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(48),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(49),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(50),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(51),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(52),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(53),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(54),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(55),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(56),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(57),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(58),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(59),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(60),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(61),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(62),
|
||||
REG_A8XX_CP_PROTECT_GLOBAL(63),
|
||||
};
|
||||
DECLARE_ADRENO_REGLIST_LIST(a810_ifpc_reglist);
|
||||
|
||||
static const struct adreno_reglist_pipe a810_dyn_pwrup_reglist_regs[] = {
|
||||
{ REG_A8XX_CP_PROTECT_CNTL_PIPE, 0, BIT(PIPE_BR) | BIT(PIPE_BV) },
|
||||
{ REG_A8XX_CP_PROTECT_PIPE(15), 0, BIT(PIPE_BR) | BIT(PIPE_BV) },
|
||||
{ REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_GRAS_NC_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_GRAS_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A7XX_RB_CCU_CNTL, 0, BIT(PIPE_BR) },
|
||||
{ REG_A7XX_RB_CCU_DBG_ECO_CNTL, 0, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_CCU_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_CMP_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_RB_GC_GMEM_PROTECT, 0, BIT(PIPE_BR) },
|
||||
{ REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 0, BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_1, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_2, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_3, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_PC_CHICKEN_BITS_4, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0, BIT(PIPE_BR) | BIT(PIPE_BV) },
|
||||
{ REG_A8XX_PC_VIS_STREAM_CNTL, 0, BIT(PIPE_BR) | BIT(PIPE_BV) },
|
||||
{ REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0, BIT(PIPE_BR) | BIT(PIPE_BV) },
|
||||
{ REG_A8XX_VFD_CB_BV_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VFD_CB_BR_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A8XX_VFD_CB_LP_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
{ REG_A7XX_VFD_DBG_ECO_CNTL, 0, BIT(PIPE_BR) | BIT(PIPE_BV) },
|
||||
};
|
||||
DECLARE_ADRENO_REGLIST_PIPE_LIST(a810_dyn_pwrup_reglist);
|
||||
|
||||
static const struct adreno_reglist_pipe a840_nonctxt_regs[] = {
|
||||
{ REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) },
|
||||
{ REG_A8XX_GRAS_DBG_ECO_CNTL, 0x00000800, BIT(PIPE_BV) | BIT(PIPE_BR) },
|
||||
|
|
@ -2193,6 +2448,48 @@ static const struct adreno_info a8xx_gpus[] = {
|
|||
{ 252, 2 },
|
||||
{ 221, 3 },
|
||||
),
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x44010000),
|
||||
.family = ADRENO_8XX_GEN1,
|
||||
.fw = {
|
||||
[ADRENO_FW_SQE] = "gen80300_sqe.fw",
|
||||
[ADRENO_FW_GMU] = "gen80300_gmu.bin",
|
||||
},
|
||||
.gmem = SZ_512K + SZ_64K,
|
||||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV |
|
||||
ADRENO_QUIRK_PREEMPTION |
|
||||
ADRENO_QUIRK_IFPC,
|
||||
.funcs = &a8xx_gpu_funcs,
|
||||
.zapfw = "gen80300_zap.mbn",
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.protect = &a810_protect,
|
||||
.nonctxt_reglist = a810_nonctxt_regs,
|
||||
.pwrup_reglist = &a810_pwrup_reglist,
|
||||
.dyn_pwrup_reglist = &a810_dyn_pwrup_reglist,
|
||||
.ifpc_reglist = &a810_ifpc_reglist,
|
||||
.gbif_cx = a840_gbif,
|
||||
.max_slices = 1,
|
||||
.gmu_chipid = 0x8030000,
|
||||
.bcms = (const struct a6xx_bcm[]) {
|
||||
{ .name = "SH0", .buswidth = 16 },
|
||||
{ .name = "MC0", .buswidth = 4 },
|
||||
{
|
||||
.name = "ACV",
|
||||
.fixed = true,
|
||||
.perfmode = BIT(2),
|
||||
.perfmode_bw = 10687500,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
},
|
||||
},
|
||||
.preempt_record_size = 4558 * SZ_1K,
|
||||
.speedbins = ADRENO_SPEEDBINS(
|
||||
{ 0, 0 },
|
||||
{ 242, 1 },
|
||||
{ 221, 2 },
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2205,4 +2502,5 @@ static inline __always_unused void __build_asserts(void)
|
|||
BUILD_BUG_ON(a660_protect.count > a660_protect.count_max);
|
||||
BUILD_BUG_ON(a690_protect.count > a690_protect.count_max);
|
||||
BUILD_BUG_ON(a730_protect.count > a730_protect.count_max);
|
||||
BUILD_BUG_ON(a810_protect.count > a810_protect.count_max);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -947,7 +947,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
|
|||
|
||||
/* Turn on TCM (Tightly Coupled Memory) retention */
|
||||
if (adreno_is_a7xx(adreno_gpu))
|
||||
a6xx_llc_write(a6xx_gpu, REG_A7XX_CX_MISC_TCM_RET_CNTL, 1);
|
||||
a6xx_cx_misc_write(a6xx_gpu, REG_A7XX_CX_MISC_TCM_RET_CNTL, 1);
|
||||
else if (!adreno_is_a8xx(adreno_gpu))
|
||||
gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
|
||||
|
||||
|
|
@ -1215,7 +1215,7 @@ static int a6xx_gmu_secure_init(struct a6xx_gpu *a6xx_gpu)
|
|||
if (!qcom_scm_is_available()) {
|
||||
dev_warn_once(gpu->dev->dev,
|
||||
"SCM is not available, poking fuse register\n");
|
||||
a6xx_llc_write(a6xx_gpu, REG_A7XX_CX_MISC_SW_FUSE_VALUE,
|
||||
a6xx_cx_misc_write(a6xx_gpu, REG_A7XX_CX_MISC_SW_FUSE_VALUE,
|
||||
A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING |
|
||||
A7XX_CX_MISC_SW_FUSE_VALUE_FASTBLEND |
|
||||
A7XX_CX_MISC_SW_FUSE_VALUE_LPAC);
|
||||
|
|
@ -1236,7 +1236,7 @@ static int a6xx_gmu_secure_init(struct a6xx_gpu *a6xx_gpu)
|
|||
* firmware, find out whether that's the case. The scm call
|
||||
* above sets the fuse register.
|
||||
*/
|
||||
fuse_val = a6xx_llc_read(a6xx_gpu,
|
||||
fuse_val = a6xx_cx_misc_read(a6xx_gpu,
|
||||
REG_A7XX_CX_MISC_SW_FUSE_VALUE);
|
||||
adreno_gpu->has_ray_tracing =
|
||||
!!(fuse_val & A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING);
|
||||
|
|
@ -1250,6 +1250,56 @@ static int a6xx_gmu_secure_init(struct a6xx_gpu *a6xx_gpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int a6xx_gmu_gxpd_get(struct a6xx_gmu *gmu)
|
||||
{
|
||||
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
|
||||
if (IS_ERR_OR_NULL(gmu->gxpd))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* On A8xx HW, GX GDSC is moved to a new clk controller block under GX
|
||||
* power domain. The clock driver for this new block keeps the GX rail
|
||||
* voted when gxpd is voted. So, use the gxpd only during gpu recovery.
|
||||
*/
|
||||
if (adreno_gpu->info->family >= ADRENO_8XX_GEN1)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* On A6x/A7x, "enable" the GX power domain which won't actually do
|
||||
* anything but it will make sure that the refcounting is correct in
|
||||
* case we need to bring down the GX after a GMU failure
|
||||
*/
|
||||
return pm_runtime_get_sync(gmu->gxpd);
|
||||
}
|
||||
|
||||
static int a6xx_gmu_gxpd_put(struct a6xx_gmu *gmu)
|
||||
{
|
||||
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
|
||||
if (IS_ERR_OR_NULL(gmu->gxpd))
|
||||
return 0;
|
||||
|
||||
if (adreno_gpu->info->family < ADRENO_8XX_GEN1)
|
||||
return pm_runtime_put_sync(gmu->gxpd);
|
||||
|
||||
/*
|
||||
* On A8x, GX GDSC collapse should be triggered only when it is stuck ON
|
||||
*/
|
||||
if (adreno_gpu->funcs->gx_is_on(adreno_gpu)) {
|
||||
pm_runtime_get_sync(gmu->gxpd);
|
||||
/*
|
||||
* Hint to gfxclkctl driver to do a hw collapse during the next
|
||||
* RPM PUT. This is a special behavior in the gfxclkctl driver
|
||||
*/
|
||||
dev_pm_genpd_synced_poweroff(gmu->gxpd);
|
||||
pm_runtime_put_sync(gmu->gxpd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
|
||||
{
|
||||
|
|
@ -1266,13 +1316,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
|
|||
/* Turn on the resources */
|
||||
pm_runtime_get_sync(gmu->dev);
|
||||
|
||||
/*
|
||||
* "enable" the GX power domain which won't actually do anything but it
|
||||
* will make sure that the refcounting is correct in case we need to
|
||||
* bring down the GX after a GMU failure
|
||||
*/
|
||||
if (!IS_ERR_OR_NULL(gmu->gxpd))
|
||||
pm_runtime_get_sync(gmu->gxpd);
|
||||
a6xx_gmu_gxpd_get(gmu);
|
||||
|
||||
/* Use a known rate to bring up the GMU */
|
||||
clk_set_rate(gmu->core_clk, 200000000);
|
||||
|
|
@ -1299,7 +1343,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
|
|||
|
||||
/* Check to see if we are doing a cold or warm boot */
|
||||
if (adreno_is_a7xx(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) {
|
||||
status = a6xx_llc_read(a6xx_gpu, REG_A7XX_CX_MISC_TCM_RET_CNTL) == 1 ?
|
||||
status = a6xx_cx_misc_read(a6xx_gpu, REG_A7XX_CX_MISC_TCM_RET_CNTL) == 1 ?
|
||||
GMU_WARM_BOOT : GMU_COLD_BOOT;
|
||||
} else if (gmu->legacy) {
|
||||
status = gmu_read(gmu, REG_A6XX_GMU_GENERAL_7) == 1 ?
|
||||
|
|
@ -1339,7 +1383,8 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
|
|||
disable_clk:
|
||||
clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
|
||||
rpm_put:
|
||||
pm_runtime_put(gmu->gxpd);
|
||||
a6xx_gmu_gxpd_put(gmu);
|
||||
|
||||
pm_runtime_put(gmu->dev);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1455,8 +1500,7 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
|
|||
* domain. Usually the GMU does this but only if the shutdown sequence
|
||||
* was successful
|
||||
*/
|
||||
if (!IS_ERR_OR_NULL(gmu->gxpd))
|
||||
pm_runtime_put_sync(gmu->gxpd);
|
||||
a6xx_gmu_gxpd_put(gmu);
|
||||
|
||||
clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
|
||||
|
||||
|
|
@ -2034,12 +2078,12 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
|
|||
return irq;
|
||||
}
|
||||
|
||||
void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu)
|
||||
void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu, bool force_on)
|
||||
{
|
||||
bool sysprof = msm_gpu_sysprof_no_ifpc(gpu) || force_on;
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
|
||||
unsigned int sysprof_active;
|
||||
|
||||
/* Nothing to do if GPU is suspended. We will handle this during GMU resume */
|
||||
if (!pm_runtime_get_if_active(&gpu->pdev->dev))
|
||||
|
|
@ -2047,15 +2091,13 @@ void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu)
|
|||
|
||||
mutex_lock(&gmu->lock);
|
||||
|
||||
sysprof_active = refcount_read(&gpu->sysprof_active);
|
||||
|
||||
/*
|
||||
* 'Perfcounter select' register values are lost during IFPC collapse. To avoid that,
|
||||
* use the currently unused perfcounter oob vote to block IFPC when sysprof is active
|
||||
*/
|
||||
if ((sysprof_active > 1) && !test_and_set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
if (sysprof && !test_and_set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
else if ((sysprof_active == 1) && test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
else if (!sysprof && test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
mutex_unlock(&gmu->lock);
|
||||
|
|
@ -2357,7 +2399,12 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
|
|||
goto err_mmio;
|
||||
}
|
||||
} else if (adreno_is_a8xx(adreno_gpu)) {
|
||||
gmu->rscc = gmu->mmio + 0x19000;
|
||||
/*
|
||||
* On a8xx , RSCC lives at GPU base + 0x50000, which falls
|
||||
* inside the GPU's kgsl_3d0_reg_memory range rather than the
|
||||
* GMU's.
|
||||
*/
|
||||
gmu->rscc = gpu->mmio + 0x50000;
|
||||
} else {
|
||||
gmu->rscc = gmu->mmio + 0x23000;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "msm_gem.h"
|
||||
#include "msm_mmu.h"
|
||||
#include "msm_gpu_trace.h"
|
||||
#include "msm_perfcntr.h"
|
||||
#include "a6xx_gpu.h"
|
||||
#include "a6xx_gmu.xml.h"
|
||||
|
||||
|
|
@ -188,6 +189,30 @@ void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
spin_unlock_irqrestore(&ring->preempt_lock, flags);
|
||||
}
|
||||
|
||||
void
|
||||
a6xx_flush_yield(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
a6xx_flush(gpu, ring);
|
||||
}
|
||||
|
||||
static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter,
|
||||
u64 iova)
|
||||
{
|
||||
|
|
@ -202,7 +227,7 @@ static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter,
|
|||
static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
||||
struct msm_ringbuffer *ring, struct msm_gem_submit *submit)
|
||||
{
|
||||
bool sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1;
|
||||
bool sysprof = msm_gpu_sysprof_no_perfcntr_zap(&a6xx_gpu->base.base);
|
||||
struct msm_context *ctx = submit->queue->ctx;
|
||||
struct drm_gpuvm *vm = msm_context_vm(submit->dev, ctx);
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
|
|
@ -596,28 +621,9 @@ 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, adreno_gpu->funcs->get_timestamp(gpu));
|
||||
|
||||
a6xx_flush(gpu, ring);
|
||||
a6xx_flush_yield(gpu, ring);
|
||||
|
||||
/* Check to see if we need to start preemption */
|
||||
if (adreno_is_a8xx(adreno_gpu))
|
||||
|
|
@ -733,82 +739,6 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
|
|||
gpu_write(gpu, REG_A6XX_CP_PROTECT(protect->count_max - 1), protect->regs[i]);
|
||||
}
|
||||
|
||||
static int a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
|
||||
{
|
||||
const struct qcom_ubwc_cfg_data *common_cfg;
|
||||
struct qcom_ubwc_cfg_data *cfg = &gpu->_ubwc_config;
|
||||
|
||||
/* Inherit the common config and make some necessary fixups */
|
||||
common_cfg = qcom_ubwc_config_get_data();
|
||||
if (IS_ERR(common_cfg))
|
||||
return PTR_ERR(common_cfg);
|
||||
|
||||
/* Copy the data into the internal struct to drop the const qualifier (temporarily) */
|
||||
*cfg = *common_cfg;
|
||||
|
||||
/* Use common config as is for A8x */
|
||||
if (!adreno_is_a8xx(gpu)) {
|
||||
cfg->ubwc_swizzle = 0x6;
|
||||
cfg->highest_bank_bit = 15;
|
||||
}
|
||||
|
||||
if (adreno_is_a610(gpu)) {
|
||||
cfg->highest_bank_bit = 13;
|
||||
cfg->ubwc_swizzle = 0x7;
|
||||
}
|
||||
|
||||
if (adreno_is_a612(gpu))
|
||||
cfg->highest_bank_bit = 14;
|
||||
|
||||
if (adreno_is_a618(gpu))
|
||||
cfg->highest_bank_bit = 14;
|
||||
|
||||
if (adreno_is_a619(gpu))
|
||||
/* TODO: Should be 14 but causes corruption at e.g. 1920x1200 on DP */
|
||||
cfg->highest_bank_bit = 13;
|
||||
|
||||
if (adreno_is_a619_holi(gpu))
|
||||
cfg->highest_bank_bit = 13;
|
||||
|
||||
if (adreno_is_a621(gpu))
|
||||
cfg->highest_bank_bit = 13;
|
||||
|
||||
if (adreno_is_a623(gpu))
|
||||
cfg->highest_bank_bit = 16;
|
||||
|
||||
if (adreno_is_a650(gpu) ||
|
||||
adreno_is_a660(gpu) ||
|
||||
adreno_is_a690(gpu) ||
|
||||
adreno_is_a730(gpu) ||
|
||||
adreno_is_a740_family(gpu)) {
|
||||
/* TODO: get ddr type from bootloader and use 15 for LPDDR4 */
|
||||
cfg->highest_bank_bit = 16;
|
||||
}
|
||||
|
||||
if (adreno_is_a663(gpu)) {
|
||||
cfg->highest_bank_bit = 13;
|
||||
cfg->ubwc_swizzle = 0x4;
|
||||
}
|
||||
|
||||
if (adreno_is_7c3(gpu))
|
||||
cfg->highest_bank_bit = 14;
|
||||
|
||||
if (adreno_is_a702(gpu))
|
||||
cfg->highest_bank_bit = 14;
|
||||
|
||||
if (cfg->highest_bank_bit != common_cfg->highest_bank_bit)
|
||||
DRM_WARN_ONCE("Inconclusive highest_bank_bit value: %u (GPU) vs %u (UBWC_CFG)\n",
|
||||
cfg->highest_bank_bit, common_cfg->highest_bank_bit);
|
||||
|
||||
if (cfg->ubwc_swizzle != common_cfg->ubwc_swizzle)
|
||||
DRM_WARN_ONCE("Inconclusive ubwc_swizzle value: %u (GPU) vs %u (UBWC_CFG)\n",
|
||||
cfg->ubwc_swizzle, common_cfg->ubwc_swizzle);
|
||||
|
||||
gpu->ubwc_config = &gpu->_ubwc_config;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
|
|
@ -821,10 +751,10 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
|
|||
BUG_ON(cfg->highest_bank_bit < 13);
|
||||
u32 hbb = cfg->highest_bank_bit - 13;
|
||||
bool rgb565_predicator = cfg->ubwc_enc_version >= UBWC_4_0;
|
||||
u32 level2_swizzling_dis = !(cfg->ubwc_swizzle & UBWC_SWIZZLE_ENABLE_LVL2);
|
||||
u32 level2_swizzling_dis = !(qcom_ubwc_swizzle(cfg) & UBWC_SWIZZLE_ENABLE_LVL2);
|
||||
bool ubwc_mode = qcom_ubwc_get_ubwc_mode(cfg);
|
||||
bool amsbc = cfg->ubwc_enc_version >= UBWC_3_0;
|
||||
bool min_acc_len_64b = false;
|
||||
bool amsbc = qcom_ubwc_enable_amsbc(cfg);
|
||||
bool min_acc_len_64b;
|
||||
u8 uavflagprd_inv = 0;
|
||||
u32 hbb_hi = hbb >> 2;
|
||||
u32 hbb_lo = hbb & 3;
|
||||
|
|
@ -832,8 +762,7 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
|
|||
if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu))
|
||||
uavflagprd_inv = 2;
|
||||
|
||||
if (adreno_is_a610(adreno_gpu) || adreno_is_a702(adreno_gpu))
|
||||
min_acc_len_64b = true;
|
||||
min_acc_len_64b = qcom_ubwc_min_acc_length_64b(cfg);
|
||||
|
||||
gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL,
|
||||
level2_swizzling_dis << 12 |
|
||||
|
|
@ -868,7 +797,7 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
|
|||
min_acc_len_64b << 23 | hbb_lo << 21);
|
||||
|
||||
gpu_write(gpu, REG_A6XX_RBBM_NC_MODE_CNTL,
|
||||
cfg->macrotile_mode);
|
||||
qcom_ubwc_macrotile_mode(cfg));
|
||||
}
|
||||
|
||||
static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
|
||||
|
|
@ -940,6 +869,7 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
|
|||
A7XX_CP_APERTURE_CNTL_HOST_PIPE(PIPE_NONE));
|
||||
}
|
||||
lock->dynamic_list_len = dyn_pwrup_reglist_count;
|
||||
a6xx_gpu->dynamic_sel_reglist_offset = dyn_pwrup_reglist_count;
|
||||
}
|
||||
|
||||
static int a7xx_preempt_start(struct msm_gpu *gpu)
|
||||
|
|
@ -957,15 +887,7 @@ static int a7xx_preempt_start(struct msm_gpu *gpu)
|
|||
|
||||
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);
|
||||
a6xx_flush_yield(gpu, ring);
|
||||
|
||||
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
|
||||
}
|
||||
|
|
@ -1185,7 +1107,7 @@ 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,
|
||||
a6xx_gpu->pwrup_reglist_ptr = msm_gem_kernel_new(gpu->dev, PWRUP_REGLIST_SIZE,
|
||||
MSM_BO_WC | MSM_BO_MAP_PRIV,
|
||||
gpu->vm, &a6xx_gpu->pwrup_reglist_bo,
|
||||
&a6xx_gpu->pwrup_reglist_iova);
|
||||
|
|
@ -1607,7 +1529,7 @@ static int hw_init(struct msm_gpu *gpu)
|
|||
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
|
||||
}
|
||||
|
||||
if (!ret && (refcount_read(&gpu->sysprof_active) > 1)) {
|
||||
if (!ret && msm_gpu_sysprof_no_ifpc(gpu)) {
|
||||
ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
if (!ret)
|
||||
set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
|
||||
|
|
@ -2039,7 +1961,7 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
|
|||
struct msm_gpu *gpu = &adreno_gpu->base;
|
||||
u32 cntl1_regval = 0;
|
||||
|
||||
if (IS_ERR(a6xx_gpu->llc_mmio))
|
||||
if (IS_ERR_OR_NULL(a6xx_gpu->llc_slice) && IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice))
|
||||
return;
|
||||
|
||||
if (!llcc_slice_activate(a6xx_gpu->llc_slice)) {
|
||||
|
|
@ -2078,14 +2000,14 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
|
|||
* pagetables
|
||||
*/
|
||||
if (!a6xx_gpu->have_mmu500) {
|
||||
a6xx_llc_write(a6xx_gpu,
|
||||
a6xx_cx_misc_write(a6xx_gpu,
|
||||
REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1, cntl1_regval);
|
||||
|
||||
/*
|
||||
* Program cacheability overrides to not allocate cache
|
||||
* lines on a write miss
|
||||
*/
|
||||
a6xx_llc_rmw(a6xx_gpu,
|
||||
a6xx_cx_misc_rmw(a6xx_gpu,
|
||||
REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 0xF, 0x03);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2098,7 +2020,7 @@ static void a7xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
|
|||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
struct msm_gpu *gpu = &adreno_gpu->base;
|
||||
|
||||
if (IS_ERR(a6xx_gpu->llc_mmio))
|
||||
if (IS_ERR_OR_NULL(a6xx_gpu->llc_slice) && IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice))
|
||||
return;
|
||||
|
||||
if (!llcc_slice_activate(a6xx_gpu->llc_slice)) {
|
||||
|
|
@ -2135,31 +2057,12 @@ static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu)
|
|||
static void a6xx_llc_slices_init(struct platform_device *pdev,
|
||||
struct a6xx_gpu *a6xx_gpu, bool is_a7xx)
|
||||
{
|
||||
struct device_node *phandle;
|
||||
|
||||
/* No LLCC on non-RPMh (and by extension, non-GMU) SoCs */
|
||||
if (adreno_has_gmu_wrapper(&a6xx_gpu->base))
|
||||
return;
|
||||
|
||||
/*
|
||||
* There is a different programming path for A6xx targets with an
|
||||
* mmu500 attached, so detect if that is the case
|
||||
*/
|
||||
phandle = of_parse_phandle(pdev->dev.of_node, "iommus", 0);
|
||||
a6xx_gpu->have_mmu500 = (phandle &&
|
||||
of_device_is_compatible(phandle, "arm,mmu-500"));
|
||||
of_node_put(phandle);
|
||||
|
||||
if (is_a7xx || !a6xx_gpu->have_mmu500)
|
||||
a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem");
|
||||
else
|
||||
a6xx_gpu->llc_mmio = NULL;
|
||||
|
||||
a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU);
|
||||
a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW);
|
||||
|
||||
if (IS_ERR_OR_NULL(a6xx_gpu->llc_slice) && IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice))
|
||||
a6xx_gpu->llc_mmio = ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
#define GBIF_CLIENT_HALT_MASK BIT(0)
|
||||
|
|
@ -2537,6 +2440,142 @@ static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
return progress;
|
||||
}
|
||||
|
||||
static void
|
||||
perfcntr_select(struct msm_ringbuffer *ring, enum adreno_pipe pipe,
|
||||
uint32_t regidx, uint32_t *countables, uint32_t nr,
|
||||
uint32_t **reglist)
|
||||
{
|
||||
OUT_PKT4(ring, regidx, nr);
|
||||
for (unsigned i = 0; i < nr; i++)
|
||||
OUT_RING(ring, countables[i]);
|
||||
|
||||
if (!*reglist)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < nr; i++) {
|
||||
/*
|
||||
* Bitfield is in same position on a7xx, but only 2 bits..
|
||||
* which is sufficient for NONE/BR/BV:
|
||||
*/
|
||||
*(*reglist)++ = A8XX_CP_APERTURE_CNTL_HOST_PIPEID(pipe);
|
||||
*(*reglist)++ = regidx + i;
|
||||
*(*reglist)++ = countables[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
a6xx_perfcntr_configure(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
|
||||
const struct msm_perfcntr_stream *stream)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
enum adreno_pipe pipe = PIPE_NONE;
|
||||
uint32_t *reglist = NULL;
|
||||
uint32_t *reglist_sel_start;
|
||||
|
||||
if (to_adreno_gpu(gpu)->info->family >= ADRENO_7XX_GEN1) {
|
||||
WARN_ON(!a6xx_gpu->pwrup_reglist_emitted);
|
||||
|
||||
struct cpu_gpu_lock *lock = a6xx_gpu->pwrup_reglist_ptr;
|
||||
int off = (2 * lock->ifpc_list_len) +
|
||||
(2 * lock->preemption_list_len) +
|
||||
(3 * a6xx_gpu->dynamic_sel_reglist_offset);
|
||||
|
||||
reglist = (uint32_t *)&lock->regs[0];
|
||||
reglist += off;
|
||||
reglist_sel_start = reglist;
|
||||
|
||||
/* Clear any previously configured SEL reg entries: */
|
||||
lock->dynamic_list_len = a6xx_gpu->dynamic_sel_reglist_offset;
|
||||
|
||||
/*
|
||||
* Ensure CP sees the dynamic_list_len update before we
|
||||
* start modifying the SEL entries:
|
||||
*/
|
||||
dma_wmb();
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < stream->nr_groups; i++) {
|
||||
unsigned group_idx = msm_perfcntr_group_idx(stream, i);
|
||||
unsigned base = msm_perfcntr_counter_base(stream, group_idx);
|
||||
|
||||
const struct msm_perfcntr_group *group =
|
||||
&gpu->perfcntr_groups[group_idx];
|
||||
|
||||
struct msm_perfcntr_group_state *group_state =
|
||||
gpu->perfcntrs->groups[group_idx];
|
||||
|
||||
if (group->pipe != pipe) {
|
||||
pipe = group->pipe;
|
||||
|
||||
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
|
||||
|
||||
if (pipe == PIPE_BR) {
|
||||
OUT_RING(ring, CP_SET_THREAD_BR);
|
||||
} else if (pipe == PIPE_BV) {
|
||||
OUT_RING(ring, CP_SET_THREAD_BV);
|
||||
} else {
|
||||
OUT_RING(ring, CP_SET_THREAD_BOTH);
|
||||
}
|
||||
}
|
||||
|
||||
const struct msm_perfcntr_counter *counter = &group->counters[base];
|
||||
unsigned nr = group_state->allocated_counters;
|
||||
perfcntr_select(ring, pipe, counter->select_reg,
|
||||
group_state->countables, nr, ®list);
|
||||
|
||||
for (unsigned s = 0; s < ARRAY_SIZE(counter->slice_select_regs); s++) {
|
||||
if (!counter->slice_select_regs[s])
|
||||
break;
|
||||
|
||||
perfcntr_select(ring, pipe, counter->slice_select_regs[s],
|
||||
group_state->countables, nr, ®list);
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe != PIPE_NONE) {
|
||||
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
|
||||
OUT_RING(ring, CP_SET_THREAD_BOTH);
|
||||
}
|
||||
|
||||
OUT_PKT7(ring, CP_MEM_WRITE, 3);
|
||||
OUT_RING(ring, lower_32_bits(rbmemptr(ring, perfcntr_fence)));
|
||||
OUT_RING(ring, upper_32_bits(rbmemptr(ring, perfcntr_fence)));
|
||||
OUT_RING(ring, stream->sel_fence);
|
||||
|
||||
/*
|
||||
* Update the pwrup reglist size before flushing. Kgsl does a shared-
|
||||
* memory spinlock dance with SQE to avoid racing with IFPC exit. But
|
||||
* we can skip that since the ringbuffer programming will be executed
|
||||
* by SQE after dynamic reglist size is updated. So even if we lose
|
||||
* the race, the register programming in the rb will overwrite/correct
|
||||
* the SEL regs restored by SQE on IFPC exit, before sampling begins.
|
||||
*/
|
||||
if (reglist) {
|
||||
struct cpu_gpu_lock *lock = a6xx_gpu->pwrup_reglist_ptr;
|
||||
unsigned nr_regs = (reglist - reglist_sel_start) / 3;
|
||||
|
||||
/*
|
||||
* Ensure CP sees updates to the pwrup_reglist before it
|
||||
* sees the new (increased) length:
|
||||
*/
|
||||
dma_wmb();
|
||||
|
||||
/* Update dynamic reglist len to include new SEL reg programming: */
|
||||
lock->dynamic_list_len = a6xx_gpu->dynamic_sel_reglist_offset + nr_regs;
|
||||
|
||||
WARN_ON_ONCE(reglist > (uint32_t *)((uint8_t *)lock + PWRUP_REGLIST_SIZE));
|
||||
}
|
||||
|
||||
a6xx_flush_yield(gpu, ring);
|
||||
|
||||
/* Check to see if we need to start preemption */
|
||||
if (adreno_is_a8xx(to_adreno_gpu(gpu)))
|
||||
a8xx_preempt_trigger(gpu);
|
||||
else
|
||||
a6xx_preempt_trigger(gpu);
|
||||
}
|
||||
|
||||
static u32 fuse_to_supp_hw(const struct adreno_info *info, u32 fuse)
|
||||
{
|
||||
if (!info->speedbins)
|
||||
|
|
@ -2560,7 +2599,7 @@ static int a6xx_read_speedbin(struct device *dev, struct a6xx_gpu *a6xx_gpu,
|
|||
return ret;
|
||||
|
||||
if (info->quirks & ADRENO_QUIRK_SOFTFUSE) {
|
||||
*speedbin = a6xx_llc_read(a6xx_gpu, REG_A8XX_CX_MISC_SW_FUSE_FREQ_LIMIT_STATUS);
|
||||
*speedbin = a6xx_cx_misc_read(a6xx_gpu, REG_A8XX_CX_MISC_SW_FUSE_FREQ_LIMIT_STATUS);
|
||||
*speedbin = A8XX_CX_MISC_SW_FUSE_FREQ_LIMIT_STATUS_FINALFREQLIMIT(*speedbin);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2621,6 +2660,7 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
|
|||
struct platform_device *pdev = priv->gpu_pdev;
|
||||
struct adreno_platform_config *config = pdev->dev.platform_data;
|
||||
const struct adreno_info *info = config->info;
|
||||
struct device_node *phandle;
|
||||
struct a6xx_gpu *a6xx_gpu;
|
||||
struct adreno_gpu *adreno_gpu;
|
||||
struct msm_gpu *gpu;
|
||||
|
|
@ -2636,6 +2676,20 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
|
|||
adreno_gpu = &a6xx_gpu->base;
|
||||
gpu = &adreno_gpu->base;
|
||||
|
||||
if ((ADRENO_6XX_GEN1 <= config->info->family) &&
|
||||
(config->info->family <= ADRENO_6XX_GEN4)) {
|
||||
gpu->perfcntr_groups = a6xx_perfcntr_groups;
|
||||
gpu->num_perfcntr_groups = a6xx_num_perfcntr_groups;
|
||||
} else if ((ADRENO_7XX_GEN1 <= config->info->family) &&
|
||||
(config->info->family <= ADRENO_7XX_GEN3)) {
|
||||
gpu->perfcntr_groups = a7xx_perfcntr_groups;
|
||||
gpu->num_perfcntr_groups = a7xx_num_perfcntr_groups;
|
||||
} else if ((ADRENO_8XX_GEN1 <= config->info->family) &&
|
||||
(config->info->family <= ADRENO_8XX_GEN2)) {
|
||||
gpu->perfcntr_groups = a8xx_perfcntr_groups;
|
||||
gpu->num_perfcntr_groups = a8xx_num_perfcntr_groups;
|
||||
}
|
||||
|
||||
mutex_init(&a6xx_gpu->gmu.lock);
|
||||
spin_lock_init(&a6xx_gpu->aperture_lock);
|
||||
|
||||
|
|
@ -2657,6 +2711,20 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
|
|||
|
||||
a6xx_llc_slices_init(pdev, a6xx_gpu, is_a7xx);
|
||||
|
||||
/*
|
||||
* There is a different programming path for A6xx targets with an
|
||||
* mmu500 attached, so detect if that is the case
|
||||
*/
|
||||
phandle = of_parse_phandle(pdev->dev.of_node, "iommus", 0);
|
||||
a6xx_gpu->have_mmu500 = (phandle &&
|
||||
of_device_is_compatible(phandle, "arm,mmu-500"));
|
||||
of_node_put(phandle);
|
||||
|
||||
if (is_a7xx || !a6xx_gpu->have_mmu500)
|
||||
a6xx_gpu->cx_misc_mmio = msm_ioremap(pdev, "cx_mem");
|
||||
else
|
||||
a6xx_gpu->cx_misc_mmio = NULL;
|
||||
|
||||
ret = a6xx_set_supported_hw(&pdev->dev, a6xx_gpu, info);
|
||||
if (ret) {
|
||||
a6xx_llc_slices_destroy(a6xx_gpu);
|
||||
|
|
@ -2700,10 +2768,10 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
|
|||
msm_mmu_set_fault_handler(to_msm_vm(gpu->vm)->mmu, gpu,
|
||||
adreno_gpu->funcs->mmu_fault_handler);
|
||||
|
||||
ret = a6xx_calc_ubwc_config(adreno_gpu);
|
||||
if (ret) {
|
||||
adreno_gpu->ubwc_config = qcom_ubwc_config_get_data();
|
||||
if (IS_ERR(adreno_gpu->ubwc_config)) {
|
||||
a6xx_destroy(&(a6xx_gpu->base.base));
|
||||
return ERR_PTR(ret);
|
||||
return ERR_CAST(adreno_gpu->ubwc_config);
|
||||
}
|
||||
|
||||
/* Set up the preemption specific bits and pieces for each ringbuffer */
|
||||
|
|
@ -2740,6 +2808,7 @@ const struct adreno_gpu_funcs a6xx_gpu_funcs = {
|
|||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a6xx_progress,
|
||||
.sysprof_setup = a6xx_gmu_sysprof_setup,
|
||||
.perfcntr_configure = a6xx_perfcntr_configure,
|
||||
},
|
||||
.init = a6xx_gpu_init,
|
||||
.get_timestamp = a6xx_gmu_get_timestamp,
|
||||
|
|
@ -2773,6 +2842,7 @@ const struct adreno_gpu_funcs a6xx_gmuwrapper_funcs = {
|
|||
.create_private_vm = a6xx_create_private_vm,
|
||||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a6xx_progress,
|
||||
.perfcntr_configure = a6xx_perfcntr_configure,
|
||||
},
|
||||
.init = a6xx_gpu_init,
|
||||
.get_timestamp = a6xx_get_timestamp,
|
||||
|
|
@ -2809,6 +2879,7 @@ const struct adreno_gpu_funcs a7xx_gpu_funcs = {
|
|||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a6xx_progress,
|
||||
.sysprof_setup = a6xx_gmu_sysprof_setup,
|
||||
.perfcntr_configure = a6xx_perfcntr_configure,
|
||||
},
|
||||
.init = a6xx_gpu_init,
|
||||
.get_timestamp = a6xx_gmu_get_timestamp,
|
||||
|
|
@ -2838,6 +2909,9 @@ const struct adreno_gpu_funcs a8xx_gpu_funcs = {
|
|||
.create_private_vm = a6xx_create_private_vm,
|
||||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a8xx_progress,
|
||||
.sysprof_setup = a6xx_gmu_sysprof_setup,
|
||||
.perfcntr_configure = a6xx_perfcntr_configure,
|
||||
.perfcntr_flush = a8xx_perfcntr_flush,
|
||||
},
|
||||
.init = a6xx_gpu_init,
|
||||
.get_timestamp = a8xx_gmu_get_timestamp,
|
||||
|
|
|
|||
|
|
@ -21,17 +21,19 @@ struct cpu_gpu_lock {
|
|||
uint32_t cpu_req;
|
||||
uint32_t turn;
|
||||
union {
|
||||
/* a6xx: */
|
||||
struct {
|
||||
uint16_t list_length;
|
||||
uint16_t list_offset;
|
||||
};
|
||||
/* a7xx+: */
|
||||
struct {
|
||||
uint8_t ifpc_list_len;
|
||||
uint8_t preemption_list_len;
|
||||
uint16_t dynamic_list_len;
|
||||
};
|
||||
};
|
||||
uint64_t regs[62];
|
||||
uint64_t regs[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -96,13 +98,21 @@ struct a6xx_gpu {
|
|||
uint32_t *shadow;
|
||||
|
||||
struct drm_gem_object *pwrup_reglist_bo;
|
||||
#define PWRUP_REGLIST_SIZE (2 * PAGE_SIZE)
|
||||
void *pwrup_reglist_ptr;
|
||||
uint64_t pwrup_reglist_iova;
|
||||
bool pwrup_reglist_emitted;
|
||||
|
||||
/*
|
||||
* Offset of start of SEL regs appended to pwrup_reglist. This
|
||||
* is equal to lock->dynamic_list_len if no SEL regs are appended
|
||||
* to the end of the dynamic reglist.
|
||||
*/
|
||||
uint16_t dynamic_sel_reglist_offset;
|
||||
|
||||
bool has_whereami;
|
||||
|
||||
void __iomem *llc_mmio;
|
||||
void __iomem *cx_misc_mmio;
|
||||
void *llc_slice;
|
||||
void *htw_llc_slice;
|
||||
bool have_mmu500;
|
||||
|
|
@ -240,19 +250,19 @@ static inline bool a6xx_has_gbif(struct adreno_gpu *gpu)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void a6xx_llc_rmw(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 mask, u32 or)
|
||||
static inline void a6xx_cx_misc_rmw(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 mask, u32 or)
|
||||
{
|
||||
return msm_rmw(a6xx_gpu->llc_mmio + (reg << 2), mask, or);
|
||||
return msm_rmw(a6xx_gpu->cx_misc_mmio + (reg << 2), mask, or);
|
||||
}
|
||||
|
||||
static inline u32 a6xx_llc_read(struct a6xx_gpu *a6xx_gpu, u32 reg)
|
||||
static inline u32 a6xx_cx_misc_read(struct a6xx_gpu *a6xx_gpu, u32 reg)
|
||||
{
|
||||
return readl(a6xx_gpu->llc_mmio + (reg << 2));
|
||||
return readl(a6xx_gpu->cx_misc_mmio + (reg << 2));
|
||||
}
|
||||
|
||||
static inline void a6xx_llc_write(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 value)
|
||||
static inline void a6xx_cx_misc_write(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 value)
|
||||
{
|
||||
writel(value, a6xx_gpu->llc_mmio + (reg << 2));
|
||||
writel(value, a6xx_gpu->cx_misc_mmio + (reg << 2));
|
||||
}
|
||||
|
||||
#define shadowptr(_a6xx_gpu, _ring) ((_a6xx_gpu)->shadow_iova + \
|
||||
|
|
@ -271,7 +281,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
|
|||
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_gmu_sysprof_setup(struct msm_gpu *gpu);
|
||||
void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu, bool force_on);
|
||||
|
||||
void a6xx_preempt_init(struct msm_gpu *gpu);
|
||||
void a6xx_preempt_hw_init(struct msm_gpu *gpu);
|
||||
|
|
@ -317,6 +327,7 @@ void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_
|
|||
void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert);
|
||||
int a6xx_fenced_write(struct a6xx_gpu *gpu, u32 offset, u64 value, u32 mask, bool is_64b);
|
||||
void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
|
||||
void a6xx_flush_yield(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
|
||||
int a6xx_zap_shader_init(struct msm_gpu *gpu);
|
||||
|
||||
void a8xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off);
|
||||
|
|
@ -333,5 +344,6 @@ void a8xx_preempt_hw_init(struct msm_gpu *gpu);
|
|||
void a8xx_preempt_trigger(struct msm_gpu *gpu);
|
||||
void a8xx_preempt_irq(struct msm_gpu *gpu);
|
||||
bool a8xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
|
||||
void a8xx_perfcntr_flush(struct msm_gpu *gpu);
|
||||
void a8xx_recover(struct msm_gpu *gpu);
|
||||
#endif /* __A6XX_GPU_H__ */
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
|
|||
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;
|
||||
sysprof = msm_gpu_sysprof_no_perfcntr_zap(gpu);
|
||||
|
||||
if (!sysprof && !a6xx_gpu->postamble_enabled)
|
||||
preempt_prepare_postamble(a6xx_gpu);
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ void a8xx_gpu_get_slice_info(struct msm_gpu *gpu)
|
|||
return;
|
||||
}
|
||||
|
||||
slice_mask &= a6xx_llc_read(a6xx_gpu,
|
||||
slice_mask &= a6xx_cx_misc_read(a6xx_gpu,
|
||||
REG_A8XX_CX_MISC_SLICE_ENABLE_FINAL);
|
||||
|
||||
a6xx_gpu->slice_mask = slice_mask;
|
||||
|
|
@ -265,8 +265,8 @@ static void a8xx_set_cp_protect(struct msm_gpu *gpu)
|
|||
* Last span feature is only supported on PIPE specific register.
|
||||
* So update those here
|
||||
*/
|
||||
a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_CP_PROTECT_PIPE(protect->count_max), final_cfg);
|
||||
a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_CP_PROTECT_PIPE(protect->count_max), final_cfg);
|
||||
a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_CP_PROTECT_PIPE(15), final_cfg);
|
||||
a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_CP_PROTECT_PIPE(15), final_cfg);
|
||||
|
||||
a8xx_aperture_clear(gpu);
|
||||
}
|
||||
|
|
@ -275,41 +275,37 @@ static void a8xx_set_ubwc_config(struct msm_gpu *gpu)
|
|||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
const struct qcom_ubwc_cfg_data *cfg = adreno_gpu->ubwc_config;
|
||||
u32 level2_swizzling_dis = !(cfg->ubwc_swizzle & UBWC_SWIZZLE_ENABLE_LVL2);
|
||||
u32 level3_swizzling_dis = !(cfg->ubwc_swizzle & UBWC_SWIZZLE_ENABLE_LVL3);
|
||||
u32 level2_swizzling_dis = !(qcom_ubwc_swizzle(cfg) & UBWC_SWIZZLE_ENABLE_LVL2);
|
||||
u32 level3_swizzling_dis = !(qcom_ubwc_swizzle(cfg) & UBWC_SWIZZLE_ENABLE_LVL3);
|
||||
bool rgba8888_lossless = false, fp16compoptdis = false;
|
||||
bool yuvnotcomptofc = false, min_acc_len_64b = false;
|
||||
bool rgb565_predicator = false, amsbc = false;
|
||||
bool rgb565_predicator = false;
|
||||
bool amsbc = qcom_ubwc_enable_amsbc(cfg);
|
||||
bool ubwc_mode = qcom_ubwc_get_ubwc_mode(cfg);
|
||||
u32 ubwc_version = cfg->ubwc_enc_version;
|
||||
u32 hbb, hbb_hi, hbb_lo, mode = 1;
|
||||
u32 hbb, hbb_hi, hbb_lo, mode;
|
||||
u8 uavflagprd_inv = 2;
|
||||
|
||||
switch (ubwc_version) {
|
||||
case UBWC_6_0:
|
||||
yuvnotcomptofc = true;
|
||||
mode = 5;
|
||||
break;
|
||||
case UBWC_5_0:
|
||||
amsbc = true;
|
||||
rgb565_predicator = true;
|
||||
mode = 4;
|
||||
break;
|
||||
case UBWC_4_0:
|
||||
amsbc = true;
|
||||
rgb565_predicator = true;
|
||||
fp16compoptdis = true;
|
||||
rgba8888_lossless = true;
|
||||
mode = 2;
|
||||
break;
|
||||
case UBWC_3_0:
|
||||
amsbc = true;
|
||||
mode = 1;
|
||||
break;
|
||||
default:
|
||||
if (ubwc_version > UBWC_6_0)
|
||||
dev_err(&gpu->pdev->dev, "Unknown UBWC version: 0x%x\n", ubwc_version);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ubwc_version == UBWC_6_0)
|
||||
yuvnotcomptofc = true;
|
||||
|
||||
if (ubwc_version < UBWC_5_0 &&
|
||||
ubwc_version >= UBWC_4_0)
|
||||
rgba8888_lossless = true;
|
||||
|
||||
if (ubwc_version < UBWC_4_3)
|
||||
fp16compoptdis = true;
|
||||
|
||||
if (cfg->ubwc_enc_version >= UBWC_4_0)
|
||||
rgb565_predicator = true;
|
||||
|
||||
if (ubwc_version < UBWC_3_0)
|
||||
dev_err(&gpu->pdev->dev, "Unsupported UBWC version: 0x%x\n", ubwc_version);
|
||||
|
||||
mode = qcom_ubwc_version_tag(cfg);
|
||||
|
||||
/*
|
||||
* We subtract 13 from the highest bank bit (13 is the minimum value
|
||||
|
|
@ -468,6 +464,7 @@ static void a8xx_patch_pwrup_reglist(struct msm_gpu *gpu)
|
|||
}
|
||||
|
||||
lock->dynamic_list_len = dyn_pwrup_reglist_count;
|
||||
a6xx_gpu->dynamic_sel_reglist_offset = dyn_pwrup_reglist_count;
|
||||
|
||||
done:
|
||||
a8xx_aperture_clear(gpu);
|
||||
|
|
@ -488,15 +485,7 @@ static int a8xx_preempt_start(struct msm_gpu *gpu)
|
|||
|
||||
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);
|
||||
a6xx_flush_yield(gpu, ring);
|
||||
|
||||
return a8xx_idle(gpu, ring) ? 0 : -EINVAL;
|
||||
}
|
||||
|
|
@ -849,7 +838,7 @@ static int hw_init(struct msm_gpu *gpu)
|
|||
*/
|
||||
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
|
||||
|
||||
if (!ret && (refcount_read(&gpu->sysprof_active) > 1)) {
|
||||
if (!ret && msm_gpu_sysprof_no_perfcntr_zap(gpu)) {
|
||||
ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
if (!ret)
|
||||
set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
|
||||
|
|
@ -886,17 +875,22 @@ void a8xx_recover(struct msm_gpu *gpu)
|
|||
|
||||
adreno_dump_info(gpu);
|
||||
|
||||
if (hang_debug)
|
||||
a8xx_dump(gpu);
|
||||
|
||||
/*
|
||||
* To handle recovery specific sequences during the rpm suspend we are
|
||||
* about to trigger
|
||||
*/
|
||||
a6xx_gpu->hung = true;
|
||||
|
||||
/* Halt SQE first */
|
||||
gpu_write(gpu, REG_A8XX_CP_SQE_CNTL, 3);
|
||||
if (adreno_gpu->funcs->gx_is_on(adreno_gpu)) {
|
||||
/*
|
||||
* Sometimes crashstate capture is skipped, so SQE should be
|
||||
* halted here again
|
||||
*/
|
||||
gpu_write(gpu, REG_A8XX_CP_SQE_CNTL, 3);
|
||||
|
||||
if (hang_debug)
|
||||
a8xx_dump(gpu);
|
||||
}
|
||||
|
||||
pm_runtime_dont_use_autosuspend(&gpu->pdev->dev);
|
||||
|
||||
|
|
@ -1353,3 +1347,23 @@ bool a8xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void a8xx_perfcntr_flush(struct msm_gpu *gpu)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* Flush delta counters (both perf counters and pipe stats) present in
|
||||
* RBBM_S and RBBM_US to perf RAM logic to get the latest data.
|
||||
*/
|
||||
gpu_write(gpu, REG_A8XX_RBBM_PERFCTR_FLUSH_HOST_CMD, BIT(0));
|
||||
gpu_write(gpu, REG_A8XX_RBBM_SLICE_PERFCTR_FLUSH_HOST_CMD, BIT(0));
|
||||
|
||||
/* Ensure all writes are posted before polling status register */
|
||||
wmb();
|
||||
|
||||
if (gpu_poll_timeout(gpu, REG_A8XX_RBBM_PERFCTR_FLUSH_HOST_STATUS, val,
|
||||
val & BIT(0), 100, 100 * 1000)) {
|
||||
dev_err(&gpu->pdev->dev, "Perfcounter flush timed out: status=0x%08x\n", val);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ void a8xx_preempt_trigger(struct msm_gpu *gpu)
|
|||
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;
|
||||
sysprof = msm_gpu_sysprof_no_perfcntr_zap(gpu);
|
||||
|
||||
if (!sysprof && !a6xx_gpu->postamble_enabled)
|
||||
preempt_prepare_postamble(a6xx_gpu);
|
||||
|
|
|
|||
|
|
@ -307,8 +307,10 @@ MODULE_DEVICE_TABLE(of, dt_match);
|
|||
static int adreno_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct msm_gpu *gpu = dev_to_gpu(dev);
|
||||
|
||||
return gpu->funcs->pm_resume(gpu);
|
||||
int ret = gpu->funcs->pm_resume(gpu);
|
||||
if (!ret)
|
||||
ret = msm_perfcntr_resume(gpu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adreno_runtime_suspend(struct device *dev)
|
||||
|
|
@ -322,6 +324,8 @@ static int adreno_runtime_suspend(struct device *dev)
|
|||
*/
|
||||
WARN_ON_ONCE(gpu->active_submits);
|
||||
|
||||
msm_perfcntr_suspend(gpu);
|
||||
|
||||
return gpu->funcs->pm_suspend(gpu);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -434,12 +434,12 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx,
|
|||
case MSM_PARAM_UBWC_SWIZZLE:
|
||||
if (!adreno_gpu->ubwc_config)
|
||||
return UERR(ENOENT, drm, "no UBWC on this platform");
|
||||
*value = adreno_gpu->ubwc_config->ubwc_swizzle;
|
||||
*value = qcom_ubwc_swizzle(adreno_gpu->ubwc_config);
|
||||
return 0;
|
||||
case MSM_PARAM_MACROTILE_MODE:
|
||||
if (!adreno_gpu->ubwc_config)
|
||||
return UERR(ENOENT, drm, "no UBWC on this platform");
|
||||
*value = adreno_gpu->ubwc_config->macrotile_mode;
|
||||
*value = qcom_ubwc_macrotile_mode(adreno_gpu->ubwc_config);
|
||||
return 0;
|
||||
case MSM_PARAM_UCHE_TRAP_BASE:
|
||||
*value = adreno_gpu->uche_trap_base;
|
||||
|
|
@ -500,7 +500,7 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_context *ctx,
|
|||
return 0;
|
||||
}
|
||||
case MSM_PARAM_SYSPROF:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
if (!perfmon_capable())
|
||||
return UERR(EPERM, drm, "invalid permissions");
|
||||
return msm_context_set_sysprof(ctx, gpu, value);
|
||||
case MSM_PARAM_EN_VM_BIND:
|
||||
|
|
@ -708,11 +708,10 @@ void adreno_recover(struct msm_gpu *gpu)
|
|||
struct drm_device *dev = gpu->dev;
|
||||
int ret;
|
||||
|
||||
// XXX pm-runtime?? we *need* the device to be off after this
|
||||
// so maybe continuing to call ->pm_suspend/resume() is better?
|
||||
|
||||
msm_perfcntr_suspend(gpu);
|
||||
gpu->funcs->pm_suspend(gpu);
|
||||
gpu->funcs->pm_resume(gpu);
|
||||
msm_perfcntr_resume(gpu);
|
||||
|
||||
ret = msm_gpu_hw_init(gpu);
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -236,12 +236,7 @@ struct adreno_gpu {
|
|||
/* firmware: */
|
||||
const struct firmware *fw[ADRENO_FW_MAX];
|
||||
|
||||
/*
|
||||
* The migration to the central UBWC config db is still in flight - keep
|
||||
* a copy containing some local fixups until that's done.
|
||||
*/
|
||||
const struct qcom_ubwc_cfg_data *ubwc_config;
|
||||
struct qcom_ubwc_cfg_data _ubwc_config;
|
||||
|
||||
/*
|
||||
* Register offsets are different between some GPUs.
|
||||
|
|
@ -592,6 +587,11 @@ static inline int adreno_is_a8xx(struct adreno_gpu *gpu)
|
|||
return gpu->info->family >= ADRENO_8XX_GEN1;
|
||||
}
|
||||
|
||||
static inline int adreno_is_a810(struct adreno_gpu *gpu)
|
||||
{
|
||||
return gpu->info->chip_ids[0] == 0x44010000;
|
||||
}
|
||||
|
||||
static inline int adreno_is_x285(struct adreno_gpu *gpu)
|
||||
{
|
||||
return gpu->info->chip_ids[0] == 0x44070001;
|
||||
|
|
|
|||
279
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_2_milos.h
Normal file
279
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_2_milos.h
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2026, Luca Weiss <luca.weiss@fairphone.com>
|
||||
*/
|
||||
|
||||
#ifndef _DPU_10_2_MILOS_H
|
||||
#define _DPU_10_2_MILOS_H
|
||||
|
||||
static const struct dpu_caps milos_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0x7,
|
||||
.has_src_split = true,
|
||||
.has_dim_layer = true,
|
||||
.has_idle_pc = true,
|
||||
.has_3d_merge = true,
|
||||
.max_linewidth = 8192,
|
||||
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg milos_mdp = {
|
||||
.name = "top_0",
|
||||
.base = 0, .len = 0x494,
|
||||
.clk_ctrls = {
|
||||
[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_ctl_cfg milos_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x15000, .len = 0x1000,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
|
||||
}, {
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x16000, .len = 0x1000,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
|
||||
}, {
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x17000, .len = 0x1000,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
|
||||
}, {
|
||||
.name = "ctl_3", .id = CTL_3,
|
||||
.base = 0x18000, .len = 0x1000,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg milos_sspp[] = {
|
||||
{
|
||||
.name = "sspp_0", .id = SSPP_VIG0,
|
||||
.base = 0x4000, .len = 0x344,
|
||||
.features = VIG_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_vig_sblk_qseed3_3_3,
|
||||
.xin_id = 0,
|
||||
.type = SSPP_TYPE_VIG,
|
||||
}, {
|
||||
.name = "sspp_8", .id = SSPP_DMA0,
|
||||
.base = 0x24000, .len = 0x344,
|
||||
.features = DMA_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 1,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
}, {
|
||||
.name = "sspp_9", .id = SSPP_DMA1,
|
||||
.base = 0x26000, .len = 0x344,
|
||||
.features = DMA_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 5,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
}, {
|
||||
.name = "sspp_10", .id = SSPP_DMA2,
|
||||
.base = 0x28000, .len = 0x344,
|
||||
.features = DMA_SDM845_MASK_SDMA,
|
||||
.sblk = &dpu_dma_sblk,
|
||||
.xin_id = 9,
|
||||
.type = SSPP_TYPE_DMA,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg milos_lm[] = {
|
||||
{
|
||||
.name = "lm_0", .id = LM_0,
|
||||
.base = 0x44000, .len = 0x400,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.pingpong = PINGPONG_0,
|
||||
.dspp = DSPP_0,
|
||||
}, {
|
||||
.name = "lm_2", .id = LM_2,
|
||||
.base = 0x46000, .len = 0x400,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_3,
|
||||
.pingpong = PINGPONG_2,
|
||||
}, {
|
||||
.name = "lm_3", .id = LM_3,
|
||||
.base = 0x47000, .len = 0x400,
|
||||
.features = MIXER_MSM8998_MASK,
|
||||
.sblk = &sdm845_lm_sblk,
|
||||
.lm_pair = LM_2,
|
||||
.pingpong = PINGPONG_3,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg milos_dspp[] = {
|
||||
{
|
||||
.name = "dspp_0", .id = DSPP_0,
|
||||
.base = 0x54000, .len = 0x1800,
|
||||
.sblk = &sdm845_dspp_sblk,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_pingpong_cfg milos_pp[] = {
|
||||
{
|
||||
.name = "pingpong_0", .id = PINGPONG_0,
|
||||
.base = 0x69000, .len = 0,
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
|
||||
}, {
|
||||
.name = "pingpong_2", .id = PINGPONG_2,
|
||||
.base = 0x6b000, .len = 0,
|
||||
.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,
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
.merge_3d = MERGE_3D_1,
|
||||
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
|
||||
}, {
|
||||
.name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
|
||||
.base = 0x66000, .len = 0,
|
||||
.sblk = &sc7280_pp_sblk,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_merge_3d_cfg milos_merge_3d[] = {
|
||||
{
|
||||
.name = "merge_3d_1", .id = MERGE_3D_1,
|
||||
.base = 0x4f000, .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 milos_dsc[] = {
|
||||
{
|
||||
.name = "dce_0_0", .id = DSC_0,
|
||||
.base = 0x80000, .len = 0x6,
|
||||
.features = BIT(DPU_DSC_NATIVE_42x_EN),
|
||||
.sblk = &milos_dsc_sblk_0,
|
||||
}, {
|
||||
.name = "dce_0_1", .id = DSC_1,
|
||||
.base = 0x80000, .len = 0x6,
|
||||
.features = BIT(DPU_DSC_NATIVE_42x_EN),
|
||||
.sblk = &milos_dsc_sblk_1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_wb_cfg milos_wb[] = {
|
||||
{
|
||||
.name = "wb_2", .id = WB_2,
|
||||
.base = 0x65000, .len = 0x2c8,
|
||||
.features = WB_SDM845_MASK,
|
||||
.format_list = wb2_formats_rgb_yuv,
|
||||
.num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
|
||||
.xin_id = 6,
|
||||
.maxlinewidth = 4096,
|
||||
.intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_cwb_cfg milos_cwb[] = {
|
||||
{
|
||||
.name = "cwb_0", .id = CWB_0,
|
||||
.base = 0x66200, .len = 0x8,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_intf_cfg milos_intf[] = {
|
||||
{
|
||||
.name = "intf_0", .id = INTF_0,
|
||||
.base = 0x34000, .len = 0x300,
|
||||
.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,
|
||||
.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_3", .id = INTF_3,
|
||||
.base = 0x37000, .len = 0x300,
|
||||
.type = INTF_DP,
|
||||
.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),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg milos_perf_data = {
|
||||
.max_bw_low = 7100000,
|
||||
.max_bw_high = 9800000,
|
||||
.min_core_ib = 2500000,
|
||||
.min_llcc_ib = 0,
|
||||
.min_dram_ib = 1600000,
|
||||
.min_prefill_lines = 40,
|
||||
/* FIXME: lut tables */
|
||||
.danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0},
|
||||
.safe_lut_tbl = {0xff00, 0xfff0, 0x0fff},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(sc7180_qos_linear),
|
||||
.entries = sc7180_qos_linear
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(sc7180_qos_macrotile),
|
||||
.entries = sc7180_qos_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(sc7180_qos_nrt),
|
||||
.entries = sc7180_qos_nrt
|
||||
},
|
||||
/* TODO: macrotile-qseed is different from macrotile */
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 105,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_mdss_version milos_mdss_ver = {
|
||||
.core_major_ver = 10,
|
||||
.core_minor_ver = 2,
|
||||
};
|
||||
|
||||
const struct dpu_mdss_cfg dpu_milos_cfg = {
|
||||
.mdss_ver = &milos_mdss_ver,
|
||||
.caps = &milos_dpu_caps,
|
||||
.mdp = &milos_mdp,
|
||||
.cdm = &dpu_cdm_5_x,
|
||||
.ctl_count = ARRAY_SIZE(milos_ctl),
|
||||
.ctl = milos_ctl,
|
||||
.sspp_count = ARRAY_SIZE(milos_sspp),
|
||||
.sspp = milos_sspp,
|
||||
.mixer_count = ARRAY_SIZE(milos_lm),
|
||||
.mixer = milos_lm,
|
||||
.dspp_count = ARRAY_SIZE(milos_dspp),
|
||||
.dspp = milos_dspp,
|
||||
.pingpong_count = ARRAY_SIZE(milos_pp),
|
||||
.pingpong = milos_pp,
|
||||
.dsc_count = ARRAY_SIZE(milos_dsc),
|
||||
.dsc = milos_dsc,
|
||||
.merge_3d_count = ARRAY_SIZE(milos_merge_3d),
|
||||
.merge_3d = milos_merge_3d,
|
||||
.wb_count = ARRAY_SIZE(milos_wb),
|
||||
.wb = milos_wb,
|
||||
.cwb_count = ARRAY_SIZE(milos_cwb),
|
||||
.cwb = milos_cwb,
|
||||
.intf_count = ARRAY_SIZE(milos_intf),
|
||||
.intf = milos_intf,
|
||||
.vbif = &milos_vbif,
|
||||
.perf = &milos_perf_data,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -454,6 +454,16 @@ static const struct dpu_dsc_sub_blks dsc_sblk_1 = {
|
|||
.ctl = {.name = "ctl", .base = 0xF80, .len = 0x10},
|
||||
};
|
||||
|
||||
static const struct dpu_dsc_sub_blks milos_dsc_sblk_0 = {
|
||||
.enc = {.name = "enc", .base = 0x100, .len = 0x100},
|
||||
.ctl = {.name = "ctl", .base = 0xF00, .len = 0x80},
|
||||
};
|
||||
|
||||
static const struct dpu_dsc_sub_blks milos_dsc_sblk_1 = {
|
||||
.enc = {.name = "enc", .base = 0x200, .len = 0x100},
|
||||
.ctl = {.name = "ctl", .base = 0xF80, .len = 0x80},
|
||||
};
|
||||
|
||||
static const struct dpu_dsc_sub_blks sm8750_dsc_sblk_0 = {
|
||||
.enc = {.name = "enc", .base = 0x100, .len = 0x100},
|
||||
.ctl = {.name = "ctl", .base = 0xF00, .len = 0x24},
|
||||
|
|
@ -513,6 +523,23 @@ static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg milos_vbif = {
|
||||
.len = 0x1074,
|
||||
.features = BIT(DPU_VBIF_QOS_REMAP),
|
||||
.xin_halt_timeout = 0x4000,
|
||||
.qos_rp_remap_size = 0x40,
|
||||
.qos_rt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(sdm845_rt_pri_lvl),
|
||||
.priority_lvl = sdm845_rt_pri_lvl,
|
||||
},
|
||||
.qos_nrt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(sdm845_nrt_pri_lvl),
|
||||
.priority_lvl = sdm845_nrt_pri_lvl,
|
||||
},
|
||||
.memtype_count = 16,
|
||||
.memtype = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg msm8996_vbif = {
|
||||
.len = 0x1040,
|
||||
.default_ot_rd_limit = 32,
|
||||
|
|
@ -754,6 +781,8 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
|
|||
#include "catalog/dpu_9_2_x1e80100.h"
|
||||
|
||||
#include "catalog/dpu_10_0_sm8650.h"
|
||||
#include "catalog/dpu_10_2_milos.h"
|
||||
|
||||
#include "catalog/dpu_12_0_sm8750.h"
|
||||
#include "catalog/dpu_12_2_glymur.h"
|
||||
#include "catalog/dpu_12_4_eliza.h"
|
||||
|
|
|
|||
|
|
@ -766,6 +766,7 @@ struct dpu_mdss_cfg {
|
|||
extern const struct dpu_mdss_cfg dpu_eliza_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_glymur_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_kaanapali_cfg;
|
||||
extern const struct dpu_mdss_cfg dpu_milos_cfg;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -310,34 +310,35 @@ void dpu_hw_setup_format_impl(struct dpu_sw_pipe *pipe, const struct msm_format
|
|||
|
||||
if (fmt->fetch_mode != MDP_FETCH_LINEAR) {
|
||||
u32 hbb = ctx->ubwc->highest_bank_bit - 13;
|
||||
u32 ctrl_val;
|
||||
u32 ctrl_val = 0;
|
||||
|
||||
if (MSM_FORMAT_IS_UBWC(fmt))
|
||||
opmode |= MDSS_MDP_OP_BWC_EN;
|
||||
src_format |= (fmt->fetch_mode & 3) << 30; /*FRAME_FORMAT */
|
||||
|
||||
if (ctx->ubwc->ubwc_enc_version == UBWC_1_0) {
|
||||
fast_clear = fmt->alpha_enable ? BIT(31) : 0;
|
||||
ctrl_val = fast_clear | (ctx->ubwc->ubwc_swizzle & 0x1) |
|
||||
BIT(8) | (hbb << 4);
|
||||
} else if (ctx->ubwc->ubwc_enc_version == UBWC_2_0) {
|
||||
fast_clear = fmt->alpha_enable ? BIT(31) : 0;
|
||||
ctrl_val = fast_clear | ctx->ubwc->ubwc_swizzle | (hbb << 4);
|
||||
} else if (ctx->ubwc->ubwc_enc_version == UBWC_3_0) {
|
||||
ctrl_val = BIT(30) | (ctx->ubwc->ubwc_swizzle) | (hbb << 4);
|
||||
} else if (ctx->ubwc->ubwc_enc_version == UBWC_4_0) {
|
||||
ctrl_val = MSM_FORMAT_IS_YUV(fmt) ? 0 : BIT(30);
|
||||
} else if (ctx->ubwc->ubwc_enc_version <= UBWC_6_0) {
|
||||
if (MSM_FORMAT_IS_YUV(fmt))
|
||||
ctrl_val = 0;
|
||||
else if (MSM_FORMAT_IS_DX(fmt)) /* or FP16, but it's unsupported */
|
||||
if (ctx->ubwc->ubwc_enc_version > UBWC_6_0) {
|
||||
DRM_WARN_ONCE("Unsupported UBWC version %x\n", ctx->ubwc->ubwc_enc_version);
|
||||
} else if (ctx->ubwc->ubwc_enc_version >= UBWC_5_0) {
|
||||
if (!MSM_FORMAT_IS_YUV(fmt)) {
|
||||
ctrl_val = BIT(30);
|
||||
else
|
||||
ctrl_val = BIT(30) | BIT(31);
|
||||
if (!MSM_FORMAT_IS_DX(fmt)) /* and not FP16, but it's unsupported */
|
||||
ctrl_val |= BIT(31);
|
||||
}
|
||||
/* SDE also sets bits for lossy formats, but we don't support them yet */
|
||||
} else if (ctx->ubwc->ubwc_enc_version >= UBWC_4_0) {
|
||||
ctrl_val = MSM_FORMAT_IS_YUV(fmt) ? 0 : BIT(30);
|
||||
} else if (ctx->ubwc->ubwc_enc_version >= UBWC_3_0) {
|
||||
ctrl_val = BIT(30) | qcom_ubwc_swizzle(ctx->ubwc) | (hbb << 4);
|
||||
} else if (ctx->ubwc->ubwc_enc_version >= UBWC_2_0) {
|
||||
fast_clear = fmt->alpha_enable ? BIT(31) : 0;
|
||||
ctrl_val = fast_clear | qcom_ubwc_swizzle(ctx->ubwc) | (hbb << 4);
|
||||
} else if (ctx->ubwc->ubwc_enc_version >= UBWC_1_0) {
|
||||
fast_clear = fmt->alpha_enable ? BIT(31) : 0;
|
||||
ctrl_val = fast_clear |
|
||||
(qcom_ubwc_swizzle(ctx->ubwc) & UBWC_SWIZZLE_ENABLE_LVL1) |
|
||||
BIT(8) | (hbb << 4);
|
||||
} else {
|
||||
DRM_WARN_ONCE("Unsupported UBWC version %x\n", ctx->ubwc->ubwc_enc_version);
|
||||
ctrl_val = 0;
|
||||
}
|
||||
|
||||
DPU_REG_WRITE(c, ubwc_ctrl_off, ctrl_val);
|
||||
|
|
|
|||
|
|
@ -1483,6 +1483,7 @@ static const struct of_device_id dpu_dt_match[] = {
|
|||
{ .compatible = "qcom,eliza-dpu", .data = &dpu_eliza_cfg, },
|
||||
{ .compatible = "qcom,glymur-dpu", .data = &dpu_glymur_cfg, },
|
||||
{ .compatible = "qcom,kaanapali-dpu", .data = &dpu_kaanapali_cfg, },
|
||||
{ .compatible = "qcom,milos-dpu", .data = &dpu_milos_cfg, },
|
||||
{ .compatible = "qcom,msm8917-mdp5", .data = &dpu_msm8917_cfg, },
|
||||
{ .compatible = "qcom,msm8937-mdp5", .data = &dpu_msm8937_cfg, },
|
||||
{ .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, },
|
||||
|
|
|
|||
|
|
@ -1781,8 +1781,7 @@ static bool dpu_plane_format_mod_supported(struct drm_plane *plane,
|
|||
uint32_t format, uint64_t modifier)
|
||||
{
|
||||
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
|
||||
bool has_no_ubwc = (dpu_kms->mdss->ubwc_enc_version == 0) &&
|
||||
(dpu_kms->mdss->ubwc_dec_version == 0);
|
||||
bool has_no_ubwc = (dpu_kms->mdss->ubwc_enc_version == 0);
|
||||
|
||||
if (modifier == DRM_FORMAT_MOD_LINEAR)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2583,22 +2583,6 @@ void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl)
|
|||
phy_init(phy);
|
||||
}
|
||||
|
||||
void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl)
|
||||
{
|
||||
struct msm_dp_ctrl_private *ctrl;
|
||||
struct phy *phy;
|
||||
|
||||
ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
|
||||
phy = ctrl->phy;
|
||||
|
||||
msm_dp_ctrl_mainlink_disable(ctrl);
|
||||
|
||||
dev_pm_opp_set_rate(ctrl->dev, 0);
|
||||
msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
|
||||
|
||||
phy_power_off(phy);
|
||||
}
|
||||
|
||||
void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl)
|
||||
{
|
||||
struct msm_dp_ctrl_private *ctrl;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ struct phy;
|
|||
int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl);
|
||||
int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train);
|
||||
void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl);
|
||||
void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl);
|
||||
void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl);
|
||||
void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl);
|
||||
irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -16,12 +16,11 @@ struct msm_dp {
|
|||
struct platform_device *pdev;
|
||||
struct drm_connector *connector;
|
||||
struct drm_bridge *next_bridge;
|
||||
bool link_ready;
|
||||
struct drm_bridge *bridge;
|
||||
bool audio_enabled;
|
||||
bool power_on;
|
||||
unsigned int connector_type;
|
||||
bool is_edp;
|
||||
bool internal_hpd;
|
||||
|
||||
struct msm_dp_audio *msm_dp_audio;
|
||||
bool psr_supported;
|
||||
|
|
|
|||
|
|
@ -15,56 +15,6 @@
|
|||
#include "dp_audio.h"
|
||||
#include "dp_drm.h"
|
||||
|
||||
/**
|
||||
* msm_dp_bridge_detect - callback to determine if connector is connected
|
||||
* @bridge: Pointer to drm bridge structure
|
||||
* @connector: Pointer to drm connector structure
|
||||
* Returns: Bridge's 'is connected' status
|
||||
*/
|
||||
static enum drm_connector_status
|
||||
msm_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)
|
||||
{
|
||||
struct msm_dp *dp;
|
||||
|
||||
dp = to_dp_bridge(bridge)->msm_dp_display;
|
||||
|
||||
drm_dbg_dp(dp->drm_dev, "link_ready = %s\n",
|
||||
str_true_false(dp->link_ready));
|
||||
|
||||
return (dp->link_ready) ? connector_status_connected :
|
||||
connector_status_disconnected;
|
||||
}
|
||||
|
||||
static int msm_dp_bridge_atomic_check(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct msm_dp *dp;
|
||||
|
||||
dp = to_dp_bridge(bridge)->msm_dp_display;
|
||||
|
||||
drm_dbg_dp(dp->drm_dev, "link_ready = %s\n",
|
||||
str_true_false(dp->link_ready));
|
||||
|
||||
/*
|
||||
* There is no protection in the DRM framework to check if the display
|
||||
* pipeline has been already disabled before trying to disable it again.
|
||||
* Hence if the sink is unplugged, the pipeline gets disabled, but the
|
||||
* crtc->active is still true. Any attempt to set the mode or manually
|
||||
* disable this encoder will result in the crash.
|
||||
*
|
||||
* TODO: add support for telling the DRM subsystem that the pipeline is
|
||||
* disabled by the hardware and thus all access to it should be forbidden.
|
||||
* After that this piece of code can be removed.
|
||||
*/
|
||||
if (bridge->ops & DRM_BRIDGE_OP_HPD)
|
||||
return (dp->link_ready) ? 0 : -ENOTCONN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* msm_dp_bridge_get_modes - callback to add drm modes via drm_mode_probed_add()
|
||||
* @bridge: Poiner to drm bridge
|
||||
|
|
@ -82,12 +32,10 @@ static int msm_dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connect
|
|||
dp = to_dp_bridge(bridge)->msm_dp_display;
|
||||
|
||||
/* pluggable case assumes EDID is read when HPD */
|
||||
if (dp->link_ready) {
|
||||
rc = msm_dp_display_get_modes(dp);
|
||||
if (rc <= 0) {
|
||||
DRM_ERROR("failed to get DP sink modes, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
rc = msm_dp_display_get_modes(dp);
|
||||
if (rc <= 0) {
|
||||
DRM_ERROR("failed to get DP sink modes, rc=%d\n", rc);
|
||||
return rc;
|
||||
} else {
|
||||
drm_dbg_dp(connector->dev, "No sink connected\n");
|
||||
}
|
||||
|
|
@ -112,7 +60,6 @@ static const struct drm_bridge_funcs msm_dp_bridge_ops = {
|
|||
.mode_valid = msm_dp_bridge_mode_valid,
|
||||
.get_modes = msm_dp_bridge_get_modes,
|
||||
.detect = msm_dp_bridge_detect,
|
||||
.atomic_check = msm_dp_bridge_atomic_check,
|
||||
.hpd_enable = msm_dp_bridge_hpd_enable,
|
||||
.hpd_disable = msm_dp_bridge_hpd_disable,
|
||||
.hpd_notify = msm_dp_bridge_hpd_notify,
|
||||
|
|
@ -360,6 +307,8 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
msm_dp_display->bridge = bridge;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
|
|||
struct drm_encoder *encoder,
|
||||
bool yuv_supported);
|
||||
|
||||
enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge,
|
||||
struct drm_connector *connector);
|
||||
void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
struct drm_atomic_commit *state);
|
||||
void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
|
||||
|
|
|
|||
|
|
@ -293,6 +293,14 @@ int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel,
|
|||
return rc;
|
||||
}
|
||||
|
||||
void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
drm_edid_connector_update(connector, NULL);
|
||||
drm_edid_free(msm_dp_panel->drm_edid);
|
||||
msm_dp_panel->drm_edid = NULL;
|
||||
}
|
||||
|
||||
u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel,
|
||||
u32 mode_edid_bpp, u32 mode_pclk_khz)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel);
|
|||
int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en);
|
||||
int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel,
|
||||
struct drm_connector *connector);
|
||||
void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel,
|
||||
struct drm_connector *connector);
|
||||
u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp,
|
||||
u32 mode_pclk_khz);
|
||||
int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel,
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@
|
|||
#define DP_DP_IRQ_HPD_INT_ACK (0x00000002)
|
||||
#define DP_DP_HPD_REPLUG_INT_ACK (0x00000004)
|
||||
#define DP_DP_HPD_UNPLUG_INT_ACK (0x00000008)
|
||||
#define DP_DP_HPD_STATE_STATUS_BITS_MASK (0x0000000F)
|
||||
#define DP_DP_HPD_STATE_STATUS_BITS_SHIFT (0x1C)
|
||||
#define DP_DP_HPD_STATE_STATUS_BITS_MASK (0x00000007)
|
||||
#define DP_DP_HPD_STATE_STATUS_BITS_SHIFT (0x1D)
|
||||
|
||||
#define REG_DP_DP_HPD_INT_MASK (0x0000000C)
|
||||
#define DP_DP_HPD_PLUG_INT_MASK (0x00000001)
|
||||
|
|
|
|||
|
|
@ -571,6 +571,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
|
|||
.data = &dsi_phy_5nm_8350_cfgs },
|
||||
{ .compatible = "qcom,sm8450-dsi-phy-5nm",
|
||||
.data = &dsi_phy_5nm_8450_cfgs },
|
||||
{ .compatible = "qcom,milos-dsi-phy-4nm",
|
||||
.data = &dsi_phy_4nm_milos_cfgs },
|
||||
{ .compatible = "qcom,sm8550-dsi-phy-4nm",
|
||||
.data = &dsi_phy_4nm_8550_cfgs },
|
||||
{ .compatible = "qcom,sm8650-dsi-phy-4nm",
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
|
|||
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_4nm_milos_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs;
|
||||
|
|
|
|||
|
|
@ -1436,6 +1436,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs = {
|
|||
.quirks = DSI_PHY_7NM_QUIRK_V5_2,
|
||||
};
|
||||
|
||||
const struct msm_dsi_phy_cfg dsi_phy_4nm_milos_cfgs = {
|
||||
.has_phy_lane = true,
|
||||
.regulator_data = dsi_phy_7nm_98000uA_regulators,
|
||||
.num_regulators = ARRAY_SIZE(dsi_phy_7nm_98000uA_regulators),
|
||||
.ops = {
|
||||
.enable = dsi_7nm_phy_enable,
|
||||
.disable = dsi_7nm_phy_disable,
|
||||
.pll_init = dsi_pll_7nm_init,
|
||||
.save_pll_state = dsi_7nm_pll_save_state,
|
||||
.restore_pll_state = dsi_7nm_pll_restore_state,
|
||||
.set_continuous_clock = dsi_7nm_set_continuous_clock,
|
||||
},
|
||||
.min_pll_rate = 600000000UL,
|
||||
#ifdef CONFIG_64BIT
|
||||
.max_pll_rate = 5000000000UL,
|
||||
#else
|
||||
.max_pll_rate = ULONG_MAX,
|
||||
#endif
|
||||
.io_start = { 0xae95000 },
|
||||
.num_dsi_phy = 1,
|
||||
.quirks = DSI_PHY_7NM_QUIRK_V5_2,
|
||||
};
|
||||
|
||||
const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs = {
|
||||
.has_phy_lane = true,
|
||||
.regulator_data = dsi_phy_7nm_98400uA_regulators,
|
||||
|
|
|
|||
|
|
@ -344,12 +344,6 @@ static int late_init_minor(struct drm_minor *minor)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = msm_perf_debugfs_init(minor);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev->dev, "could not install perf debugfs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_op
|
|||
|
||||
msm_gem_shrinker_cleanup(ddev);
|
||||
|
||||
msm_perf_debugfs_cleanup(priv);
|
||||
msm_rd_debugfs_cleanup(priv);
|
||||
|
||||
if (priv->kms)
|
||||
|
|
@ -801,6 +800,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
|
|||
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(MSM_VM_BIND, msm_ioctl_vm_bind, DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(MSM_PERFCNTR_CONFIG, msm_ioctl_perfcntr_config, DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
static void msm_show_fdinfo(struct drm_printer *p, struct drm_file *file)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ struct msm_gpu;
|
|||
struct msm_mmu;
|
||||
struct msm_mdss;
|
||||
struct msm_rd_state;
|
||||
struct msm_perf_state;
|
||||
struct msm_gem_submit;
|
||||
struct msm_fence_context;
|
||||
struct msm_disp_state;
|
||||
|
|
@ -89,7 +88,6 @@ struct msm_drm_private {
|
|||
|
||||
struct msm_rd_state *rd; /* debugfs to dump all submits */
|
||||
struct msm_rd_state *hangrd; /* debugfs to dump hanging submits */
|
||||
struct msm_perf_state *perf;
|
||||
|
||||
/**
|
||||
* total_mem: Total/global amount of memory backing GEM objects.
|
||||
|
|
@ -230,6 +228,14 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|||
int msm_ioctl_vm_bind(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
|
||||
int msm_perfcntr_resume(struct msm_gpu *gpu);
|
||||
void msm_perfcntr_suspend(struct msm_gpu *gpu);
|
||||
int msm_ioctl_perfcntr_config(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
|
||||
struct msm_perfcntr_state * msm_perfcntr_init(struct msm_gpu *gpu);
|
||||
void msm_perfcntr_cleanup(struct msm_gpu *gpu);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
unsigned long msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan);
|
||||
#endif
|
||||
|
|
@ -435,8 +441,6 @@ void msm_rd_debugfs_cleanup(struct msm_drm_private *priv);
|
|||
__printf(3, 4)
|
||||
void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
|
||||
const char *fmt, ...);
|
||||
int msm_perf_debugfs_init(struct drm_minor *minor);
|
||||
void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);
|
||||
#else
|
||||
static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }
|
||||
__printf(3, 4)
|
||||
|
|
@ -444,7 +448,6 @@ static inline void msm_rd_dump_submit(struct msm_rd_state *rd,
|
|||
struct msm_gem_submit *submit,
|
||||
const char *fmt, ...) {}
|
||||
static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {}
|
||||
static inline void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) {}
|
||||
#endif
|
||||
|
||||
struct clk *msm_clk_get(struct platform_device *pdev, const char *name);
|
||||
|
|
|
|||
|
|
@ -681,104 +681,6 @@ static void hangcheck_handler(struct timer_list *t)
|
|||
msm_gpu_retire(gpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performance Counters:
|
||||
*/
|
||||
|
||||
/* called under perf_lock */
|
||||
static int update_hw_cntrs(struct msm_gpu *gpu, uint32_t ncntrs, uint32_t *cntrs)
|
||||
{
|
||||
uint32_t current_cntrs[ARRAY_SIZE(gpu->last_cntrs)];
|
||||
int i, n = min(ncntrs, gpu->num_perfcntrs);
|
||||
|
||||
/* read current values: */
|
||||
for (i = 0; i < gpu->num_perfcntrs; i++)
|
||||
current_cntrs[i] = gpu_read(gpu, gpu->perfcntrs[i].sample_reg);
|
||||
|
||||
/* update cntrs: */
|
||||
for (i = 0; i < n; i++)
|
||||
cntrs[i] = current_cntrs[i] - gpu->last_cntrs[i];
|
||||
|
||||
/* save current values: */
|
||||
for (i = 0; i < gpu->num_perfcntrs; i++)
|
||||
gpu->last_cntrs[i] = current_cntrs[i];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void update_sw_cntrs(struct msm_gpu *gpu)
|
||||
{
|
||||
ktime_t time;
|
||||
uint32_t elapsed;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&gpu->perf_lock, flags);
|
||||
if (!gpu->perfcntr_active)
|
||||
goto out;
|
||||
|
||||
time = ktime_get();
|
||||
elapsed = ktime_to_us(ktime_sub(time, gpu->last_sample.time));
|
||||
|
||||
gpu->totaltime += elapsed;
|
||||
if (gpu->last_sample.active)
|
||||
gpu->activetime += elapsed;
|
||||
|
||||
gpu->last_sample.active = msm_gpu_active(gpu);
|
||||
gpu->last_sample.time = time;
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&gpu->perf_lock, flags);
|
||||
}
|
||||
|
||||
void msm_gpu_perfcntr_start(struct msm_gpu *gpu)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pm_runtime_get_sync(&gpu->pdev->dev);
|
||||
|
||||
spin_lock_irqsave(&gpu->perf_lock, flags);
|
||||
/* we could dynamically enable/disable perfcntr registers too.. */
|
||||
gpu->last_sample.active = msm_gpu_active(gpu);
|
||||
gpu->last_sample.time = ktime_get();
|
||||
gpu->activetime = gpu->totaltime = 0;
|
||||
gpu->perfcntr_active = true;
|
||||
update_hw_cntrs(gpu, 0, NULL);
|
||||
spin_unlock_irqrestore(&gpu->perf_lock, flags);
|
||||
}
|
||||
|
||||
void msm_gpu_perfcntr_stop(struct msm_gpu *gpu)
|
||||
{
|
||||
gpu->perfcntr_active = false;
|
||||
pm_runtime_put_sync(&gpu->pdev->dev);
|
||||
}
|
||||
|
||||
/* returns -errno or # of cntrs sampled */
|
||||
int msm_gpu_perfcntr_sample(struct msm_gpu *gpu, uint32_t *activetime,
|
||||
uint32_t *totaltime, uint32_t ncntrs, uint32_t *cntrs)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&gpu->perf_lock, flags);
|
||||
|
||||
if (!gpu->perfcntr_active) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*activetime = gpu->activetime;
|
||||
*totaltime = gpu->totaltime;
|
||||
|
||||
gpu->activetime = gpu->totaltime = 0;
|
||||
|
||||
ret = update_hw_cntrs(gpu, ncntrs, cntrs);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&gpu->perf_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cmdstream submission/retirement:
|
||||
*/
|
||||
|
|
@ -881,7 +783,6 @@ void msm_gpu_retire(struct msm_gpu *gpu)
|
|||
msm_update_fence(gpu->rb[i]->fctx, gpu->rb[i]->memptrs->fence);
|
||||
|
||||
kthread_queue_work(gpu->worker, &gpu->retire_work);
|
||||
update_sw_cntrs(gpu);
|
||||
}
|
||||
|
||||
/* add bo's to gpu's ring, and kick gpu: */
|
||||
|
|
@ -898,8 +799,6 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
|
||||
submit->seqno = submit->hw_fence->seqno;
|
||||
|
||||
update_sw_cntrs(gpu);
|
||||
|
||||
/*
|
||||
* ring->submits holds a ref to the submit, to deal with the case
|
||||
* that a submit completes before msm_ioctl_gem_submit() returns.
|
||||
|
|
@ -991,9 +890,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
|
|||
void *memptrs;
|
||||
uint64_t memptrs_iova;
|
||||
|
||||
if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs)))
|
||||
gpu->num_perfcntrs = ARRAY_SIZE(gpu->last_cntrs);
|
||||
|
||||
gpu->dev = drm;
|
||||
gpu->funcs = funcs;
|
||||
gpu->name = name;
|
||||
|
|
@ -1025,9 +921,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
|
|||
|
||||
timer_setup(&gpu->hangcheck_timer, hangcheck_handler, 0);
|
||||
|
||||
spin_lock_init(&gpu->perf_lock);
|
||||
|
||||
|
||||
/* Map registers: */
|
||||
gpu->mmio = msm_ioremap(pdev, config->ioname);
|
||||
if (IS_ERR(gpu->mmio)) {
|
||||
|
|
@ -1117,6 +1010,17 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
|
|||
|
||||
refcount_set(&gpu->sysprof_active, 1);
|
||||
|
||||
mutex_init(&gpu->perfcntr_lock);
|
||||
|
||||
if (gpu->num_perfcntr_groups > 0) {
|
||||
gpu->perfcntrs = msm_perfcntr_init(gpu);
|
||||
if (IS_ERR(gpu->perfcntrs)) {
|
||||
ret = PTR_ERR(gpu->perfcntrs);
|
||||
gpu->perfcntrs = NULL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
@ -1155,6 +1059,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
|
|||
}
|
||||
|
||||
msm_devfreq_cleanup(gpu);
|
||||
msm_perfcntr_cleanup(gpu);
|
||||
|
||||
platform_set_drvdata(gpu->pdev, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,10 @@
|
|||
|
||||
struct msm_gem_submit;
|
||||
struct msm_gem_vm_log_entry;
|
||||
struct msm_gpu_perfcntr;
|
||||
struct msm_gpu_state;
|
||||
struct msm_context;
|
||||
struct msm_perfcntr_group;
|
||||
struct msm_perfcntr_stream;
|
||||
|
||||
struct msm_gpu_config {
|
||||
const char *ioname;
|
||||
|
|
@ -92,7 +93,14 @@ struct msm_gpu_funcs {
|
|||
* for cmdstream that is buffered in this FIFO upstream of the CP fw.
|
||||
*/
|
||||
bool (*progress)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
|
||||
void (*sysprof_setup)(struct msm_gpu *gpu);
|
||||
void (*sysprof_setup)(struct msm_gpu *gpu, bool force_on);
|
||||
|
||||
/* Configure perfcntr SELect regs: */
|
||||
void (*perfcntr_configure)(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
|
||||
const struct msm_perfcntr_stream *stream);
|
||||
|
||||
/* Flush perfcntrs before reading (optional): */
|
||||
void (*perfcntr_flush)(struct msm_gpu *gpu);
|
||||
};
|
||||
|
||||
/* Additional state for iommu faults: */
|
||||
|
|
@ -168,18 +176,6 @@ struct msm_gpu {
|
|||
|
||||
struct adreno_smmu_priv adreno_smmu;
|
||||
|
||||
/* performance counters (hw & sw): */
|
||||
spinlock_t perf_lock;
|
||||
bool perfcntr_active;
|
||||
struct {
|
||||
bool active;
|
||||
ktime_t time;
|
||||
} last_sample;
|
||||
uint32_t totaltime, activetime; /* sw counters */
|
||||
uint32_t last_cntrs[5]; /* hw counters */
|
||||
const struct msm_gpu_perfcntr *perfcntrs;
|
||||
uint32_t num_perfcntrs;
|
||||
|
||||
struct msm_ringbuffer *rb[MSM_GPU_MAX_RINGS];
|
||||
int nr_rings;
|
||||
|
||||
|
|
@ -275,6 +271,14 @@ struct msm_gpu {
|
|||
bool allow_relocs;
|
||||
|
||||
struct thermal_cooling_device *cooling;
|
||||
|
||||
const struct msm_perfcntr_group *perfcntr_groups;
|
||||
unsigned num_perfcntr_groups;
|
||||
|
||||
struct msm_perfcntr_state *perfcntrs;
|
||||
|
||||
/** @perfcntr_lock: protects perfcntr related state */
|
||||
struct mutex perfcntr_lock;
|
||||
};
|
||||
|
||||
static inline struct msm_gpu *dev_to_gpu(struct device *dev)
|
||||
|
|
@ -320,19 +324,63 @@ static inline bool msm_gpu_active(struct msm_gpu *gpu)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Perf-Counters:
|
||||
* The select_reg and select_val are just there for the benefit of the child
|
||||
* class that actually enables the perf counter.. but msm_gpu base class
|
||||
* will handle sampling/displaying the counters.
|
||||
/**
|
||||
* struct msm_perfcntr_group_state - Tracking for the currently allocated counter state
|
||||
*/
|
||||
struct msm_perfcntr_group_state {
|
||||
/**
|
||||
* @allocated_counters:
|
||||
*
|
||||
* allocated counters for global counter collection. The
|
||||
* corresponding counters are allocated from highest to
|
||||
* lowest, to minimize chance of conflict with old userspace
|
||||
* allocating from lowest to highest.
|
||||
*/
|
||||
unsigned allocated_counters;
|
||||
|
||||
struct msm_gpu_perfcntr {
|
||||
uint32_t select_reg;
|
||||
uint32_t sample_reg;
|
||||
uint32_t select_val;
|
||||
const char *name;
|
||||
/**
|
||||
* @countables:
|
||||
*
|
||||
* The corresponding SELect reg values for the allocated counters
|
||||
*/
|
||||
uint32_t countables[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_perfcntr_state - overall global perfcntr state
|
||||
*/
|
||||
struct msm_perfcntr_state {
|
||||
/** @stream: current global counter stream if active */
|
||||
struct msm_perfcntr_stream *stream;
|
||||
|
||||
/** @sel_seqno: counter for sel_fence */
|
||||
uint32_t sel_seqno;
|
||||
|
||||
/**
|
||||
* @groups: Global perfcntr stream group state.
|
||||
*
|
||||
* Conceptually this is part of msm_perfcntr_stream state, but is
|
||||
* statically pre-allocated when the gpu is initialized to simplify
|
||||
* error path cleanup in PERFCNTR_CONFIG ioctl. (__free(kfree)
|
||||
* doesn't really help with variable length arrays of allocated
|
||||
* pointers.)
|
||||
*/
|
||||
struct msm_perfcntr_group_state *groups[];
|
||||
};
|
||||
|
||||
static inline bool
|
||||
msm_gpu_sysprof_no_perfcntr_zap(struct msm_gpu *gpu)
|
||||
{
|
||||
return (refcount_read(&gpu->sysprof_active) > 1) ||
|
||||
(gpu->perfcntrs && READ_ONCE(gpu->perfcntrs->stream));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
msm_gpu_sysprof_no_ifpc(struct msm_gpu *gpu)
|
||||
{
|
||||
return refcount_read(&gpu->sysprof_active) > 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The number of priority levels provided by drm gpu scheduler. The
|
||||
* DRM_SCHED_PRIORITY_KERNEL priority level is treated specially in some
|
||||
|
|
@ -438,6 +486,11 @@ struct msm_context {
|
|||
* this context.
|
||||
*/
|
||||
atomic64_t ctx_mem;
|
||||
|
||||
/**
|
||||
* @perfcntrs: Per-context reserved perfcntrs state
|
||||
*/
|
||||
struct msm_perfcntr_context_state *perfctx;
|
||||
};
|
||||
|
||||
struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx);
|
||||
|
|
@ -689,11 +742,6 @@ void msm_devfreq_idle(struct msm_gpu *gpu);
|
|||
|
||||
int msm_gpu_hw_init(struct msm_gpu *gpu);
|
||||
|
||||
void msm_gpu_perfcntr_start(struct msm_gpu *gpu);
|
||||
void msm_gpu_perfcntr_stop(struct msm_gpu *gpu);
|
||||
int msm_gpu_perfcntr_sample(struct msm_gpu *gpu, uint32_t *activetime,
|
||||
uint32_t *totaltime, uint32_t ncntrs, uint32_t *cntrs);
|
||||
|
||||
void msm_gpu_retire(struct msm_gpu *gpu);
|
||||
void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit);
|
||||
|
||||
|
|
|
|||
|
|
@ -166,90 +166,72 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
|
||||
static void msm_mdss_4x_setup_ubwc(struct msm_mdss *msm_mdss)
|
||||
{
|
||||
const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
|
||||
u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
|
||||
u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(qcom_ubwc_swizzle(data) &
|
||||
UBWC_SWIZZLE_ENABLE_LVL1) |
|
||||
MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
|
||||
|
||||
if (data->ubwc_bank_spread)
|
||||
value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
|
||||
|
||||
if (data->ubwc_enc_version == UBWC_1_0)
|
||||
value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1);
|
||||
value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(qcom_ubwc_min_acc_length_64b(data));
|
||||
|
||||
writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
|
||||
}
|
||||
|
||||
static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss)
|
||||
static void msm_mdss_5x_setup_ubwc(struct msm_mdss *msm_mdss)
|
||||
{
|
||||
const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
|
||||
u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle & 0x1) |
|
||||
u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(qcom_ubwc_swizzle(data) &
|
||||
UBWC_SWIZZLE_ENABLE_LVL1) |
|
||||
MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
|
||||
|
||||
if (data->macrotile_mode)
|
||||
if (qcom_ubwc_macrotile_mode(data))
|
||||
value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
|
||||
|
||||
if (data->ubwc_enc_version == UBWC_3_0)
|
||||
if (qcom_ubwc_enable_amsbc(data))
|
||||
value |= MDSS_UBWC_STATIC_UBWC_AMSBC;
|
||||
|
||||
if (data->ubwc_enc_version == UBWC_1_0)
|
||||
value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1);
|
||||
value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(qcom_ubwc_min_acc_length_64b(data));
|
||||
|
||||
writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
|
||||
}
|
||||
|
||||
static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
|
||||
static void msm_mdss_6x_setup_ubwc(struct msm_mdss *msm_mdss)
|
||||
{
|
||||
const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
|
||||
u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
|
||||
u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(qcom_ubwc_swizzle(data)) |
|
||||
MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
|
||||
u32 prediction_mode;
|
||||
|
||||
if (data->ubwc_bank_spread)
|
||||
if (qcom_ubwc_bank_spread(data))
|
||||
value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
|
||||
|
||||
if (data->macrotile_mode)
|
||||
if (qcom_ubwc_macrotile_mode(data))
|
||||
value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
|
||||
|
||||
value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(qcom_ubwc_min_acc_length_64b(data));
|
||||
|
||||
writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
|
||||
|
||||
if (data->ubwc_enc_version == UBWC_3_0) {
|
||||
writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
|
||||
writel_relaxed(0, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
|
||||
} else {
|
||||
if (data->ubwc_dec_version == UBWC_4_3)
|
||||
writel_relaxed(3, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
|
||||
else
|
||||
writel_relaxed(2, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
|
||||
writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
static void msm_mdss_setup_ubwc_dec_50(struct msm_mdss *msm_mdss)
|
||||
{
|
||||
const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
|
||||
u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
|
||||
MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
|
||||
|
||||
if (data->ubwc_bank_spread)
|
||||
value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
|
||||
|
||||
if (data->macrotile_mode)
|
||||
value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
|
||||
|
||||
writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
|
||||
|
||||
if (data->ubwc_dec_version == UBWC_6_0)
|
||||
writel_relaxed(5, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
|
||||
if (data->ubwc_enc_version < UBWC_4_0)
|
||||
prediction_mode = 0;
|
||||
else
|
||||
writel_relaxed(4, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
|
||||
prediction_mode = 1;
|
||||
|
||||
writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
|
||||
writel_relaxed(qcom_ubwc_version_tag(data),
|
||||
msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
|
||||
writel_relaxed(prediction_mode, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
|
||||
}
|
||||
|
||||
#define MDSS_HW_VER(major, minor, step) \
|
||||
((((major) & 0xf) << 28) | \
|
||||
(((minor) & 0xfff) << 16) | \
|
||||
((step) & 0xffff))
|
||||
|
||||
static int msm_mdss_enable(struct msm_mdss *msm_mdss)
|
||||
{
|
||||
int ret, i;
|
||||
u32 hw_rev;
|
||||
|
||||
/*
|
||||
* Several components have AXI clocks that can only be turned on if
|
||||
|
|
@ -283,43 +265,15 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
|
|||
if (msm_mdss->is_mdp5 || !msm_mdss->mdss_data)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* ubwc config is part of the "mdss" region which is not accessible
|
||||
* from the rest of the driver. hardcode known configurations here
|
||||
*
|
||||
* Decoder version can be read from the UBWC_DEC_HW_VERSION reg,
|
||||
* UBWC_n and the rest of params comes from hw data.
|
||||
*/
|
||||
switch (msm_mdss->mdss_data->ubwc_dec_version) {
|
||||
case 0: /* no UBWC */
|
||||
case UBWC_1_0:
|
||||
/* do nothing */
|
||||
break;
|
||||
case UBWC_2_0:
|
||||
msm_mdss_setup_ubwc_dec_20(msm_mdss);
|
||||
break;
|
||||
case UBWC_3_0:
|
||||
msm_mdss_setup_ubwc_dec_30(msm_mdss);
|
||||
break;
|
||||
case UBWC_4_0:
|
||||
case UBWC_4_3:
|
||||
msm_mdss_setup_ubwc_dec_40(msm_mdss);
|
||||
break;
|
||||
case UBWC_5_0:
|
||||
msm_mdss_setup_ubwc_dec_50(msm_mdss);
|
||||
break;
|
||||
case UBWC_6_0:
|
||||
msm_mdss_setup_ubwc_dec_50(msm_mdss);
|
||||
break;
|
||||
default:
|
||||
dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n",
|
||||
msm_mdss->mdss_data->ubwc_dec_version);
|
||||
dev_err(msm_mdss->dev, "HW_REV: 0x%x\n",
|
||||
readl_relaxed(msm_mdss->mmio + REG_MDSS_HW_VERSION));
|
||||
dev_err(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n",
|
||||
readl_relaxed(msm_mdss->mmio + REG_MDSS_UBWC_DEC_HW_VERSION));
|
||||
break;
|
||||
}
|
||||
hw_rev = readl_relaxed(msm_mdss->mmio + REG_MDSS_HW_VERSION);
|
||||
|
||||
if (hw_rev >= MDSS_HW_VER(6, 0, 0))
|
||||
msm_mdss_6x_setup_ubwc(msm_mdss);
|
||||
else if (hw_rev >= MDSS_HW_VER(5, 0, 0))
|
||||
msm_mdss_5x_setup_ubwc(msm_mdss);
|
||||
else if (hw_rev >= MDSS_HW_VER(4, 0, 0))
|
||||
msm_mdss_4x_setup_ubwc(msm_mdss);
|
||||
/* else UBWC 1.0 or none, no params to program */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -550,6 +504,10 @@ static void mdss_remove(struct platform_device *pdev)
|
|||
msm_mdss_destroy(mdss);
|
||||
}
|
||||
|
||||
static const struct msm_mdss_data data_14k = {
|
||||
.reg_bus_bw = 14000,
|
||||
};
|
||||
|
||||
static const struct msm_mdss_data data_57k = {
|
||||
.reg_bus_bw = 57000,
|
||||
};
|
||||
|
|
@ -571,6 +529,7 @@ static const struct of_device_id mdss_dt_match[] = {
|
|||
{ .compatible = "qcom,eliza-mdss", .data = &data_57k },
|
||||
{ .compatible = "qcom,glymur-mdss", .data = &data_57k },
|
||||
{ .compatible = "qcom,kaanapali-mdss", .data = &data_57k },
|
||||
{ .compatible = "qcom,milos-mdss", .data = &data_14k },
|
||||
{ .compatible = "qcom,msm8998-mdss", .data = &data_76k8 },
|
||||
{ .compatible = "qcom,qcm2290-mdss", .data = &data_76k8 },
|
||||
{ .compatible = "qcom,qcs8300-mdss", .data = &data_74k },
|
||||
|
|
|
|||
|
|
@ -1,235 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
*/
|
||||
|
||||
/* For profiling, userspace can:
|
||||
*
|
||||
* tail -f /sys/kernel/debug/dri/<minor>/gpu
|
||||
*
|
||||
* This will enable performance counters/profiling to track the busy time
|
||||
* and any gpu specific performance counters that are supported.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_file.h>
|
||||
|
||||
#include "msm_drv.h"
|
||||
#include "msm_gpu.h"
|
||||
|
||||
struct msm_perf_state {
|
||||
struct drm_device *dev;
|
||||
|
||||
bool open;
|
||||
int cnt;
|
||||
struct mutex read_lock;
|
||||
|
||||
char buf[256];
|
||||
int buftot, bufpos;
|
||||
|
||||
unsigned long next_jiffies;
|
||||
};
|
||||
|
||||
#define SAMPLE_TIME (HZ/4)
|
||||
|
||||
/* wait for next sample time: */
|
||||
static int wait_sample(struct msm_perf_state *perf)
|
||||
{
|
||||
unsigned long start_jiffies = jiffies;
|
||||
|
||||
if (time_after(perf->next_jiffies, start_jiffies)) {
|
||||
unsigned long remaining_jiffies =
|
||||
perf->next_jiffies - start_jiffies;
|
||||
int ret = schedule_timeout_interruptible(remaining_jiffies);
|
||||
if (ret > 0) {
|
||||
/* interrupted */
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
}
|
||||
perf->next_jiffies += SAMPLE_TIME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int refill_buf(struct msm_perf_state *perf)
|
||||
{
|
||||
struct msm_drm_private *priv = perf->dev->dev_private;
|
||||
struct msm_gpu *gpu = priv->gpu;
|
||||
char *ptr = perf->buf;
|
||||
int rem = sizeof(perf->buf);
|
||||
int i, n;
|
||||
|
||||
if ((perf->cnt++ % 32) == 0) {
|
||||
/* Header line: */
|
||||
n = scnprintf(ptr, rem, "%%BUSY");
|
||||
ptr += n;
|
||||
rem -= n;
|
||||
|
||||
for (i = 0; i < gpu->num_perfcntrs; i++) {
|
||||
const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
|
||||
n = scnprintf(ptr, rem, "\t%s", perfcntr->name);
|
||||
ptr += n;
|
||||
rem -= n;
|
||||
}
|
||||
} else {
|
||||
/* Sample line: */
|
||||
uint32_t activetime = 0, totaltime = 0;
|
||||
uint32_t cntrs[5];
|
||||
uint32_t val;
|
||||
int ret;
|
||||
|
||||
/* sleep until next sample time: */
|
||||
ret = wait_sample(perf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = msm_gpu_perfcntr_sample(gpu, &activetime, &totaltime,
|
||||
ARRAY_SIZE(cntrs), cntrs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = totaltime ? 1000 * activetime / totaltime : 0;
|
||||
n = scnprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
|
||||
ptr += n;
|
||||
rem -= n;
|
||||
|
||||
for (i = 0; i < ret; i++) {
|
||||
/* cycle counters (I think).. convert to MHz.. */
|
||||
val = cntrs[i] / 10000;
|
||||
n = scnprintf(ptr, rem, "\t%5d.%02d",
|
||||
val / 100, val % 100);
|
||||
ptr += n;
|
||||
rem -= n;
|
||||
}
|
||||
}
|
||||
|
||||
n = scnprintf(ptr, rem, "\n");
|
||||
ptr += n;
|
||||
rem -= n;
|
||||
|
||||
perf->bufpos = 0;
|
||||
perf->buftot = ptr - perf->buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t perf_read(struct file *file, char __user *buf,
|
||||
size_t sz, loff_t *ppos)
|
||||
{
|
||||
struct msm_perf_state *perf = file->private_data;
|
||||
int n = 0, ret = 0;
|
||||
|
||||
mutex_lock(&perf->read_lock);
|
||||
|
||||
if (perf->bufpos >= perf->buftot) {
|
||||
ret = refill_buf(perf);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
n = min((int)sz, perf->buftot - perf->bufpos);
|
||||
if (copy_to_user(buf, &perf->buf[perf->bufpos], n)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
perf->bufpos += n;
|
||||
*ppos += n;
|
||||
|
||||
out:
|
||||
mutex_unlock(&perf->read_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
return n;
|
||||
}
|
||||
|
||||
static int perf_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct msm_perf_state *perf = inode->i_private;
|
||||
struct drm_device *dev = perf->dev;
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_gpu *gpu = priv->gpu;
|
||||
int ret = 0;
|
||||
|
||||
if (!gpu)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&gpu->lock);
|
||||
|
||||
if (perf->open) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
file->private_data = perf;
|
||||
perf->open = true;
|
||||
perf->cnt = 0;
|
||||
perf->buftot = 0;
|
||||
perf->bufpos = 0;
|
||||
msm_gpu_perfcntr_start(gpu);
|
||||
perf->next_jiffies = jiffies + SAMPLE_TIME;
|
||||
|
||||
out:
|
||||
mutex_unlock(&gpu->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int perf_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct msm_perf_state *perf = inode->i_private;
|
||||
struct msm_drm_private *priv = perf->dev->dev_private;
|
||||
msm_gpu_perfcntr_stop(priv->gpu);
|
||||
perf->open = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations perf_debugfs_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = perf_open,
|
||||
.read = perf_read,
|
||||
.release = perf_release,
|
||||
};
|
||||
|
||||
int msm_perf_debugfs_init(struct drm_minor *minor)
|
||||
{
|
||||
struct msm_drm_private *priv = minor->dev->dev_private;
|
||||
struct msm_perf_state *perf;
|
||||
|
||||
/* only create on first minor: */
|
||||
if (priv->perf)
|
||||
return 0;
|
||||
|
||||
perf = kzalloc_obj(*perf);
|
||||
if (!perf)
|
||||
return -ENOMEM;
|
||||
|
||||
perf->dev = minor->dev;
|
||||
|
||||
mutex_init(&perf->read_lock);
|
||||
priv->perf = perf;
|
||||
|
||||
debugfs_create_file("perf", S_IFREG | S_IRUGO, minor->debugfs_root,
|
||||
perf, &perf_debugfs_fops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msm_perf_debugfs_cleanup(struct msm_drm_private *priv)
|
||||
{
|
||||
struct msm_perf_state *perf = priv->perf;
|
||||
|
||||
if (!perf)
|
||||
return;
|
||||
|
||||
priv->perf = NULL;
|
||||
|
||||
mutex_destroy(&perf->read_lock);
|
||||
|
||||
kfree(perf);
|
||||
}
|
||||
|
||||
#endif
|
||||
670
drivers/gpu/drm/msm/msm_perfcntr.c
Normal file
670
drivers/gpu/drm/msm/msm_perfcntr.c
Normal file
|
|
@ -0,0 +1,670 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#include "drm/drm_file.h"
|
||||
#include "drm/msm_drm.h"
|
||||
|
||||
#include "linux/anon_inodes.h"
|
||||
#include "linux/gfp_types.h"
|
||||
#include "linux/poll.h"
|
||||
#include "linux/slab.h"
|
||||
|
||||
#include "msm_drv.h"
|
||||
#include "msm_gpu.h"
|
||||
#include "msm_perfcntr.h"
|
||||
|
||||
#include "adreno/adreno_gpu.h"
|
||||
|
||||
/* space used: */
|
||||
#define fifo_count(stream) \
|
||||
(CIRC_CNT((stream)->fifo.head, (stream)->fifo.tail, (stream)->fifo_size))
|
||||
#define fifo_count_to_end(stream) \
|
||||
(CIRC_CNT_TO_END(smp_load_acquire(&(stream)->fifo.head), (stream)->fifo.tail, (stream)->fifo_size))
|
||||
/* space available: */
|
||||
#define fifo_space(stream) \
|
||||
(CIRC_SPACE((stream)->fifo.head, (stream)->fifo.tail, (stream)->fifo_size))
|
||||
|
||||
static int
|
||||
msm_perfcntr_resume_locked(struct msm_perfcntr_stream *stream)
|
||||
{
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
/* Reprogram SEL regs on highest priority rb: */
|
||||
struct msm_ringbuffer *ring = stream->gpu->rb[0];
|
||||
|
||||
queue_work(ring->sched.submit_wq, &stream->sel_work);
|
||||
|
||||
hrtimer_start(&stream->sample_timer,
|
||||
ns_to_ktime(stream->sample_period_ns),
|
||||
HRTIMER_MODE_REL_PINNED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
msm_perfcntr_resume(struct msm_gpu *gpu)
|
||||
{
|
||||
if (!gpu->perfcntrs)
|
||||
return 0;
|
||||
guard(mutex)(&gpu->perfcntr_lock);
|
||||
return msm_perfcntr_resume_locked(gpu->perfcntrs->stream);
|
||||
}
|
||||
|
||||
static void
|
||||
msm_perfcntr_suspend_locked(struct msm_perfcntr_stream *stream)
|
||||
{
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
hrtimer_cancel(&stream->sample_timer);
|
||||
kthread_cancel_work_sync(&stream->sample_work);
|
||||
|
||||
/*
|
||||
* We can't use cancel_work_sync() here, since sel_work acquires
|
||||
* gpu->lock which (a) in suspend path can already be held, or
|
||||
* (b) in release path would invert the order of gpu->lock and
|
||||
* gpu->perfcntr_lock. Either would cause deadlock.
|
||||
*/
|
||||
cancel_work(&stream->sel_work);
|
||||
|
||||
stream->sel_fence = ++stream->gpu->perfcntrs->sel_seqno;
|
||||
stream->seqno = 0;
|
||||
}
|
||||
|
||||
void
|
||||
msm_perfcntr_suspend(struct msm_gpu *gpu)
|
||||
{
|
||||
if (!gpu->perfcntrs)
|
||||
return;
|
||||
guard(mutex)(&gpu->perfcntr_lock);
|
||||
msm_perfcntr_suspend_locked(gpu->perfcntrs->stream);
|
||||
}
|
||||
|
||||
static int
|
||||
msm_perfcntrs_stream_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct msm_perfcntr_stream *stream = file->private_data;
|
||||
struct msm_gpu *gpu = stream->gpu;
|
||||
|
||||
scoped_guard (mutex, &gpu->perfcntr_lock) {
|
||||
struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
|
||||
|
||||
msm_perfcntr_suspend_locked(stream);
|
||||
perfcntrs->stream = NULL;
|
||||
|
||||
/* release previously allocated counters: */
|
||||
for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++)
|
||||
perfcntrs->groups[i]->allocated_counters = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the suspend path we use async cancel_work(), to avoid blocking
|
||||
* on sel_work, which acquires gpu->lock (which could deadlock since
|
||||
* other paths acquire gpu->lock before perfcntr_lock) or already
|
||||
* hold gpu->lock.
|
||||
*
|
||||
* But since we are freeing the stream, after dropping perfcntr_lock
|
||||
* we need to block until sel_work is done:
|
||||
*/
|
||||
cancel_work_sync(&stream->sel_work);
|
||||
|
||||
kfree(stream->group_idx);
|
||||
kfree(stream->fifo.buf);
|
||||
kfree(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __poll_t
|
||||
msm_perfcntrs_stream_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct msm_perfcntr_stream *stream = file->private_data;
|
||||
__poll_t events = 0;
|
||||
|
||||
poll_wait(file, &stream->poll_wq, wait);
|
||||
|
||||
/* Are there samples to read? */
|
||||
if (fifo_count(stream) > 0)
|
||||
events |= EPOLLIN;
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
msm_perfcntrs_stream_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct msm_perfcntr_stream *stream = file->private_data;
|
||||
int ret;
|
||||
|
||||
if (!(file->f_flags & O_NONBLOCK)) {
|
||||
ret = wait_event_interruptible(stream->poll_wq,
|
||||
fifo_count(stream) > 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
guard(mutex)(&stream->read_lock);
|
||||
|
||||
struct circ_buf *fifo = &stream->fifo;
|
||||
const char *fptr = &fifo->buf[fifo->tail];
|
||||
|
||||
count = min_t(size_t, count, fifo_count_to_end(stream));
|
||||
if (!count)
|
||||
return -EAGAIN;
|
||||
if (copy_to_user(buf, fptr, count))
|
||||
return -EFAULT;
|
||||
|
||||
smp_store_release(&fifo->tail, (fifo->tail + count) & (stream->fifo_size - 1));
|
||||
*ppos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations stream_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.release = msm_perfcntrs_stream_release,
|
||||
.poll = msm_perfcntrs_stream_poll,
|
||||
.read = msm_perfcntrs_stream_read,
|
||||
};
|
||||
|
||||
static void
|
||||
sel_worker(struct work_struct *w)
|
||||
{
|
||||
struct msm_perfcntr_stream *stream =
|
||||
container_of(w, typeof(*stream), sel_work);
|
||||
struct msm_gpu *gpu = stream->gpu;
|
||||
/* Reprogram SEL regs on highest priority rb: */
|
||||
struct msm_ringbuffer *ring = stream->gpu->rb[0];
|
||||
|
||||
/*
|
||||
* If in the process of resuming, wait for that. Otherwise sel_worker
|
||||
* which is enqueued in the resume path can be scheduled before the
|
||||
* resume completes.
|
||||
*/
|
||||
pm_runtime_barrier(&gpu->pdev->dev);
|
||||
|
||||
/*
|
||||
* sel_work could end up scheduled before suspend, but running
|
||||
* after. See msm_perfcntr_suspend_locked()
|
||||
*
|
||||
* So if we end up running sel_work after the GPU is already
|
||||
* suspended, just bail. It will be scheduled again after
|
||||
* the GPU is resumed.
|
||||
*/
|
||||
if (!pm_runtime_get_if_active(&gpu->pdev->dev))
|
||||
return;
|
||||
|
||||
scoped_guard (mutex, &gpu->lock) {
|
||||
guard(mutex)(&gpu->perfcntr_lock);
|
||||
|
||||
if (stream == gpu->perfcntrs->stream) {
|
||||
msm_gpu_hw_init(gpu);
|
||||
gpu->funcs->perfcntr_configure(gpu, ring, stream);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put_autosuspend(&gpu->pdev->dev);
|
||||
}
|
||||
|
||||
static void
|
||||
sample_write(struct msm_perfcntr_stream *stream, int *head, const void *buf, size_t sz)
|
||||
{
|
||||
/*
|
||||
* FIFO size is power-of-two, and guaranteed to have enough space to
|
||||
* fit what we are writing. So we should not hit the wrap-around
|
||||
* point writing things that are power-of-two sized
|
||||
*/
|
||||
WARN_ON(CIRC_SPACE_TO_END(*head, stream->fifo.tail, stream->fifo_size) < sz);
|
||||
|
||||
memcpy(&stream->fifo.buf[*head], buf, sz);
|
||||
|
||||
/* Advance head, wrapping around if necessary: */
|
||||
*head = (*head + sz) & (stream->fifo_size - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
sample_write_u32(struct msm_perfcntr_stream *stream, int *head, uint32_t val)
|
||||
{
|
||||
sample_write(stream, head, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static void
|
||||
sample_write_u64(struct msm_perfcntr_stream *stream, int *head, uint64_t val)
|
||||
{
|
||||
sample_write(stream, head, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static void
|
||||
sample_worker(struct kthread_work *work)
|
||||
{
|
||||
struct msm_perfcntr_stream *stream =
|
||||
container_of(work, typeof(*stream), sample_work);
|
||||
struct msm_gpu *gpu = stream->gpu;
|
||||
struct msm_rbmemptrs *memptrs = gpu->rb[0]->memptrs;
|
||||
|
||||
if (memptrs->perfcntr_fence != stream->sel_fence)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ensure we have enough space to capture a sample period's
|
||||
* worth of data:
|
||||
*/
|
||||
if (stream->period_size > fifo_space(stream)) {
|
||||
stream->seqno = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Inhibit IFPC while accessing registers: */
|
||||
if (gpu->funcs->sysprof_setup)
|
||||
gpu->funcs->sysprof_setup(gpu, true);
|
||||
|
||||
if (gpu->funcs->perfcntr_flush)
|
||||
gpu->funcs->perfcntr_flush(gpu);
|
||||
|
||||
/* Keep local copy of head to avoid updating fifo until the end: */
|
||||
int head = stream->fifo.head;
|
||||
|
||||
/*
|
||||
* We expect the GPU to be powered at this point, as the timer
|
||||
* and kthread work are canceled/flushed in the suspend path:
|
||||
*/
|
||||
sample_write_u64(stream, &head,
|
||||
to_adreno_gpu(gpu)->funcs->get_timestamp(gpu));
|
||||
sample_write_u32(stream, &head, stream->seqno++);
|
||||
sample_write_u32(stream, &head, 0);
|
||||
|
||||
for (unsigned i = 0; i < stream->nr_groups; i++) {
|
||||
unsigned group_idx = msm_perfcntr_group_idx(stream, i);
|
||||
unsigned base = msm_perfcntr_counter_base(stream, group_idx);
|
||||
|
||||
const struct msm_perfcntr_group *group =
|
||||
&gpu->perfcntr_groups[group_idx];
|
||||
|
||||
struct msm_perfcntr_group_state *group_state =
|
||||
gpu->perfcntrs->groups[group_idx];
|
||||
|
||||
unsigned nr = group_state->allocated_counters;
|
||||
for (unsigned j = 0; j < nr; j++) {
|
||||
const struct msm_perfcntr_counter *counter =
|
||||
&group->counters[j + base];
|
||||
uint64_t val = gpu_read64(gpu, counter->counter_reg_lo);
|
||||
sample_write_u64(stream, &head, val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Re-enable IFPC: */
|
||||
if (gpu->funcs->sysprof_setup)
|
||||
gpu->funcs->sysprof_setup(gpu, false);
|
||||
|
||||
smp_store_release(&stream->fifo.head, head);
|
||||
wake_up_all(&stream->poll_wq);
|
||||
}
|
||||
|
||||
static enum hrtimer_restart
|
||||
sample_timer(struct hrtimer *hrtimer)
|
||||
{
|
||||
struct msm_perfcntr_stream *stream =
|
||||
container_of(hrtimer, typeof(*stream), sample_timer);
|
||||
|
||||
kthread_queue_work(stream->gpu->worker, &stream->sample_work);
|
||||
|
||||
hrtimer_forward_now(hrtimer, ns_to_ktime(stream->sample_period_ns));
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
static int
|
||||
get_group_idx(struct msm_gpu *gpu, const char *name, size_t len)
|
||||
{
|
||||
for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++) {
|
||||
const struct msm_perfcntr_group *group =
|
||||
&gpu->perfcntr_groups[i];
|
||||
if (!strncmp(group->name, name, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
get_available_counters(struct msm_gpu *gpu, int group_idx, uint32_t flags)
|
||||
{
|
||||
struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
|
||||
|
||||
/*
|
||||
* For local counter reservation, anything that is not used by
|
||||
* global perfcntr stream is available:
|
||||
*/
|
||||
if (!(flags & MSM_PERFCNTR_STREAM)) {
|
||||
return gpu->perfcntr_groups[group_idx].num_counters -
|
||||
perfcntrs->groups[group_idx]->allocated_counters;
|
||||
}
|
||||
|
||||
/*
|
||||
* For global counter collection, anything that is not reserved by
|
||||
* one or more contexts is available:
|
||||
*/
|
||||
guard(mutex)(&gpu->dev->filelist_mutex);
|
||||
|
||||
unsigned reserved_counters = 0;
|
||||
struct drm_file *file;
|
||||
|
||||
list_for_each_entry (file, &gpu->dev->filelist, lhead) {
|
||||
struct msm_context *ctx = file->driver_priv;
|
||||
|
||||
if (!ctx || !ctx->perfctx)
|
||||
continue;
|
||||
|
||||
unsigned n = ctx->perfctx->reserved_counters[group_idx];
|
||||
reserved_counters = max(reserved_counters, n);
|
||||
}
|
||||
|
||||
return gpu->perfcntr_groups[group_idx].num_counters - reserved_counters;
|
||||
}
|
||||
|
||||
int
|
||||
msm_ioctl_perfcntr_config(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
const struct drm_msm_perfcntr_config *args = data;
|
||||
struct msm_context *ctx = file->driver_priv;
|
||||
struct msm_gpu *gpu = priv->gpu;
|
||||
int stream_fd = 0;
|
||||
|
||||
if (!gpu || !gpu->num_perfcntr_groups)
|
||||
return -ENXIO;
|
||||
|
||||
struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
|
||||
|
||||
/*
|
||||
* Validate args that don't require locks/power first:
|
||||
*/
|
||||
|
||||
if (args->flags & ~MSM_PERFCNTR_FLAGS)
|
||||
return UERR(EINVAL, dev, "invalid flags");
|
||||
|
||||
if (args->nr_groups && !args->group_stride)
|
||||
return UERR(EINVAL, dev, "invalid group_stride");
|
||||
|
||||
if (args->nr_groups > gpu->num_perfcntr_groups)
|
||||
return UERR(EINVAL, dev, "too many groups");
|
||||
|
||||
if (args->nr_groups && !args->groups)
|
||||
return UERR(EINVAL, dev, "no groups");
|
||||
|
||||
if (args->flags & MSM_PERFCNTR_STREAM) {
|
||||
if (!perfmon_capable())
|
||||
return UERR(EPERM, dev, "invalid permissions");
|
||||
if (!args->nr_groups)
|
||||
return UERR(EINVAL, dev, "invalid nr_groups");
|
||||
if (!args->period)
|
||||
return UERR(EINVAL, dev, "invalid sampling period");
|
||||
if (args->bufsz_shift > const_ilog2(SZ_128M))
|
||||
return UERR(EINVAL, dev, "buffer size too big (>128M)");
|
||||
} else {
|
||||
if (args->period)
|
||||
return UERR(EINVAL, dev, "sampling period not allowed");
|
||||
if (args->bufsz_shift)
|
||||
return UERR(EINVAL, dev, "sample buf size not allowed");
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid iterating over the groups multiple times, allocate and setup
|
||||
* both a ctx and global stream object. Only one of the two will be
|
||||
* kept in the end.
|
||||
*/
|
||||
|
||||
struct msm_perfcntr_context_state *perfctx __free(kfree) = kzalloc(
|
||||
struct_size(perfctx, reserved_counters, gpu->num_perfcntr_groups),
|
||||
GFP_KERNEL);
|
||||
if (!perfctx)
|
||||
return -ENOMEM;
|
||||
|
||||
struct msm_perfcntr_stream *stream __free(kfree) = kzalloc_obj(*stream);
|
||||
if (!stream)
|
||||
return -ENOMEM;
|
||||
|
||||
uint8_t *nr_counters __free(kfree) = kzalloc_objs(uint8_t, gpu->num_perfcntr_groups);
|
||||
if (!nr_counters)
|
||||
return -ENOMEM;
|
||||
|
||||
uint32_t *group_idx __free(kfree) = kzalloc_objs(uint32_t, args->nr_groups);
|
||||
if (!group_idx)
|
||||
return -ENOMEM;
|
||||
|
||||
stream->gpu = gpu;
|
||||
stream->sample_period_ns = args->period;
|
||||
stream->nr_groups = args->nr_groups;
|
||||
stream->fifo_size = 1ull << args->bufsz_shift;
|
||||
|
||||
mutex_init(&stream->read_lock);
|
||||
|
||||
guard(mutex)(&gpu->perfcntr_lock);
|
||||
|
||||
if (args->flags & MSM_PERFCNTR_STREAM) {
|
||||
if (perfcntrs->stream)
|
||||
return UERR(EBUSY, dev, "perfcntr stream already open");
|
||||
}
|
||||
|
||||
size_t bufsz = 16; /* header size includes seqno and 64b timestamp: */
|
||||
int ret = 0;
|
||||
|
||||
for (unsigned i = 0; i < args->nr_groups; i++) {
|
||||
struct drm_msm_perfcntr_group g = {0};
|
||||
size_t sz = min_t(size_t, args->group_stride, sizeof(g));
|
||||
void __user *userptr =
|
||||
u64_to_user_ptr(args->groups + (i * args->group_stride));
|
||||
|
||||
if (copy_from_user(&g, userptr, sz))
|
||||
return -EFAULT;
|
||||
|
||||
if (g.pad)
|
||||
return UERR(EINVAL, dev, "groups[%d]: invalid pad", i);
|
||||
|
||||
int idx = get_group_idx(gpu, g.group_name, sizeof(g.group_name));
|
||||
|
||||
if (idx < 0)
|
||||
return UERR(EINVAL, dev, "groups[%d]: unknown group", i);
|
||||
|
||||
if (nr_counters[idx])
|
||||
return UERR(EINVAL, dev, "groups[%d]: duplicate group", i);
|
||||
|
||||
if (g.nr_countables > gpu->perfcntr_groups[idx].num_counters)
|
||||
return UERR(EINVAL, dev, "groups[%d]: too many counters", i);
|
||||
|
||||
if (args->flags & MSM_PERFCNTR_STREAM) {
|
||||
if (g.nr_countables && !g.countables)
|
||||
return UERR(EINVAL, dev, "groups[%d]: no countables", i);
|
||||
} else {
|
||||
if (g.countables)
|
||||
return UERR(EINVAL, dev, "groups[%d]: countables should be NULL", i);
|
||||
}
|
||||
|
||||
int avail_counters = get_available_counters(gpu, idx, args->flags);
|
||||
if (g.nr_countables > avail_counters) {
|
||||
/*
|
||||
* Defer error return until we process all groups, in
|
||||
* case there are other E2BIG groups:
|
||||
*/
|
||||
ret = UERR(E2BIG, dev, "groups[%d]: too few counters available", i);
|
||||
|
||||
if (args->flags & MSM_PERFCNTR_UPDATE) {
|
||||
/* Let userspace know how many counters are actually avail: */
|
||||
g.nr_countables = avail_counters;
|
||||
if (copy_to_user(userptr, &g, sz))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
group_idx[i] = idx;
|
||||
perfctx->reserved_counters[idx] = g.nr_countables;
|
||||
|
||||
/* +1 to catch duplicate zero sized groups: */
|
||||
nr_counters[idx] = g.nr_countables + 1;
|
||||
|
||||
if (args->flags & MSM_PERFCNTR_STREAM) {
|
||||
size_t sz = sizeof(uint32_t) * g.nr_countables;
|
||||
void __user *userptr = u64_to_user_ptr(g.countables);
|
||||
|
||||
if (copy_from_user(perfcntrs->groups[idx]->countables, userptr, sz))
|
||||
return -EFAULT;
|
||||
|
||||
/* Samples are 64b per countable: */
|
||||
bufsz += 2 * sz;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (args->flags & MSM_PERFCNTR_STREAM) {
|
||||
/*
|
||||
* Validate requested buffer size is large enough for at least
|
||||
* a single sample period.
|
||||
*
|
||||
* Note the circ_buf implementation needs to be 1 byte larger
|
||||
* than max it can hold (see CIRC_SPACE()).
|
||||
*/
|
||||
if (stream->fifo_size <= bufsz)
|
||||
return UERR(EINVAL, dev, "required buffer size: %zu", bufsz);
|
||||
|
||||
/* There aren't enough counters to hit this limit: */
|
||||
WARN_ON(bufsz > SZ_128M);
|
||||
|
||||
stream->period_size = bufsz;
|
||||
|
||||
void *buf __free(kfree) = kmalloc(stream->fifo_size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
FD_PREPARE(fdf, O_CLOEXEC,
|
||||
anon_inode_getfile("[msm_perfcntrs]", &stream_fops, stream, 0));
|
||||
if (fdf.err)
|
||||
return fdf.err;
|
||||
|
||||
INIT_WORK(&stream->sel_work, sel_worker);
|
||||
kthread_init_work(&stream->sample_work, sample_worker);
|
||||
init_waitqueue_head(&stream->poll_wq);
|
||||
hrtimer_setup(&stream->sample_timer, sample_timer,
|
||||
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
|
||||
stream->sel_fence = ++perfcntrs->sel_seqno;
|
||||
stream->group_idx = no_free_ptr(group_idx);
|
||||
stream->fifo.buf = no_free_ptr(buf);
|
||||
|
||||
/* commit the allocated counters, subtracting off original +1: */
|
||||
for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++)
|
||||
perfcntrs->groups[i]->allocated_counters = nr_counters[i] - 1;
|
||||
|
||||
perfcntrs->stream = no_free_ptr(stream);
|
||||
|
||||
msm_perfcntr_resume_locked(perfcntrs->stream);
|
||||
|
||||
stream_fd = fd_publish(fdf);
|
||||
} else {
|
||||
kfree(ctx->perfctx);
|
||||
ctx->perfctx = no_free_ptr(perfctx);
|
||||
}
|
||||
|
||||
return stream_fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* msm_perfcntr_group_idx - map idx of perfcntr group to group_idx
|
||||
* @stream: The global perfcntr stream
|
||||
* @n: The requested group_idx
|
||||
*
|
||||
* The PERFCNTR_CONFIG ioctl requested N counters/countables per perfcntr
|
||||
* group, but the order of groups is not required to match the order they
|
||||
* are defined in the perfcntr tables (which is not stable/UABI, only the
|
||||
* group names are UABI).
|
||||
*
|
||||
* But the order samples are returned in the stream should match the
|
||||
* order they are requested in the PERFCNTR_CONFIG ioctl. This helper
|
||||
* handles the order remapping.
|
||||
*
|
||||
* Returns an index into gpu->perfcntr_groups[] and perfcntrs->groups[].
|
||||
*/
|
||||
uint32_t
|
||||
msm_perfcntr_group_idx(const struct msm_perfcntr_stream *stream, uint32_t n)
|
||||
{
|
||||
WARN_ON_ONCE(n >= stream->nr_groups);
|
||||
return stream->group_idx[n];
|
||||
}
|
||||
|
||||
/**
|
||||
* msm_perfcntr_counter_base - get idx of the first counter in group
|
||||
* @stream: The global perfcntr stream
|
||||
* @group_idx: the index of the counter group
|
||||
*
|
||||
* For global counter collection, counters are allocated from the end
|
||||
* (last counter) while UMD allocates them from the start (0..N-1).
|
||||
* Since UMD always allocated them from the start this also minimizes
|
||||
* the chance of conflict when using old UMD which predates
|
||||
* PERFCNTR_CONFIG ioctl.
|
||||
*
|
||||
* Returns the index of first counter to use. An index into
|
||||
* msm_perfcntr_group::counters[].
|
||||
*/
|
||||
uint32_t
|
||||
msm_perfcntr_counter_base(const struct msm_perfcntr_stream *stream, uint32_t group_idx)
|
||||
{
|
||||
struct msm_gpu *gpu = stream->gpu;
|
||||
struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
|
||||
unsigned num_counters = gpu->perfcntr_groups[group_idx].num_counters;
|
||||
unsigned allocated_counters = perfcntrs->groups[group_idx]->allocated_counters;
|
||||
|
||||
return num_counters - allocated_counters;
|
||||
}
|
||||
|
||||
static void
|
||||
__msm_perfcntr_cleanup(struct msm_gpu *gpu, struct msm_perfcntr_state *perfcntrs)
|
||||
{
|
||||
struct device *dev = &gpu->pdev->dev;
|
||||
|
||||
for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++)
|
||||
devm_kfree(dev, perfcntrs->groups[i]);
|
||||
|
||||
devm_kfree(dev, perfcntrs);
|
||||
}
|
||||
|
||||
void
|
||||
msm_perfcntr_cleanup(struct msm_gpu *gpu)
|
||||
{
|
||||
if (!gpu->perfcntrs)
|
||||
return;
|
||||
|
||||
__msm_perfcntr_cleanup(gpu, gpu->perfcntrs);
|
||||
gpu->perfcntrs = NULL;
|
||||
}
|
||||
|
||||
struct msm_perfcntr_state *
|
||||
msm_perfcntr_init(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_perfcntr_state *perfcntrs;
|
||||
struct device *dev = &gpu->pdev->dev;
|
||||
size_t sz;
|
||||
|
||||
sz = struct_size(perfcntrs, groups, gpu->num_perfcntr_groups);
|
||||
perfcntrs = devm_kzalloc(dev, sz, GFP_KERNEL);
|
||||
if (!perfcntrs)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++) {
|
||||
const struct msm_perfcntr_group *group =
|
||||
&gpu->perfcntr_groups[i];
|
||||
|
||||
sz = struct_size(perfcntrs->groups[i], countables, group->num_counters);
|
||||
perfcntrs->groups[i] = devm_kzalloc(dev, sz, GFP_KERNEL);
|
||||
if (!perfcntrs->groups[i]) {
|
||||
__msm_perfcntr_cleanup(gpu, perfcntrs);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
return perfcntrs;
|
||||
}
|
||||
155
drivers/gpu/drm/msm/msm_perfcntr.h
Normal file
155
drivers/gpu/drm/msm/msm_perfcntr.h
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_PERFCNTR_H__
|
||||
#define __MSM_PERFCNTR_H__
|
||||
|
||||
#include "linux/array_size.h"
|
||||
#include "linux/circ_buf.h"
|
||||
#include "linux/hrtimer.h"
|
||||
#include "linux/kthread.h"
|
||||
#include "linux/wait.h"
|
||||
#include "linux/workqueue.h"
|
||||
|
||||
#include "adreno_common.xml.h"
|
||||
|
||||
/*
|
||||
* This is a subset of the tables used by mesa. We don't need to
|
||||
* enumerate the countables on the kernel side.
|
||||
*/
|
||||
|
||||
/* Describes a single counter: */
|
||||
struct msm_perfcntr_counter {
|
||||
/* offset of the SELect register to choose what to count: */
|
||||
unsigned select_reg;
|
||||
/* additional SEL regs to enable slice counters (gen8+) */
|
||||
unsigned slice_select_regs[2];
|
||||
/* offset of the lo/hi 32b to read current counter value: */
|
||||
unsigned counter_reg_lo;
|
||||
unsigned counter_reg_hi;
|
||||
/* TODO some counters have enable/clear registers */
|
||||
};
|
||||
|
||||
/* Describes an entire counter group: */
|
||||
struct msm_perfcntr_group {
|
||||
const char *name;
|
||||
enum adreno_pipe pipe;
|
||||
unsigned num_counters;
|
||||
const struct msm_perfcntr_counter *counters;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_perfcntr_stream - state for a single open stream fd
|
||||
*/
|
||||
struct msm_perfcntr_stream {
|
||||
/** @gpu: Back-link to the GPU */
|
||||
struct msm_gpu *gpu;
|
||||
|
||||
/** @sample_timer: Timer to sample counters */
|
||||
struct hrtimer sample_timer;
|
||||
|
||||
/** @poll_wq: Wait queue for waiting for OA data to be available */
|
||||
wait_queue_head_t poll_wq;
|
||||
|
||||
/** @sample_period_ns: Sampling period */
|
||||
uint64_t sample_period_ns;
|
||||
|
||||
/** @nr_groups: # of counter groups with enabled counters */
|
||||
uint32_t nr_groups;
|
||||
|
||||
/** @seqno: counter for collected samples */
|
||||
uint32_t seqno;
|
||||
|
||||
/** @sel_fence: Fence for SEL reg programming */
|
||||
uint32_t sel_fence;
|
||||
|
||||
/**
|
||||
* @sel_work: Worker for SEL reg programming
|
||||
*
|
||||
* Initial SEL reg programming (as opposed to restoring the SEL
|
||||
* regs on runpm resume) must run on the same ordered wq as is
|
||||
* used by drm_sched, to serialize it with GEM_SUBMITs written
|
||||
* into the same ringbuffer.
|
||||
*/
|
||||
struct work_struct sel_work;
|
||||
|
||||
/**
|
||||
* @sample_work: Worker for collecting samples
|
||||
*/
|
||||
struct kthread_work sample_work;
|
||||
|
||||
/**
|
||||
* @read_lock:
|
||||
*
|
||||
* Fifo access is synchronied on the producer side by virtue
|
||||
* of there being a single timer collecting samples and writing
|
||||
* into the fifo. It is protected on the consumer side by
|
||||
* @read_lock.
|
||||
*/
|
||||
struct mutex read_lock;
|
||||
|
||||
/**
|
||||
* @group_idx: array of nr_groups
|
||||
*
|
||||
* Maps the order of groups in PERFCNTR_CONFIG ioctl to group idx,
|
||||
* so that results in the results stream can be ordered to match
|
||||
* the ioctl call that setup the stream
|
||||
*/
|
||||
uint32_t *group_idx;
|
||||
|
||||
/** @fifo: circular buffer for samples */
|
||||
struct circ_buf fifo;
|
||||
|
||||
/** @fifo_size: circular buffer size */
|
||||
size_t fifo_size;
|
||||
|
||||
/** @period_size: size of data for single sampling period */
|
||||
size_t period_size;
|
||||
};
|
||||
|
||||
uint32_t msm_perfcntr_group_idx(const struct msm_perfcntr_stream *stream, uint32_t n);
|
||||
uint32_t msm_perfcntr_counter_base(const struct msm_perfcntr_stream *stream, uint32_t group_idx);
|
||||
|
||||
/**
|
||||
* struct msm_perfcntr_context_state - per-msm_context counter state
|
||||
*
|
||||
* A given counter can either be unused, reserved for global counter
|
||||
* collection exclusively, or reserved for local per-context counter
|
||||
* collection inclusively. Multiple contexts can reserve the same
|
||||
* counter, since SEL reg programming and counter begin/end sampling
|
||||
* happen locally (within a single GEM_SUBMIT ioctl).
|
||||
*/
|
||||
struct msm_perfcntr_context_state {
|
||||
/** @dummy: Some compilers dislike structs with only a flex array */
|
||||
unsigned dummy;
|
||||
|
||||
/**
|
||||
* @reserved_counters:
|
||||
*
|
||||
* The number of reserved counters indexed by perfcntr group.
|
||||
*/
|
||||
unsigned reserved_counters[];
|
||||
};
|
||||
|
||||
extern const struct msm_perfcntr_group a6xx_perfcntr_groups[];
|
||||
extern const unsigned a6xx_num_perfcntr_groups;
|
||||
|
||||
extern const struct msm_perfcntr_group a7xx_perfcntr_groups[];
|
||||
extern const unsigned a7xx_num_perfcntr_groups;
|
||||
|
||||
extern const struct msm_perfcntr_group a8xx_perfcntr_groups[];
|
||||
extern const unsigned a8xx_num_perfcntr_groups;
|
||||
|
||||
#define GROUP(_name, _pipe, _counters, _countables) { \
|
||||
.name = _name, \
|
||||
.pipe = _pipe, \
|
||||
.num_counters = ARRAY_SIZE(_counters), \
|
||||
.counters = _counters, \
|
||||
}
|
||||
|
||||
#define fd_perfcntr_counter msm_perfcntr_counter
|
||||
#define fd_perfcntr_group msm_perfcntr_group
|
||||
|
||||
#endif /* __MSM_PERFCNTR_H__ */
|
||||
|
|
@ -37,6 +37,8 @@ struct msm_rbmemptrs {
|
|||
volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT];
|
||||
volatile u64 ttbr0;
|
||||
volatile u32 context_idr;
|
||||
|
||||
volatile u32 perfcntr_fence;
|
||||
};
|
||||
|
||||
struct msm_cp_state {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sy
|
|||
|
||||
/* Some gpu families require additional setup for sysprof */
|
||||
if (gpu->funcs->sysprof_setup)
|
||||
gpu->funcs->sysprof_setup(gpu);
|
||||
gpu->funcs->sysprof_setup(gpu, false);
|
||||
|
||||
ctx->sysprof = sysprof;
|
||||
|
||||
|
|
@ -66,6 +66,7 @@ void __msm_context_destroy(struct kref *kref)
|
|||
drm_gpuvm_put(ctx->vm);
|
||||
kfree(ctx->comm);
|
||||
kfree(ctx->cmdline);
|
||||
kfree(ctx->perfctx);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
|
|
|
|||
109
drivers/gpu/drm/msm/registers/adreno/a2xx_perfcntrs.json
Normal file
109
drivers/gpu/drm/msm/registers/adreno/a2xx_perfcntrs.json
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"chip": "A2XX",
|
||||
"groups": [
|
||||
{
|
||||
"name": "CP",
|
||||
"num": 1,
|
||||
"select": "CP_PERFCOUNTER_SELECT",
|
||||
"counter_lo": "CP_PERFCOUNTER_LO",
|
||||
"counter_hi": "CP_PERFCOUNTER_HI",
|
||||
"countable_type": "a2xx_cp_perfcount_sel"
|
||||
},
|
||||
{
|
||||
"name": "PA_SU",
|
||||
"num": 4,
|
||||
"select": "PA_SU_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "PA_SU_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "PA_SU_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_su_perfcnt_select"
|
||||
},
|
||||
{
|
||||
"name": "PA_SC",
|
||||
"num": 1,
|
||||
"select": "PA_SC_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "PA_SC_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "PA_SC_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_sc_perfcnt_select"
|
||||
},
|
||||
{
|
||||
"name": "VGT",
|
||||
"num": 4,
|
||||
"select": "VGT_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "VGT_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "VGT_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_vgt_perfcount_select"
|
||||
},
|
||||
{
|
||||
"name": "TCR",
|
||||
"num": 2,
|
||||
"select": "TCR_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "TCR_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "TCR_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_tcr_perfcount_select"
|
||||
},
|
||||
{
|
||||
"name": "TP0",
|
||||
"num": 2,
|
||||
"select": "TP0_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "TP0_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "TP0_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_tp_perfcount_select"
|
||||
},
|
||||
{
|
||||
"name": "TCM",
|
||||
"num": 2,
|
||||
"select": "TCM_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "TCM_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "TCM_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_tcm_perfcount_select"
|
||||
},
|
||||
{
|
||||
"name": "TCF",
|
||||
"num": 12,
|
||||
"select": "TCF_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "TCF_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "TCF_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_tcf_perfcount_select"
|
||||
},
|
||||
{
|
||||
"name": "SQ",
|
||||
"num": 4,
|
||||
"select": "SQ_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "SQ_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "SQ_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_sq_perfcnt_select"
|
||||
},
|
||||
{
|
||||
"name": "SX",
|
||||
"num": 1,
|
||||
"select": "SX_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "SX_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "SX_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_sx_perfcnt_select"
|
||||
},
|
||||
{
|
||||
"name": "MH",
|
||||
"num": 2,
|
||||
"select": "MH_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "MH_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "MH_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_mh_perfcnt_select"
|
||||
},
|
||||
{
|
||||
"name": "RBBM",
|
||||
"num": 2,
|
||||
"select": "RBBM_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "RBBM_PERFCOUNTER{}_LO",
|
||||
"counter_hi": "RBBM_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_rbbm_perfcount1_sel"
|
||||
},
|
||||
{
|
||||
"name": "RB",
|
||||
"num": 4,
|
||||
"select": "RB_PERFCOUNTER{}_SELECT",
|
||||
"counter_lo": "RB_PERFCOUNTER{}_LOW",
|
||||
"counter_hi": "RB_PERFCOUNTER{}_HI",
|
||||
"countable_type": "a2xx_rb_perfcnt_select"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1330,11 +1330,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
</reg32>
|
||||
<reg32 offset="0x22c5" name="SP_VS_CTRL_REG1">
|
||||
<bitfield name="CONSTLENGTH" low="0" high="9" type="uint"/>
|
||||
<!--
|
||||
not sure about full vs half const.. I can't get blob generate
|
||||
something with a mediump/lowp uniform.
|
||||
-->
|
||||
<bitfield name="CONSTFOOTPRINT" low="10" high="19" type="uint"/>
|
||||
<bitfield name="CONSTMAXID" low="10" high="19" type="uint"/>
|
||||
<bitfield name="INITIALOUTSTANDING" low="24" high="30" type="uint"/>
|
||||
</reg32>
|
||||
<reg32 offset="0x22c6" name="SP_VS_PARAM_REG">
|
||||
|
|
@ -1420,7 +1416,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
</reg32>
|
||||
<reg32 offset="0x22e1" name="SP_FS_CTRL_REG1">
|
||||
<bitfield name="CONSTLENGTH" low="0" high="9" type="uint"/>
|
||||
<bitfield name="CONSTFOOTPRINT" low="10" high="19" type="uint"/>
|
||||
<bitfield name="CONSTMAXID" low="10" high="19" type="uint"/>
|
||||
<bitfield name="INITIALOUTSTANDING" low="20" high="23" type="uint"/>
|
||||
<bitfield name="HALFPRECVAROFFSET" low="24" high="30" type="uint"/>
|
||||
</reg32>
|
||||
|
|
|
|||
|
|
@ -1418,8 +1418,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<bitfield name="HEIGHT" low="9" high="16" shr="5" type="uint"/>
|
||||
<!-- b17 maybe BYPASS like RB_CNTL, but reg not written for bypass -->
|
||||
</reg32>
|
||||
<reg32 offset="0x0bc3" name="VSC_SIZE_ADDRESS_LO"/>
|
||||
<reg32 offset="0x0bc4" name="VSC_SIZE_ADDRESS_HI"/>
|
||||
<reg64 offset="0x0bc3" name="VSC_SIZE_ADDRESS" type="waddress"/>
|
||||
<reg32 offset="0x0bc5" name="UNKNOWN_0BC5"/> <!-- always 00000000? -->
|
||||
<reg32 offset="0x0bc6" name="UNKNOWN_0BC6"/> <!-- always 00000000? -->
|
||||
<array offset="0x0bd0" name="VSC_PIPE_CONFIG" stride="1" length="16">
|
||||
|
|
@ -1498,12 +1497,10 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
</reg32>
|
||||
<reg32 offset="0x0d01" name="PC_ADDR_MODE_CNTL" type="a5xx_address_mode"/>
|
||||
<reg32 offset="0x0d02" name="PC_MODE_CNTL"/> <!-- always 0000001f? -->
|
||||
<reg32 offset="0x0d04" name="PC_INDEX_BUF_LO"/>
|
||||
<reg32 offset="0x0d05" name="PC_INDEX_BUF_HI"/>
|
||||
<reg64 offset="0x0d04" name="PC_INDEX_BUF" type="waddress"/>
|
||||
<reg32 offset="0x0d06" name="PC_START_INDEX"/>
|
||||
<reg32 offset="0x0d07" name="PC_MAX_INDEX"/>
|
||||
<reg32 offset="0x0d08" name="PC_TESSFACTOR_ADDR_LO"/>
|
||||
<reg32 offset="0x0d09" name="PC_TESSFACTOR_ADDR_HI"/>
|
||||
<reg64 offset="0x0d08" name="PC_TESSFACTOR_ADDR" type="waddress"/>
|
||||
<reg32 offset="0x0d10" name="PC_PERFCTR_PC_SEL_0" type="a5xx_pc_perfcounter_select"/>
|
||||
<reg32 offset="0x0d11" name="PC_PERFCTR_PC_SEL_1" type="a5xx_pc_perfcounter_select"/>
|
||||
<reg32 offset="0x0d12" name="PC_PERFCTR_PC_SEL_2" type="a5xx_pc_perfcounter_select"/>
|
||||
|
|
@ -1555,20 +1552,14 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 offset="0x0e80" name="UCHE_ADDR_MODE_CNTL" type="a5xx_address_mode"/>
|
||||
<reg32 offset="0x0e81" name="UCHE_MODE_CNTL"/>
|
||||
<reg32 offset="0x0e82" name="UCHE_SVM_CNTL"/>
|
||||
<reg32 offset="0x0e87" name="UCHE_WRITE_THRU_BASE_LO"/>
|
||||
<reg32 offset="0x0e88" name="UCHE_WRITE_THRU_BASE_HI"/>
|
||||
<reg32 offset="0x0e89" name="UCHE_TRAP_BASE_LO"/>
|
||||
<reg32 offset="0x0e8a" name="UCHE_TRAP_BASE_HI"/>
|
||||
<reg32 offset="0x0e8b" name="UCHE_GMEM_RANGE_MIN_LO"/>
|
||||
<reg32 offset="0x0e8c" name="UCHE_GMEM_RANGE_MIN_HI"/>
|
||||
<reg32 offset="0x0e8d" name="UCHE_GMEM_RANGE_MAX_LO"/>
|
||||
<reg32 offset="0x0e8e" name="UCHE_GMEM_RANGE_MAX_HI"/>
|
||||
<reg64 offset="0x0e87" name="UCHE_WRITE_THRU_BASE" type="waddress"/>
|
||||
<reg64 offset="0x0e89" name="UCHE_TRAP_BASE" type="waddress"/>
|
||||
<reg64 offset="0x0e8b" name="UCHE_GMEM_RANGE_MIN" type="waddress"/>
|
||||
<reg64 offset="0x0e8d" name="UCHE_GMEM_RANGE_MAX" type="waddress"/>
|
||||
<reg32 offset="0x0e8f" name="UCHE_DBG_ECO_CNTL_2"/>
|
||||
<reg32 offset="0x0e90" name="UCHE_DBG_ECO_CNTL"/>
|
||||
<reg32 offset="0x0e91" name="UCHE_CACHE_INVALIDATE_MIN_LO"/>
|
||||
<reg32 offset="0x0e92" name="UCHE_CACHE_INVALIDATE_MIN_HI"/>
|
||||
<reg32 offset="0x0e93" name="UCHE_CACHE_INVALIDATE_MAX_LO"/>
|
||||
<reg32 offset="0x0e94" name="UCHE_CACHE_INVALIDATE_MAX_HI"/>
|
||||
<reg64 offset="0x0e91" name="UCHE_CACHE_INVALIDATE_MIN" type="address"/>
|
||||
<reg64 offset="0x0e93" name="UCHE_CACHE_INVALIDATE_MAX" type="address"/>
|
||||
<reg32 offset="0x0e95" name="UCHE_CACHE_INVALIDATE"/>
|
||||
<reg32 offset="0x0e96" name="UCHE_CACHE_WAYS"/>
|
||||
<reg32 offset="0x0ea0" name="UCHE_PERFCTR_UCHE_SEL_0" type="a5xx_uche_perfcounter_select"/>
|
||||
|
|
@ -1583,8 +1574,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 offset="0x0ea9" name="UCHE_POWERCTR_UCHE_SEL_1"/>
|
||||
<reg32 offset="0x0eaa" name="UCHE_POWERCTR_UCHE_SEL_2"/>
|
||||
<reg32 offset="0x0eab" name="UCHE_POWERCTR_UCHE_SEL_3"/>
|
||||
<reg32 offset="0x0eb1" name="UCHE_TRAP_LOG_LO"/>
|
||||
<reg32 offset="0x0eb2" name="UCHE_TRAP_LOG_HI"/>
|
||||
<reg64 offset="0x0eb1" name="UCHE_TRAP_LOG" type="waddress"/>
|
||||
|
||||
<reg32 offset="0x0ec0" name="SP_DBG_ECO_CNTL"/>
|
||||
<reg32 offset="0x0ec1" name="SP_ADDR_MODE_CNTL" type="a5xx_address_mode"/>
|
||||
|
|
@ -1923,8 +1913,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
invalidates the LRZ buffer? (Or just the covered positions?
|
||||
-->
|
||||
</reg32>
|
||||
<reg32 offset="0xe101" name="GRAS_LRZ_BUFFER_BASE_LO"/>
|
||||
<reg32 offset="0xe102" name="GRAS_LRZ_BUFFER_BASE_HI"/>
|
||||
<reg64 offset="0xe101" name="GRAS_LRZ_BUFFER_BASE" type="waddress"/>
|
||||
<!--
|
||||
lzr pitch is depth pitch (in pixels) / 8 (aligned to 32)..
|
||||
-->
|
||||
|
|
@ -1933,8 +1922,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
is also divided by 8 (ie. covers 8x8 pixels)
|
||||
</doc>
|
||||
<reg32 offset="0xe103" name="GRAS_LRZ_BUFFER_PITCH" shr="5" type="uint"/>
|
||||
<reg32 offset="0xe104" name="GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO"/>
|
||||
<reg32 offset="0xe105" name="GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_HI"/>
|
||||
<reg64 offset="0xe104" name="GRAS_LRZ_FAST_CLEAR_BUFFER_BASE" type="waddress"/>
|
||||
|
||||
<reg32 offset="0xe140" name="RB_CNTL">
|
||||
<bitfield name="WIDTH" low="0" high="7" shr="5" type="uint"/>
|
||||
|
|
@ -2035,8 +2023,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
-->
|
||||
<reg32 offset="0x3" name="PITCH" shr="6" type="uint"/>
|
||||
<reg32 offset="0x4" name="ARRAY_PITCH" shr="6" type="uint"/>
|
||||
<reg32 offset="0x5" name="BASE_LO"/>
|
||||
<reg32 offset="0x6" name="BASE_HI"/>
|
||||
<reg64 offset="0x5" name="BASE" type="waddress"/>
|
||||
</array>
|
||||
<reg32 offset="0xe1a0" name="RB_BLEND_RED">
|
||||
<bitfield name="UINT" low="0" high="7" type="hex"/>
|
||||
|
|
@ -2089,8 +2076,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<reg32 offset="0xe1b2" name="RB_DEPTH_BUFFER_INFO">
|
||||
<bitfield name="DEPTH_FORMAT" low="0" high="2" type="a5xx_depth_format"/>
|
||||
</reg32>
|
||||
<reg32 offset="0xe1b3" name="RB_DEPTH_BUFFER_BASE_LO"/>
|
||||
<reg32 offset="0xe1b4" name="RB_DEPTH_BUFFER_BASE_HI"/>
|
||||
<reg64 offset="0xe1b3" name="RB_DEPTH_BUFFER_BASE" type="waddress"/>
|
||||
<reg32 offset="0xe1b5" name="RB_DEPTH_BUFFER_PITCH" shr="6" type="uint">
|
||||
<doc>stride of depth/stencil buffer</doc>
|
||||
</reg32>
|
||||
|
|
@ -2119,8 +2105,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<reg32 offset="0xe1c1" name="RB_STENCIL_INFO">
|
||||
<bitfield name="SEPARATE_STENCIL" pos="0" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="0xe1c2" name="RB_STENCIL_BASE_LO"/>
|
||||
<reg32 offset="0xe1c3" name="RB_STENCIL_BASE_HI"/>
|
||||
<reg64 offset="0xe1c2" name="RB_STENCIL_BASE" type="waddress"/>
|
||||
<reg32 offset="0xe1c4" name="RB_STENCIL_PITCH" shr="6" type="uint"/>
|
||||
<reg32 offset="0xe1c5" name="RB_STENCIL_ARRAY_PITCH" shr="6" type="uint"/>
|
||||
<reg32 offset="0xe1c6" name="RB_STENCILREFMASK" type="adreno_rb_stencilrefmask"/>
|
||||
|
|
@ -2163,8 +2148,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
also for gmem->mem preserving tiling
|
||||
-->
|
||||
</reg32>
|
||||
<reg32 offset="0xe214" name="RB_BLIT_DST_LO"/>
|
||||
<reg32 offset="0xe215" name="RB_BLIT_DST_HI"/>
|
||||
<reg64 offset="0xe214" name="RB_BLIT_DST" type="waddress"/>
|
||||
<reg32 offset="0xe216" name="RB_BLIT_DST_PITCH" shr="6" type="uint"/>
|
||||
<!-- array-pitch is size of layer -->
|
||||
<reg32 offset="0xe217" name="RB_BLIT_DST_ARRAY_PITCH" shr="6" type="uint"/>
|
||||
|
|
@ -2235,25 +2219,22 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
|
||||
|
||||
</doc>
|
||||
<reg32 offset="0xe240" name="RB_DEPTH_FLAG_BUFFER_BASE_LO"/>
|
||||
<reg32 offset="0xe241" name="RB_DEPTH_FLAG_BUFFER_BASE_HI"/>
|
||||
<reg64 offset="0xe240" name="RB_DEPTH_FLAG_BUFFER_BASE" type="waddress"/>
|
||||
<reg32 offset="0xe242" name="RB_DEPTH_FLAG_BUFFER_PITCH">
|
||||
</reg32>
|
||||
<array offset="0xe243" name="RB_MRT_FLAG_BUFFER" stride="4" length="8">
|
||||
<reg32 offset="0" name="ADDR_LO"/>
|
||||
<reg64 offset="0" name="ADDR" type="waddress"/>
|
||||
<reg32 offset="1" name="ADDR_HI"/>
|
||||
<reg32 offset="2" name="PITCH" shr="6" type="uint"/>
|
||||
<!-- array-pitch is size of layer -->
|
||||
<reg32 offset="3" name="ARRAY_PITCH" shr="6" type="uint"/>
|
||||
</array>
|
||||
<reg32 offset="0xe263" name="RB_BLIT_FLAG_DST_LO"/>
|
||||
<reg32 offset="0xe264" name="RB_BLIT_FLAG_DST_HI"/>
|
||||
<reg64 offset="0xe263" name="RB_BLIT_FLAG_DST" type="waddress"/>
|
||||
<reg32 offset="0xe265" name="RB_BLIT_FLAG_DST_PITCH" shr="6" type="uint"/>
|
||||
<!-- array-pitch is size of layer -->
|
||||
<reg32 offset="0xe266" name="RB_BLIT_FLAG_DST_ARRAY_PITCH" shr="6" type="uint"/>
|
||||
|
||||
<reg32 offset="0xe267" name="RB_SAMPLE_COUNT_ADDR_LO"/>
|
||||
<reg32 offset="0xe268" name="RB_SAMPLE_COUNT_ADDR_HI"/>
|
||||
<reg64 offset="0xe267" name="RB_SAMPLE_COUNT_ADDR" type="waddress"/>
|
||||
|
||||
<reg32 offset="0xe280" name="VPC_CNTL_0">
|
||||
<doc>
|
||||
|
|
@ -2357,13 +2338,11 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<bitfield name="B_EN" pos="23" type="boolean"/>
|
||||
</reg32>
|
||||
<array offset="0xe2a7" name="VPC_SO" stride="7" length="4">
|
||||
<reg32 offset="0" name="BUFFER_BASE_LO"/>
|
||||
<reg32 offset="1" name="BUFFER_BASE_HI"/>
|
||||
<reg64 offset="0" name="BUFFER_BASE" type="waddress"/>
|
||||
<reg32 offset="2" name="BUFFER_SIZE"/>
|
||||
<reg32 offset="3" name="NCOMP"/> <!-- component count -->
|
||||
<reg32 offset="4" name="BUFFER_OFFSET"/>
|
||||
<reg32 offset="5" name="FLUSH_BASE_LO"/>
|
||||
<reg32 offset="6" name="FLUSH_BASE_HI"/>
|
||||
<reg64 offset="5" name="FLUSH_BASE" type="waddress"/>
|
||||
</array>
|
||||
|
||||
<reg32 offset="0xe384" name="PC_PRIMITIVE_CNTL">
|
||||
|
|
@ -2423,8 +2402,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<reg32 offset="0xe408" name="VFD_INDEX_OFFSET"/>
|
||||
<reg32 offset="0xe409" name="VFD_INSTANCE_START_OFFSET"/>
|
||||
<array offset="0xe40a" name="VFD_FETCH" stride="4" length="32">
|
||||
<reg32 offset="0x0" name="BASE_LO"/>
|
||||
<reg32 offset="0x1" name="BASE_HI"/>
|
||||
<reg64 offset="0x0" name="BASE" type="address"/>
|
||||
<reg32 offset="0x2" name="SIZE" type="uint"/>
|
||||
<reg32 offset="0x3" name="STRIDE" type="uint"/>
|
||||
</array>
|
||||
|
|
@ -2475,7 +2453,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<bitfield name="VARYING" pos="16" type="boolean"/>
|
||||
<bitfield name="PIXLODENABLE" pos="20" type="boolean"/>
|
||||
<!-- seems to be nesting level for flow control:.. -->
|
||||
<bitfield name="BRANCHSTACK" low="25" high="31" type="uint"/>
|
||||
<bitfield name="BRANCHSTACK" low="24" high="31" type="uint"/>
|
||||
</bitset>
|
||||
<!-- assuming things appear in same relative order as a4xx: -->
|
||||
<!-- duplicated exactly w/ corresponding HLSQ_ regs starting at 0xe78b.. -->
|
||||
|
|
@ -2516,8 +2494,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
</reg32>
|
||||
</array>
|
||||
<reg32 offset="0xe5ab" name="UNKNOWN_E5AB"/>
|
||||
<reg32 offset="0xe5ac" name="SP_VS_OBJ_START_LO"/>
|
||||
<reg32 offset="0xe5ad" name="SP_VS_OBJ_START_HI"/>
|
||||
<reg64 offset="0xe5ac" name="SP_VS_OBJ_START" type="address"/>
|
||||
|
||||
<bitset name="a5xx_sp_xs_pvt_mem_param" inline="yes">
|
||||
<bitfield name="MEMSIZEPERITEM" low="0" high="7" shr="9">
|
||||
|
|
@ -2538,8 +2515,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<reg32 offset="0xe5b1" name="SP_VS_PVT_MEM_SIZE" type="a5xx_sp_xs_pvt_mem_size"/>
|
||||
<reg32 offset="0xe5c0" name="SP_FS_CTRL_REG0" type="a5xx_sp_xs_ctrl_reg0"/>
|
||||
<reg32 offset="0xe5c2" name="UNKNOWN_E5C2"/>
|
||||
<reg32 offset="0xe5c3" name="SP_FS_OBJ_START_LO"/>
|
||||
<reg32 offset="0xe5c4" name="SP_FS_OBJ_START_HI"/>
|
||||
<reg64 offset="0xe5c3" name="SP_FS_OBJ_START" type="address"/>
|
||||
<reg32 offset="0xe5c5" name="SP_FS_PVT_MEM_PARAM" type="a5xx_sp_xs_pvt_mem_param"/>
|
||||
<reg64 offset="0xe5c6" name="SP_FS_PVT_MEM_ADDR" type="waddress" align="32"/>
|
||||
<reg32 offset="0xe5c8" name="SP_FS_PVT_MEM_SIZE" type="a5xx_sp_xs_pvt_mem_size"/>
|
||||
|
|
@ -2577,8 +2553,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<reg32 offset="0xe5db" name="UNKNOWN_E5DB"/>
|
||||
<reg32 offset="0xe5f0" name="SP_CS_CTRL_REG0" type="a5xx_sp_xs_ctrl_reg0"/>
|
||||
<reg32 offset="0xe5f2" name="UNKNOWN_E5F2"/>
|
||||
<reg32 offset="0xe5f3" name="SP_CS_OBJ_START_LO"/>
|
||||
<reg32 offset="0xe5f4" name="SP_CS_OBJ_START_HI"/>
|
||||
<reg64 offset="0xe5f3" name="SP_CS_OBJ_START" type="address"/>
|
||||
<reg32 offset="0xe5f5" name="SP_CS_PVT_MEM_PARAM" type="a5xx_sp_xs_pvt_mem_param"/>
|
||||
<reg64 offset="0xe5f6" name="SP_CS_PVT_MEM_ADDR" type="waddress" align="32"/>
|
||||
<reg32 offset="0xe5f8" name="SP_CS_PVT_MEM_SIZE" type="a5xx_sp_xs_pvt_mem_size"/>
|
||||
|
|
@ -2587,22 +2562,19 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
|
||||
<reg32 offset="0xe600" name="SP_HS_CTRL_REG0" type="a5xx_sp_xs_ctrl_reg0"/>
|
||||
<reg32 offset="0xe602" name="UNKNOWN_E602"/>
|
||||
<reg32 offset="0xe603" name="SP_HS_OBJ_START_LO"/>
|
||||
<reg32 offset="0xe604" name="SP_HS_OBJ_START_HI"/>
|
||||
<reg64 offset="0xe603" name="SP_HS_OBJ_START" type="address"/>
|
||||
<reg32 offset="0xe605" name="SP_HS_PVT_MEM_PARAM" type="a5xx_sp_xs_pvt_mem_param"/>
|
||||
<reg64 offset="0xe606" name="SP_HS_PVT_MEM_ADDR" type="waddress" align="32"/>
|
||||
<reg32 offset="0xe608" name="SP_HS_PVT_MEM_SIZE" type="a5xx_sp_xs_pvt_mem_size"/>
|
||||
<reg32 offset="0xe610" name="SP_DS_CTRL_REG0" type="a5xx_sp_xs_ctrl_reg0"/>
|
||||
<reg32 offset="0xe62b" name="UNKNOWN_E62B"/>
|
||||
<reg32 offset="0xe62c" name="SP_DS_OBJ_START_LO"/>
|
||||
<reg32 offset="0xe62d" name="SP_DS_OBJ_START_HI"/>
|
||||
<reg64 offset="0xe62c" name="SP_DS_OBJ_START" type="address"/>
|
||||
<reg32 offset="0xe62e" name="SP_DS_PVT_MEM_PARAM" type="a5xx_sp_xs_pvt_mem_param"/>
|
||||
<reg64 offset="0xe62f" name="SP_DS_PVT_MEM_ADDR" type="waddress" align="32"/>
|
||||
<reg32 offset="0xe631" name="SP_DS_PVT_MEM_SIZE" type="a5xx_sp_xs_pvt_mem_size"/>
|
||||
<reg32 offset="0xe640" name="SP_GS_CTRL_REG0" type="a5xx_sp_xs_ctrl_reg0"/>
|
||||
<reg32 offset="0xe65b" name="UNKNOWN_E65B"/>
|
||||
<reg32 offset="0xe65c" name="SP_GS_OBJ_START_LO"/>
|
||||
<reg32 offset="0xe65d" name="SP_GS_OBJ_START_HI"/>
|
||||
<reg64 offset="0xe65c" name="SP_GS_OBJ_START" type="address"/>
|
||||
<reg32 offset="0xe65e" name="SP_GS_PVT_MEM_PARAM" type="a5xx_sp_xs_pvt_mem_param"/>
|
||||
<reg64 offset="0xe65f" name="SP_GS_PVT_MEM_ADDR" type="waddress" align="32"/>
|
||||
<reg32 offset="0xe661" name="SP_GS_PVT_MEM_SIZE" type="a5xx_sp_xs_pvt_mem_size"/>
|
||||
|
|
@ -2615,8 +2587,7 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<bitfield name="MSAA_DISABLE" pos="2" type="boolean"/>
|
||||
</reg32>
|
||||
<!-- either blob is doing it wrong, or this is not per-stage anymore: -->
|
||||
<reg32 offset="0xe706" name="TPL1_TP_BORDER_COLOR_BASE_ADDR_LO"/>
|
||||
<reg32 offset="0xe707" name="TPL1_TP_BORDER_COLOR_BASE_ADDR_HI"/>
|
||||
<reg64 offset="0xe706" name="TPL1_TP_BORDER_COLOR_BASE_ADDR" type="address"/>
|
||||
|
||||
<!--
|
||||
so these have the same info that is normally in the CP_LOAD_STATE
|
||||
|
|
@ -2628,35 +2599,23 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
<reg32 offset="0xe702" name="TPL1_DS_TEX_COUNT" type="uint"/>
|
||||
<reg32 offset="0xe703" name="TPL1_GS_TEX_COUNT" type="uint"/>
|
||||
|
||||
<reg32 offset="0xe722" name="TPL1_VS_TEX_SAMP_LO"/>
|
||||
<reg32 offset="0xe723" name="TPL1_VS_TEX_SAMP_HI"/>
|
||||
<reg32 offset="0xe724" name="TPL1_HS_TEX_SAMP_LO"/>
|
||||
<reg32 offset="0xe725" name="TPL1_HS_TEX_SAMP_HI"/>
|
||||
<reg32 offset="0xe726" name="TPL1_DS_TEX_SAMP_LO"/>
|
||||
<reg32 offset="0xe727" name="TPL1_DS_TEX_SAMP_HI"/>
|
||||
<reg32 offset="0xe728" name="TPL1_GS_TEX_SAMP_LO"/>
|
||||
<reg32 offset="0xe729" name="TPL1_GS_TEX_SAMP_HI"/>
|
||||
<reg64 offset="0xe722" name="TPL1_VS_TEX_SAMP" type="address"/>
|
||||
<reg64 offset="0xe724" name="TPL1_HS_TEX_SAMP" type="address"/>
|
||||
<reg64 offset="0xe726" name="TPL1_DS_TEX_SAMP" type="address"/>
|
||||
<reg64 offset="0xe728" name="TPL1_GS_TEX_SAMP" type="address"/>
|
||||
|
||||
<reg32 offset="0xe72a" name="TPL1_VS_TEX_CONST_LO"/>
|
||||
<reg32 offset="0xe72b" name="TPL1_VS_TEX_CONST_HI"/>
|
||||
<reg32 offset="0xe72c" name="TPL1_HS_TEX_CONST_LO"/>
|
||||
<reg32 offset="0xe72d" name="TPL1_HS_TEX_CONST_HI"/>
|
||||
<reg32 offset="0xe72e" name="TPL1_DS_TEX_CONST_LO"/>
|
||||
<reg32 offset="0xe72f" name="TPL1_DS_TEX_CONST_HI"/>
|
||||
<reg32 offset="0xe730" name="TPL1_GS_TEX_CONST_LO"/>
|
||||
<reg32 offset="0xe731" name="TPL1_GS_TEX_CONST_HI"/>
|
||||
<reg64 offset="0xe72a" name="TPL1_VS_TEX_CONST" type="address"/>
|
||||
<reg64 offset="0xe72c" name="TPL1_HS_TEX_CONST" type="address"/>
|
||||
<reg64 offset="0xe72e" name="TPL1_DS_TEX_CONST" type="address"/>
|
||||
<reg64 offset="0xe730" name="TPL1_GS_TEX_CONST" type="address"/>
|
||||
|
||||
<reg32 offset="0xe750" name="TPL1_FS_TEX_COUNT" type="uint"/>
|
||||
<reg32 offset="0xe751" name="TPL1_CS_TEX_COUNT" type="uint"/>
|
||||
|
||||
<reg32 offset="0xe75a" name="TPL1_FS_TEX_SAMP_LO"/>
|
||||
<reg32 offset="0xe75b" name="TPL1_FS_TEX_SAMP_HI"/>
|
||||
<reg32 offset="0xe75c" name="TPL1_CS_TEX_SAMP_LO"/>
|
||||
<reg32 offset="0xe75d" name="TPL1_CS_TEX_SAMP_HI"/>
|
||||
<reg32 offset="0xe75e" name="TPL1_FS_TEX_CONST_LO"/>
|
||||
<reg32 offset="0xe75f" name="TPL1_FS_TEX_CONST_HI"/>
|
||||
<reg32 offset="0xe760" name="TPL1_CS_TEX_CONST_LO"/>
|
||||
<reg32 offset="0xe761" name="TPL1_CS_TEX_CONST_HI"/>
|
||||
<reg64 offset="0xe75a" name="TPL1_FS_TEX_SAMP" type="address"/>
|
||||
<reg64 offset="0xe75c" name="TPL1_CS_TEX_SAMP" type="address"/>
|
||||
<reg64 offset="0xe75e" name="TPL1_FS_TEX_CONST" type="address"/>
|
||||
<reg64 offset="0xe760" name="TPL1_CS_TEX_CONST" type="address"/>
|
||||
|
||||
<reg32 offset="0xe764" name="TPL1_TP_FS_ROTATION_CNTL"/>
|
||||
|
||||
|
|
@ -2809,25 +2768,21 @@ bit 7 for RECTLIST (clear) when z32s8 (used for clear of depth32? not set
|
|||
</bitset>
|
||||
|
||||
<reg32 offset="0x2107" name="RB_2D_SRC_INFO" type="a5xx_2d_surf_info"/>
|
||||
<reg32 offset="0x2108" name="RB_2D_SRC_LO"/>
|
||||
<reg32 offset="0x2109" name="RB_2D_SRC_HI"/>
|
||||
<reg64 offset="0x2108" name="RB_2D_SRC" type="address"/>
|
||||
<reg32 offset="0x210a" name="RB_2D_SRC_SIZE">
|
||||
<bitfield name="PITCH" low="0" high="15" shr="6" type="uint"/>
|
||||
<bitfield name="ARRAY_PITCH" low="16" high="31" shr="6" type="uint"/>
|
||||
</reg32>
|
||||
|
||||
<reg32 offset="0x2110" name="RB_2D_DST_INFO" type="a5xx_2d_surf_info"/>
|
||||
<reg32 offset="0x2111" name="RB_2D_DST_LO"/>
|
||||
<reg32 offset="0x2112" name="RB_2D_DST_HI"/>
|
||||
<reg64 offset="0x2111" name="RB_2D_DST" type="address"/>
|
||||
<reg32 offset="0x2113" name="RB_2D_DST_SIZE">
|
||||
<bitfield name="PITCH" low="0" high="15" shr="6" type="uint"/>
|
||||
<bitfield name="ARRAY_PITCH" low="16" high="31" shr="6" type="uint"/>
|
||||
</reg32>
|
||||
<reg32 offset="0x2140" name="RB_2D_SRC_FLAGS_LO"/>
|
||||
<reg32 offset="0x2141" name="RB_2D_SRC_FLAGS_HI"/>
|
||||
<reg64 offset="0x2140" name="RB_2D_SRC_FLAGS" type="address"/>
|
||||
<reg32 offset="0x2142" name="RB_2D_SRC_FLAGS_PITCH" shr="6" type="uint"/>
|
||||
<reg32 offset="0x2143" name="RB_2D_DST_FLAGS_LO"/>
|
||||
<reg32 offset="0x2144" name="RB_2D_DST_FLAGS_HI"/>
|
||||
<reg64 offset="0x2143" name="RB_2D_DST_FLAGS" type="address"/>
|
||||
<reg32 offset="0x2145" name="RB_2D_DST_FLAGS_PITCH" shr="6" type="uint"/>
|
||||
<reg32 offset="0x2180" name="GRAS_2D_BLIT_CNTL"/> <!-- same as 0x2100 -->
|
||||
<!-- looks same as 0x2107: -->
|
||||
|
|
|
|||
128
drivers/gpu/drm/msm/registers/adreno/a5xx_perfcntrs.json
Normal file
128
drivers/gpu/drm/msm/registers/adreno/a5xx_perfcntrs.json
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
{
|
||||
"chip": "A5XX",
|
||||
"groups": [
|
||||
{
|
||||
"name": "CP",
|
||||
"num": 8,
|
||||
"reserved": [ 0 ],
|
||||
"select": "CP_PERFCTR_CP_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_CP_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_CP_{}_HI",
|
||||
"countable_type": "a5xx_cp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "CCU",
|
||||
"num": 4,
|
||||
"select": "RB_PERFCTR_CCU_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_CCU_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_CCU_{}_HI",
|
||||
"countable_type": "a5xx_ccu_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TSE",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_TSE_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_TSE_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_TSE_{}_HI",
|
||||
"countable_type": "a5xx_tse_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RAS",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_RAS_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_RAS_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_RAS_{}_HI",
|
||||
"countable_type": "a5xx_ras_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "LRZ",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_LRZ_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_LRZ_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_LRZ_{}_HI",
|
||||
"countable_type": "a5xx_lrz_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "HLSQ",
|
||||
"num": 8,
|
||||
"select": "HLSQ_PERFCTR_HLSQ_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_HLSQ_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_HLSQ_{}_HI",
|
||||
"countable_type": "a5xx_hlsq_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "PC",
|
||||
"num": 8,
|
||||
"select": "PC_PERFCTR_PC_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_PC_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_PC_{}_HI",
|
||||
"countable_type": "a5xx_pc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RB",
|
||||
"num": 8,
|
||||
"select": "RB_PERFCTR_RB_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_RB_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_RB_{}_HI",
|
||||
"countable_type": "a5xx_rb_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RBBM",
|
||||
"num": 4,
|
||||
"reserved": [ 0 ],
|
||||
"select": "RBBM_PERFCTR_RBBM_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_RBBM_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_RBBM_{}_HI",
|
||||
"countable_type": "a5xx_rbbm_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "SP",
|
||||
"num": 12,
|
||||
"reserved": [ 0 ],
|
||||
"select": "SP_PERFCTR_SP_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_SP_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_SP_{}_HI",
|
||||
"countable_type": "a5xx_sp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TP",
|
||||
"num": 8,
|
||||
"select": "TPL1_PERFCTR_TP_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_TP_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_TP_{}_HI",
|
||||
"countable_type": "a5xx_tp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "UCHE",
|
||||
"num": 8,
|
||||
"select": "UCHE_PERFCTR_UCHE_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_UCHE_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_UCHE_{}_HI",
|
||||
"countable_type": "a5xx_uche_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VFD",
|
||||
"num": 8,
|
||||
"select": "VFD_PERFCTR_VFD_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_VFD_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_VFD_{}_HI",
|
||||
"countable_type": "a5xx_vfd_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VPC",
|
||||
"num": 4,
|
||||
"select": "VPC_PERFCTR_VPC_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_VPC_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_VPC_{}_HI",
|
||||
"countable_type": "a5xx_vpc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VSC",
|
||||
"num": 2,
|
||||
"select": "VSC_PERFCTR_VSC_SEL_{}",
|
||||
"counter_lo": "RBBM_PERFCTR_VSC_{}_LO",
|
||||
"counter_hi": "RBBM_PERFCTR_VSC_{}_HI",
|
||||
"countable_type": "a5xx_vsc_perfcounter_select"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -45,19 +45,21 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 offset="3" name="3"/>
|
||||
</domain>
|
||||
|
||||
<domain name="A6XX_TEX_CONST" width="32" varset="chip">
|
||||
<domain name="A6XX_TEX_MEMOBJ" width="32" varset="desctype">
|
||||
<doc>Texture constant dwords</doc>
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode"/>
|
||||
<bitfield name="SRGB" pos="2" type="boolean"/>
|
||||
<bitfield name="SWIZ_X" low="4" high="6" type="a6xx_tex_swiz"/>
|
||||
<bitfield name="SWIZ_Y" low="7" high="9" type="a6xx_tex_swiz"/>
|
||||
<bitfield name="SWIZ_Z" low="10" high="12" type="a6xx_tex_swiz"/>
|
||||
<bitfield name="SWIZ_W" low="13" high="15" type="a6xx_tex_swiz"/>
|
||||
<bitfield name="MIPLVLS" low="16" high="19" type="uint"/>
|
||||
<bitfield name="SWIZ_X" low="4" high="6" type="a6xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
<bitfield name="SWIZ_Y" low="7" high="9" type="a6xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
<bitfield name="SWIZ_Z" low="10" high="12" type="a6xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
<bitfield name="SWIZ_W" low="13" high="15" type="a6xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
<bitfield name="MIPLVLS" low="16" high="19" type="uint" variants="DESC_SINGLE_PLANE DESC_BUFFER DESC_WEIGHT"/>
|
||||
|
||||
<!-- overlaps with MIPLVLS -->
|
||||
<bitfield name="CHROMA_MIDPOINT_X" pos="16" type="boolean"/>
|
||||
<bitfield name="CHROMA_MIDPOINT_Y" pos="18" type="boolean"/>
|
||||
<bitfield name="CHROMA_MIDPOINT_X" pos="16" type="boolean" variants="DESC_MULTI_PLANE"/>
|
||||
<bitfield name="CHROMA_MIDPOINT_Y" pos="18" type="boolean" variants="DESC_MULTI_PLANE"/>
|
||||
|
||||
<bitfield name="SAMPLES" low="20" high="21" type="a3xx_msaa_samples"/>
|
||||
<bitfield name="FMT" low="22" high="29" type="a6xx_format"/>
|
||||
<!--
|
||||
|
|
@ -68,9 +70,10 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<bitfield name="SWAP" low="30" high="31" type="a3xx_color_swap"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="WIDTH" low="0" high="14" type="uint"/>
|
||||
<bitfield name="HEIGHT" low="15" high="29" type="uint"/>
|
||||
<bitfield name="MUTABLEEN" pos="31" type="boolean" variants="A7XX-"/>
|
||||
<bitfield name="WIDTH" low="0" high="14" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="HEIGHT" low="15" high="29" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="NUM_ELEMENTS" low="0" high="29" type="uint" variants="DESC_BUFFER"/>
|
||||
<bitfield name="MUTABLEEN" pos="31" type="boolean"/> <!-- a7xx+ -->
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<!--
|
||||
|
|
@ -78,13 +81,13 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
PITCH/PITCHALIGN when TYPE is A6XX_TEX_BUFFER.
|
||||
-->
|
||||
<doc> probably for D3D structured UAVs, normally set to 1 </doc>
|
||||
<bitfield name="STRUCTSIZETEXELS" low="4" high="15" type="uint"/>
|
||||
<bitfield name="STARTOFFSETTEXELS" low="16" high="21" type="uint"/>
|
||||
<bitfield name="STRUCTSIZETEXELS" low="4" high="15" type="uint" variants="DESC_BUFFER"/>
|
||||
<bitfield name="STARTOFFSETTEXELS" low="16" high="21" type="uint" variants="DESC_BUFFER"/>
|
||||
|
||||
<!-- minimum pitch (for mipmap levels): log2(pitchalign / 64) -->
|
||||
<bitfield name="PITCHALIGN" low="0" high="3" type="uint"/>
|
||||
<bitfield name="PITCHALIGN" low="0" high="3" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<doc>Pitch in bytes (so actually stride)</doc>
|
||||
<bitfield name="PITCH" low="7" high="28" type="uint"/>
|
||||
<bitfield name="PITCH" low="7" high="28" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="TYPE" low="29" high="31" type="a6xx_tex_type"/>
|
||||
</reg32>
|
||||
<reg32 offset="3" name="3">
|
||||
|
|
@ -94,15 +97,15 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
layer size at the point that it stops being reduced moving to
|
||||
higher (smaller) mipmap levels
|
||||
-->
|
||||
<bitfield name="ARRAY_PITCH" low="0" high="22" shr="12" type="uint"/>
|
||||
<bitfield name="MIN_LAYERSZ" low="23" high="26" shr="12"/>
|
||||
<bitfield name="ARRAY_PITCH" low="0" high="22" shr="12" type="uint" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="MIN_LAYERSZ" low="23" high="26" shr="12" variants="DESC_SINGLE_PLANE"/>
|
||||
<!--
|
||||
by default levels with w < 16 are linear
|
||||
TILE_ALL makes all levels have tiling
|
||||
seems required when using UBWC, since all levels have UBWC (can possibly be disabled?)
|
||||
-->
|
||||
<bitfield name="TILE_ALL" pos="27" type="boolean"/>
|
||||
<bitfield name="FLAG" pos="28" type="boolean"/>
|
||||
<bitfield name="TILE_ALL" pos="27" type="boolean" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="FLAG" pos="28" type="boolean" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<!-- for 2-3 plane format, BASE is flag buffer address (if enabled)
|
||||
the address of the non-flag base buffer is determined automatically,
|
||||
|
|
@ -113,30 +116,42 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
</reg32>
|
||||
<reg32 offset="5" name="5">
|
||||
<bitfield name="BASE_HI" low="0" high="16"/>
|
||||
<bitfield name="DEPTH" low="17" high="29" type="uint"/>
|
||||
<bitfield name="DEPTH" low="17" high="29" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<reg32 offset="6" name="6">
|
||||
<!-- overlaps with PLANE_PITCH -->
|
||||
<bitfield name="MIN_LOD_CLAMP" low="0" high="11" type="ufixed" radix="8"/>
|
||||
<bitfield name="MIN_LOD_CLAMP" low="0" high="11" type="ufixed" radix="8" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE"/>
|
||||
<!-- pitch for plane 2 / plane 3 -->
|
||||
<bitfield name="PLANE_PITCH" low="8" high="31" type="uint"/>
|
||||
<bitfield name="PLANE_PITCH" low="8" high="31" type="uint" variants="DESC_MULTI_PLANE"/>
|
||||
|
||||
<!-- QCOM_image_filtering sample weights descriptor fields, overlapping the others. -->
|
||||
<bitfield name="LOG2_PHASES" low="0" high="2" type="uint" variants="DESC_WEIGHT"/>
|
||||
<bitfield name="DILATION" low="8" high="11" type="uint" variants="DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<!-- 7/8 is plane 2 address for planar formats -->
|
||||
<reg32 offset="7" name="7">
|
||||
<bitfield name="FLAG_LO" low="5" high="31" shr="5"/>
|
||||
<bitfield name="FLAG_LO" low="5" high="31" shr="5" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="BASE_U_LO" low="5" high="31" shr="5" variants="DESC_MULTI_PLANE"/>
|
||||
</reg32>
|
||||
<reg32 offset="8" name="8">
|
||||
<bitfield name="FLAG_HI" low="0" high="16"/>
|
||||
<bitfield name="FLAG_HI" low="0" high="16" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="BASE_U_HI" low="0" high="16" variants="DESC_MULTI_PLANE"/>
|
||||
<bitfield name="FILTER_SIZE_X" low="17" high="23" variants="DESC_WEIGHT"/>
|
||||
<bitfield name="FILTER_SIZE_Y" low="24" high="30" variants="DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<!-- 9/10 is plane 3 address for planar formats -->
|
||||
<reg32 offset="9" name="9">
|
||||
<bitfield name="FLAG_BUFFER_ARRAY_PITCH" low="0" high="16" shr="4" type="uint"/>
|
||||
<bitfield name="FLAG_BUFFER_ARRAY_PITCH" low="0" high="16" shr="4" type="uint" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="BASE_V_LO" low="5" high="31" shr="5" variants="DESC_MULTI_PLANE"/>
|
||||
</reg32>
|
||||
<reg32 offset="10" name="10">
|
||||
<bitfield name="FLAG_BUFFER_PITCH" low="0" high="6" shr="6" type="uint"/>
|
||||
<bitfield name="FLAG_BUFFER_PITCH" low="0" high="6" shr="6" type="uint" variants="DESC_SINGLE_PLANE"/>
|
||||
<!-- log2 size of the first level, required for mipmapping -->
|
||||
<bitfield name="FLAG_BUFFER_LOGW" low="8" high="11" type="uint"/>
|
||||
<bitfield name="FLAG_BUFFER_LOGH" low="12" high="15" type="uint"/>
|
||||
<bitfield name="FLAG_BUFFER_LOGW" low="8" high="11" type="uint" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="FLAG_BUFFER_LOGH" low="12" high="15" type="uint" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="BASE_V_HI" low="0" high="16" variants="DESC_MULTI_PLANE"/>
|
||||
<bitfield name="FILTER_OFFSET_X" low="17" high="22" variants="DESC_WEIGHT"/>
|
||||
<bitfield name="FILTER_OFFSET_Y" low="23" high="28" variants="DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<reg32 offset="11" name="11"/>
|
||||
<reg32 offset="12" name="12"/>
|
||||
|
|
|
|||
|
|
@ -328,6 +328,9 @@ to upconvert to 32b float internally?
|
|||
<value value="0x2" name="R2D_SNORM8"/>
|
||||
<value value="0x1" name="R2D_UNORM8_SRGB"/>
|
||||
<value value="0x0" name="R2D_UNORM8"/>
|
||||
|
||||
<!-- Not a hw enum, used internally in driver -->
|
||||
<value value="0xff" name="R2D_NONE"/>
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_tex_type">
|
||||
|
|
|
|||
112
drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.json
Normal file
112
drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.json
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"chip": "A6XX",
|
||||
"groups": [
|
||||
{
|
||||
"name": "CP",
|
||||
"num": 14,
|
||||
"reserved": [ 0 ],
|
||||
"select": "CP_PERFCTR_CP_SEL",
|
||||
"counter": "RBBM_PERFCTR_CP",
|
||||
"countable_type": "a6xx_cp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "CCU",
|
||||
"num": 5,
|
||||
"select": "RB_PERFCTR_CCU_SEL",
|
||||
"counter": "RBBM_PERFCTR_CCU",
|
||||
"countable_type": "a6xx_ccu_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TSE",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_TSE_SEL",
|
||||
"counter": "RBBM_PERFCTR_TSE",
|
||||
"countable_type": "a6xx_tse_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RAS",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_RAS_SEL",
|
||||
"counter": "RBBM_PERFCTR_RAS",
|
||||
"countable_type": "a6xx_ras_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "LRZ",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_LRZ_SEL",
|
||||
"counter": "RBBM_PERFCTR_LRZ",
|
||||
"countable_type": "a6xx_lrz_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "CMP",
|
||||
"num": 4,
|
||||
"select": "RB_PERFCTR_CMP_SEL",
|
||||
"counter": "RBBM_PERFCTR_CMP",
|
||||
"countable_type": "a6xx_cmp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "HLSQ",
|
||||
"num": 6,
|
||||
"select": "HLSQ_PERFCTR_HLSQ_SEL",
|
||||
"counter": "RBBM_PERFCTR_HLSQ",
|
||||
"countable_type": "a6xx_hlsq_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "PC",
|
||||
"num": 8,
|
||||
"select": "PC_PERFCTR_PC_SEL",
|
||||
"counter": "RBBM_PERFCTR_PC",
|
||||
"countable_type": "a6xx_pc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RB",
|
||||
"num": 8,
|
||||
"select": "RB_PERFCTR_RB_SEL",
|
||||
"counter": "RBBM_PERFCTR_RB",
|
||||
"countable_type": "a6xx_rb_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "SP",
|
||||
"num": 24,
|
||||
"reserved": [ 0 ],
|
||||
"select": "SP_PERFCTR_SP_SEL",
|
||||
"counter": "RBBM_PERFCTR_SP",
|
||||
"countable_type": "a6xx_sp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TP",
|
||||
"num": 12,
|
||||
"select": "TPL1_PERFCTR_TP_SEL",
|
||||
"counter": "RBBM_PERFCTR_TP",
|
||||
"countable_type": "a6xx_tp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "UCHE",
|
||||
"num": 12,
|
||||
"select": "UCHE_PERFCTR_UCHE_SEL",
|
||||
"counter": "RBBM_PERFCTR_UCHE",
|
||||
"countable_type": "a6xx_uche_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VFD",
|
||||
"num": 8,
|
||||
"select": "VFD_PERFCTR_VFD_SEL",
|
||||
"counter": "RBBM_PERFCTR_VFD",
|
||||
"countable_type": "a6xx_vfd_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VPC",
|
||||
"num": 6,
|
||||
"select": "VPC_PERFCTR_VPC_SEL",
|
||||
"counter": "RBBM_PERFCTR_VPC",
|
||||
"countable_type": "a6xx_vpc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VSC",
|
||||
"num": 2,
|
||||
"select": "VSC_PERFCTR_VSC_SEL",
|
||||
"counter": "RBBM_PERFCTR_VSC",
|
||||
"countable_type": "a6xx_vsc_perfcounter_select"
|
||||
}
|
||||
]
|
||||
}
|
||||
228
drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.json
Normal file
228
drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.json
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
{
|
||||
"chip": "A7XX",
|
||||
"groups": [
|
||||
{
|
||||
"name": "CP",
|
||||
"num": 14,
|
||||
"reserved": [ 0 ],
|
||||
"select": "CP_PERFCTR_CP_SEL",
|
||||
"counter": "RBBM_PERFCTR_CP",
|
||||
"countable_type": "a7xx_cp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RBBM",
|
||||
"num": 4,
|
||||
"select": "RBBM_PERFCTR_RBBM_SEL",
|
||||
"counter": "RBBM_PERFCTR_RBBM",
|
||||
"countable_type": "a7xx_rbbm_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "PC",
|
||||
"pipe": "BR",
|
||||
"num": 8,
|
||||
"select": "PC_PERFCTR_PC_SEL",
|
||||
"counter": "RBBM_PERFCTR_PC",
|
||||
"countable_type": "a7xx_pc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VFD",
|
||||
"pipe": "BR",
|
||||
"num": 8,
|
||||
"select": "VFD_PERFCTR_VFD_SEL",
|
||||
"counter": "RBBM_PERFCTR_VFD",
|
||||
"countable_type": "a7xx_vfd_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "HLSQ",
|
||||
"pipe": "BR",
|
||||
"num": 6,
|
||||
"select": "SP_PERFCTR_HLSQ_SEL",
|
||||
"counter": "RBBM_PERFCTR_HLSQ",
|
||||
"countable_type": "a7xx_hlsq_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VPC",
|
||||
"pipe": "BR",
|
||||
"num": 6,
|
||||
"select": "VPC_PERFCTR_VPC_SEL",
|
||||
"counter": "RBBM_PERFCTR_VPC",
|
||||
"countable_type": "a7xx_vpc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TSE",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_TSE_SEL",
|
||||
"counter": "RBBM_PERFCTR_TSE",
|
||||
"countable_type": "a7xx_tse_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RAS",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_RAS_SEL",
|
||||
"counter": "RBBM_PERFCTR_RAS",
|
||||
"countable_type": "a7xx_ras_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "UCHE",
|
||||
"num": 12,
|
||||
"select": "UCHE_PERFCTR_UCHE_SEL",
|
||||
"counter": "RBBM_PERFCTR_UCHE",
|
||||
"countable_type": "a7xx_uche_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TP",
|
||||
"pipe": "BR",
|
||||
"num": 12,
|
||||
"select": "TPL1_PERFCTR_TP_SEL",
|
||||
"counter": "RBBM_PERFCTR_TP",
|
||||
"countable_type": "a7xx_tp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "SP",
|
||||
"pipe": "BR",
|
||||
"num": 24,
|
||||
"select": "SP_PERFCTR_SP_SEL",
|
||||
"counter": "RBBM_PERFCTR_SP",
|
||||
"countable_type": "a7xx_sp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RB",
|
||||
"num": 8,
|
||||
"select": "RB_PERFCTR_RB_SEL",
|
||||
"counter": "RBBM_PERFCTR_RB",
|
||||
"countable_type": "a7xx_rb_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VSC",
|
||||
"num": 2,
|
||||
"select": "VSC_PERFCTR_VSC_SEL",
|
||||
"counter": "RBBM_PERFCTR_VSC",
|
||||
"countable_type": "a7xx_vsc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "CCU",
|
||||
"num": 5,
|
||||
"select": "RB_PERFCTR_CCU_SEL",
|
||||
"counter": "RBBM_PERFCTR_CCU",
|
||||
"countable_type": "a7xx_ccu_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "LRZ",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_LRZ_SEL",
|
||||
"counter": "RBBM_PERFCTR_LRZ",
|
||||
"countable_type": "a7xx_lrz_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "CMP",
|
||||
"num": 4,
|
||||
"select": "RB_PERFCTR_CMP_SEL",
|
||||
"counter": "RBBM_PERFCTR_CMP",
|
||||
"countable_type": "a7xx_cmp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "UFC",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "RB_PERFCTR_UFC_SEL",
|
||||
"counter": "RBBM_PERFCTR_UFC",
|
||||
"countable_type": "a7xx_ufc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_CP",
|
||||
"num": 7,
|
||||
"select": "CP_BV_PERFCTR_CP_SEL",
|
||||
"counter": "RBBM_PERFCTR2_CP",
|
||||
"countable_type": "a7xx_cp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_PC",
|
||||
"pipe": "BV",
|
||||
"num": 8,
|
||||
"select_offset": 8,
|
||||
"select": "PC_PERFCTR_PC_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_PC",
|
||||
"countable_type": "a7xx_pc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_VFD",
|
||||
"pipe": "BV",
|
||||
"num": 8,
|
||||
"select_offset": 8,
|
||||
"select": "VFD_PERFCTR_VFD_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_VFD",
|
||||
"countable_type": "a7xx_vfd_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_VPC",
|
||||
"pipe": "BV",
|
||||
"num": 6,
|
||||
"select_offset": 6,
|
||||
"select": "VPC_PERFCTR_VPC_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_VPC",
|
||||
"countable_type": "a7xx_vpc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_TP",
|
||||
"pipe": "BV",
|
||||
"num": 6,
|
||||
"select_offset": 12,
|
||||
"select": "TPL1_PERFCTR_TP_SEL",
|
||||
"counter": "RBBM_PERFCTR2_TP",
|
||||
"countable_type": "a7xx_tp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_SP",
|
||||
"pipe": "BV",
|
||||
"num": 12,
|
||||
"select_offset": 24,
|
||||
"select": "SP_PERFCTR_SP_SEL",
|
||||
"counter": "RBBM_PERFCTR2_SP",
|
||||
"countable_type": "a7xx_sp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_UFC",
|
||||
"pipe": "BV",
|
||||
"num": 2,
|
||||
"select_offset": 4,
|
||||
"select": "RB_PERFCTR_UFC_SEL",
|
||||
"counter": "RBBM_PERFCTR2_UFC",
|
||||
"countable_type": "a7xx_ufc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_TSE",
|
||||
"pipe": "BV",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_TSE_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_TSE",
|
||||
"countable_type": "a7xx_tse_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_RAS",
|
||||
"pipe": "BV",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_RAS_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_RAS",
|
||||
"countable_type": "a7xx_ras_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_LRZ",
|
||||
"pipe": "BV",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_LRZ_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_LRZ",
|
||||
"countable_type": "a7xx_lrz_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_HLSQ",
|
||||
"pipe": "BV",
|
||||
"num": 6,
|
||||
"select": "SP_PERFCTR_HLSQ_SEL",
|
||||
"counter": "RBBM_PERFCTR2_HLSQ",
|
||||
"countable_type": "a7xx_hlsq_perfcounter_select"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -39,76 +39,92 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 offset="3" name="3"/>
|
||||
</domain>
|
||||
|
||||
<domain name="A8XX_TEX_MEMOBJ" width="32" varset="chip">
|
||||
<domain name="A8XX_TEX_MEMOBJ" width="32" varset="desctype">
|
||||
<doc>Texture memobj dwords</doc>
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="BASE_LO" low="6" high="31" shr="6"/>
|
||||
<bitfield name="BASE_LO" low="6" high="31" shr="6" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<doc>for type TEX_BUFFER</doc>
|
||||
<bitfield name="INSTANCE_DESC_BASE_LO" low="0" high="31" variants="DESC_BUFFER"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="BASE_HI" low="0" high="16"/>
|
||||
<bitfield name="BASE_HI" low="0" high="16" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="INSTANCE_DESC_BASE_HI" low="0" high="16" variants="DESC_BUFFER"/>
|
||||
<bitfield name="TYPE" low="17" high="19" type="a6xx_tex_type"/>
|
||||
<bitfield name="DEPTH" low="20" high="31" type="uint"/>
|
||||
<bitfield name="DEPTH" low="20" high="31" type="uint" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/>
|
||||
<doc> for type TEX_BUFFER, probably for D3D structured UAVs, normally set to 1 </doc>
|
||||
<bitfield name="STRUCTSIZETEXELS" low="20" high="31" type="uint" variants="DESC_BUFFER"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="WIDTH" low="0" high="14" type="uint"/>
|
||||
<bitfield name="HEIGHT" low="15" high="29" type="uint"/>
|
||||
<bitfield name="SAMPLES" low="30" high="31" type="a3xx_msaa_samples"/>
|
||||
<bitfield name="WIDTH" low="0" high="14" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="HEIGHT" low="15" high="29" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="SAMPLES" low="30" high="31" type="a3xx_msaa_samples" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="NUM_ELEMENTS" low="0" high="31" type="uint" variants="DESC_BUFFER"/>
|
||||
</reg32>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="FMT" low="0" high="7" type="a6xx_format"/>
|
||||
<bitfield name="SWAP" low="8" high="9" type="a3xx_color_swap"/>
|
||||
<bitfield name="SWIZ_X" low="10" high="12" type="a8xx_tex_swiz"/>
|
||||
<bitfield name="SWIZ_Y" low="13" high="15" type="a8xx_tex_swiz"/>
|
||||
<bitfield name="SWIZ_Z" low="16" high="18" type="a8xx_tex_swiz"/>
|
||||
<bitfield name="SWIZ_W" low="19" high="21" type="a8xx_tex_swiz"/>
|
||||
<bitfield name="SWIZ_X" low="10" high="12" type="a8xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
<bitfield name="SWIZ_Y" low="13" high="15" type="a8xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
<bitfield name="SWIZ_Z" low="16" high="18" type="a8xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
<bitfield name="SWIZ_W" low="19" high="21" type="a8xx_tex_swiz" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_BUFFER"/>
|
||||
</reg32>
|
||||
<reg32 offset="4" name="4">
|
||||
<bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode"/>
|
||||
<bitfield name="FLAG" pos="2" type="boolean"/>
|
||||
<bitfield name="PRT_EN" pos="3" type="boolean"/>
|
||||
<bitfield name="TILE_ALL" pos="4" type="boolean"/>
|
||||
<bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="FLAG" pos="2" type="boolean" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="PRT_EN" pos="3" type="boolean" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/>
|
||||
<bitfield name="TILE_ALL" pos="4" type="boolean" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="SRGB" pos="5" type="boolean"/>
|
||||
<bitfield name="FLAG_LO" low="6" high="31" shr="6"/>
|
||||
<bitfield name="FLAG_LO" low="6" high="31" shr="6" variants="DESC_SINGLE_PLANE"/>
|
||||
<!-- For multiplanar: -->
|
||||
<bitfield name="BASE_U_LO" low="6" high="31" shr="6"/>
|
||||
<bitfield name="BASE_U_LO" low="6" high="31" shr="6" variants="DESC_MULTI_PLANE"/>
|
||||
</reg32>
|
||||
<reg32 offset="5" name="5">
|
||||
<bitfield name="FLAG_HI" low="0" high="16"/>
|
||||
<bitfield name="FLAG_HI" low="0" high="16" variants="DESC_SINGLE_PLANE"/>
|
||||
<!-- For multiplanar: -->
|
||||
<bitfield name="BASE_U_HI" low="0" high="16"/>
|
||||
<bitfield name="FLAG_BUFFER_PITCH" low="17" high="24" shr="6" type="uint"/>
|
||||
<bitfield name="ALL_SAMPLES_CENTER" pos="29" type="boolean"/>
|
||||
<bitfield name="MUTABLEEN" pos="31" type="boolean"/>
|
||||
<bitfield name="BASE_U_HI" low="0" high="16" variants="DESC_MULTI_PLANE"/>
|
||||
<bitfield name="FLAG_BUFFER_PITCH" low="17" high="24" shr="6" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE"/>
|
||||
<bitfield name="ALL_SAMPLES_CENTER" pos="29" type="boolean" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="MUTABLEEN" pos="31" type="boolean" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/>
|
||||
|
||||
<!-- QCOM_image_filtering sample weights descriptor fields, overlapping the others. -->
|
||||
<bitfield name="FILTER_SIZE_X" low="0" high="6" type="uint" variants="DESC_WEIGHT"/>
|
||||
<bitfield name="FILTER_SIZE_Y" low="7" high="13" type="uint" variants="DESC_WEIGHT"/>
|
||||
<bitfield name="FILTER_OFFSET_X" low="19" high="24" type="uint" variants="DESC_WEIGHT"/>
|
||||
<bitfield name="FILTER_OFFSET_Y" low="25" high="30" type="uint" variants="DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<reg32 offset="6" name="6">
|
||||
<bitfield name="TEX_LINE_OFFSET" low="0" high="23" type="uint"/> <!-- PITCH -->
|
||||
<bitfield name="MIN_LINE_OFFSET" low="24" high="27" type="uint"/> <!-- PITCHALIGN -->
|
||||
<bitfield name="MIPLVLS" low="28" high="31" type="uint"/>
|
||||
<bitfield name="TEX_LINE_OFFSET" low="0" high="23" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/> <!-- PITCH -->
|
||||
<bitfield name="MIN_LINE_OFFSET" low="24" high="27" type="uint" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/> <!-- PITCHALIGN -->
|
||||
<bitfield name="MIPLVLS" low="28" high="31" type="uint" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<reg32 offset="7" name="7">
|
||||
<bitfield name="ARRAY_SLICE_OFFSET" low="0" high="22" shr="12" type="uint"/> <!-- ARRAY_PITCH -->
|
||||
<bitfield name="ASO_UNIT" pos="23"/> <!-- 4KB or 32B ? -->
|
||||
<bitfield name="MIN_ARRAY_SLIZE_OFFSET" low="24" high="27" shr="12"/> <!-- MIN_LAYERSZ -->
|
||||
<bitfield name="GMEM_TILING_FALLBACK_EN" pos="28" type="boolean"/>
|
||||
<bitfield name="CORNER_BASED_EN" pos="30" type="boolean"/>
|
||||
<bitfield name="GMEM_FULL_SURF" pos="31" type="boolean"/>
|
||||
<bitfield name="ARRAY_SLICE_OFFSET" low="0" high="22" shr="12" type="uint" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/> <!-- ARRAY_PITCH -->
|
||||
<bitfield name="ASO_UNIT" pos="23" variants="DESC_SINGLE_PLANE DESC_WEIGHT"/> <!-- 4KB or 32B ? -->
|
||||
<bitfield name="MIN_ARRAY_SLIZE_OFFSET" low="24" high="27" shr="12" variants="DESC_SINGLE_PLANE"/> <!-- MIN_LAYERSZ -->
|
||||
<bitfield name="GMEM_TILING_FALLBACK_EN" pos="28" type="boolean" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="CORNER_BASED_EN" pos="30" type="boolean" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE"/>
|
||||
<bitfield name="GMEM_FULL_SURF" pos="31" type="boolean" variants="DESC_SINGLE_PLANE DESC_MULTI_PLANE DESC_WEIGHT"/>
|
||||
<!-- For multiplanar. This overlaps other single-planar fields: -->
|
||||
<bitfield name="UV_OFFSET_H" low="24" high="25" type="ufixed" radix="2"/> <!-- CHROMA_MIDPOINT_X -->
|
||||
<bitfield name="UV_OFFSET_V" low="26" high="27" type="ufixed" radix="2"/> <!-- CHROMA_MIDPOINT_Y -->
|
||||
<bitfield name="UV_OFFSET_H" low="24" high="25" type="ufixed" radix="2" variants="DESC_MULTI_PLANE"/> <!-- CHROMA_MIDPOINT_X -->
|
||||
<bitfield name="UV_OFFSET_V" low="26" high="27" type="ufixed" radix="2" variants="DESC_MULTI_PLANE"/> <!-- CHROMA_MIDPOINT_Y -->
|
||||
|
||||
<!-- QCOM_image_filtering sample weights descriptor fields, overlapping the others. -->
|
||||
<bitfield name="DILATION" low="24" high="27" type="uint" variants="DESC_WEIGHT"/>
|
||||
<bitfield name="LOG2_PHASES" low="28" high="30" type="uint" variants="DESC_WEIGHT"/>
|
||||
</reg32>
|
||||
<reg32 offset="8" name="8">
|
||||
<bitfield name="FLAG_ARRAY_PITCH" low="0" high="14" shr="12" type="uint"/> <!-- FLAG_BUFFER_ARRAY_PITCH -->
|
||||
<bitfield name="FLAG_ARRAY_PITCH" low="0" high="14" shr="12" type="uint" variants="DESC_SINGLE_PLANE"/> <!-- FLAG_BUFFER_ARRAY_PITCH -->
|
||||
<!-- log2 size of the first level, required for mipmapping -->
|
||||
<bitfield name="FLAG_BUFFER_LOGW" low="24" high="27" type="uint"/>
|
||||
<bitfield name="FLAG_BUFFER_LOGH" low="28" high="31" type="uint"/>
|
||||
<bitfield name="FLAG_BUFFER_LOGW" low="24" high="27" type="uint" variants="DESC_SINGLE_PLANE"/>
|
||||
<bitfield name="FLAG_BUFFER_LOGH" low="28" high="31" type="uint" variants="DESC_SINGLE_PLANE"/>
|
||||
<!-- For multiplanar. This overlaps other single-planar fields: -->
|
||||
<bitfield name="BASE_V_LO" low="6" high="31" shr="6"/>
|
||||
<bitfield name="BASE_V_LO" low="6" high="31" shr="6" variants="DESC_MULTI_PLANE"/>
|
||||
</reg32>
|
||||
<reg32 offset="9" name="9">
|
||||
<bitfield name="MIN_LOD_CLAMP" low="19" high="30" type="ufixed" radix="8"/>
|
||||
<bitfield name="MIN_LOD_CLAMP" low="19" high="30" type="ufixed" radix="8" variants="DESC_SINGLE_PLANE"/>
|
||||
<!-- For multiplanar, this overlaps other fields: -->
|
||||
<bitfield name="BASE_V_HI" low="0" high="16"/>
|
||||
<bitfield name="UV_PITCH" low="17" high="26"/> <!-- PLANE_PITCH -->
|
||||
<bitfield name="BASE_V_HI" low="0" high="16" variants="DESC_MULTI_PLANE"/>
|
||||
<bitfield name="UV_PITCH" shr="6" low="17" high="26" variants="DESC_MULTI_PLANE"/> <!-- PLANE_PITCH -->
|
||||
</reg32>
|
||||
<reg32 offset="10" name="10"/>
|
||||
<reg32 offset="11" name="11"/>
|
||||
|
|
|
|||
241
drivers/gpu/drm/msm/registers/adreno/a8xx_perfcntrs.json
Normal file
241
drivers/gpu/drm/msm/registers/adreno/a8xx_perfcntrs.json
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
{
|
||||
"chip": "A8XX",
|
||||
"groups": [
|
||||
{
|
||||
"name": "CP",
|
||||
"num": 14,
|
||||
"reserved": [ 0 ],
|
||||
"select": "CP_PERFCTR_CP_SEL",
|
||||
"counter": "RBBM_PERFCTR_CP",
|
||||
"countable_type": "a8xx_cp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RBBM",
|
||||
"num": 4,
|
||||
"select": "RBBM_PERFCTR_RBBM_SEL",
|
||||
"slice_select": [ "RBBM_SLICE_PERFCTR_RBBM_SEL" ],
|
||||
"counter": "RBBM_PERFCTR_RBBM",
|
||||
"countable_type": "a8xx_rbbm_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "PC",
|
||||
"pipe": "BR",
|
||||
"num": 8,
|
||||
"select": "PC_PERFCTR_PC_SEL",
|
||||
"slice_select": [ "PC_SLICE_PERFCTR_PC_SEL" ],
|
||||
"counter": "RBBM_PERFCTR_PC",
|
||||
"countable_type": "a8xx_pc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VFD",
|
||||
"pipe": "BR",
|
||||
"num": 8,
|
||||
"select": "VFD_PERFCTR_VFD_SEL",
|
||||
"counter": "RBBM_PERFCTR_VFD",
|
||||
"countable_type": "a8xx_vfd_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "HLSQ",
|
||||
"pipe": "BR",
|
||||
"num": 6,
|
||||
"select": "SP_PERFCTR_HLSQ_SEL",
|
||||
"slice_select": [ "SP_PERFCTR_HLSQ_SEL_2" ],
|
||||
"counter": "RBBM_PERFCTR_HLSQ",
|
||||
"countable_type": "a8xx_hlsq_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VPC",
|
||||
"pipe": "BR",
|
||||
"num": 6,
|
||||
"select": "VPC_PERFCTR_VPC_SEL",
|
||||
"slice_select": [ "VPC_PERFCTR_VPC_SEL_1", "VPC_PERFCTR_VPC_SEL_2" ],
|
||||
"counter": "RBBM_PERFCTR_VPC",
|
||||
"countable_type": "a8xx_vpc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TSE",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_TSE_SEL",
|
||||
"slice_select": [ "GRAS_PERFCTR_TSEFE_SEL" ],
|
||||
"counter": "RBBM_PERFCTR_TSE",
|
||||
"countable_type": "a8xx_tse_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RAS",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_RAS_SEL",
|
||||
"counter": "RBBM_PERFCTR_RAS",
|
||||
"countable_type": "a8xx_ras_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "UCHE",
|
||||
"num": 24,
|
||||
"select": "UCHE_PERFCTR_UCHE_SEL",
|
||||
"counter": "RBBM_PERFCTR_UCHE",
|
||||
"countable_type": "a8xx_uche_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "TP",
|
||||
"pipe": "BR",
|
||||
"num": 12,
|
||||
"select": "TPL1_PERFCTR_TP_SEL",
|
||||
"counter": "RBBM_PERFCTR_TP",
|
||||
"countable_type": "a8xx_tp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "SP",
|
||||
"pipe": "BR",
|
||||
"num": 24,
|
||||
"select": "SP_PERFCTR_SP_SEL",
|
||||
"counter": "RBBM_PERFCTR_SP",
|
||||
"countable_type": "a8xx_sp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "RB",
|
||||
"pipe": "BR",
|
||||
"num": 8,
|
||||
"select": "RB_PERFCTR_RB_SEL",
|
||||
"counter": "RBBM_PERFCTR_RB",
|
||||
"countable_type": "a8xx_rb_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "VSC",
|
||||
"num": 2,
|
||||
"select": "VSC_PERFCTR_VSC_SEL",
|
||||
"counter": "RBBM_PERFCTR_VSC",
|
||||
"countable_type": "a8xx_vsc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "CCU",
|
||||
"pipe": "BR",
|
||||
"num": 5,
|
||||
"select": "RB_PERFCTR_CCU_SEL",
|
||||
"counter": "RBBM_PERFCTR_CCU",
|
||||
"countable_type": "a8xx_ccu_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "LRZ",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_LRZ_SEL",
|
||||
"counter": "RBBM_PERFCTR_LRZ",
|
||||
"countable_type": "a8xx_lrz_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "CMP",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "RB_PERFCTR_CMP_SEL",
|
||||
"counter": "RBBM_PERFCTR_CMP",
|
||||
"countable_type": "a8xx_cmp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "UFC",
|
||||
"pipe": "BR",
|
||||
"num": 4,
|
||||
"select": "RB_PERFCTR_UFC_SEL",
|
||||
"counter": "RBBM_PERFCTR_UFC",
|
||||
"countable_type": "a8xx_ufc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_CP",
|
||||
"num": 7,
|
||||
"select_offset": 14,
|
||||
"select": "CP_PERFCTR_CP_SEL",
|
||||
"counter": "RBBM_PERFCTR2_CP",
|
||||
"countable_type": "a8xx_cp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_PC",
|
||||
"pipe": "BV",
|
||||
"num": 8,
|
||||
"select_offset": 8,
|
||||
"select": "PC_PERFCTR_PC_SEL",
|
||||
"slice_select": [ "PC_SLICE_PERFCTR_PC_SEL" ],
|
||||
"counter": "RBBM_PERFCTR_BV_PC",
|
||||
"countable_type": "a8xx_pc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_VFD",
|
||||
"pipe": "BV",
|
||||
"num": 8,
|
||||
"select_offset": 8,
|
||||
"select": "VFD_PERFCTR_VFD_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_VFD",
|
||||
"countable_type": "a8xx_vfd_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_VPC",
|
||||
"pipe": "BV",
|
||||
"num": 6,
|
||||
"select_offset": 6,
|
||||
"select": "VPC_PERFCTR_VPC_SEL",
|
||||
"slice_select": [ "VPC_PERFCTR_VPC_SEL_1", "VPC_PERFCTR_VPC_SEL_2" ],
|
||||
"counter": "RBBM_PERFCTR_BV_VPC",
|
||||
"countable_type": "a8xx_vpc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_TP",
|
||||
"pipe": "BV",
|
||||
"num": 8,
|
||||
"select_offset": 12,
|
||||
"select": "TPL1_PERFCTR_TP_SEL",
|
||||
"counter": "RBBM_PERFCTR2_TP",
|
||||
"countable_type": "a8xx_tp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_SP",
|
||||
"pipe": "BV",
|
||||
"num": 12,
|
||||
"select_offset": 24,
|
||||
"select": "SP_PERFCTR_SP_SEL",
|
||||
"counter": "RBBM_PERFCTR2_SP",
|
||||
"countable_type": "a8xx_sp_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_UFC",
|
||||
"pipe": "BV",
|
||||
"num": 2,
|
||||
"select_offset": 4,
|
||||
"select": "RB_PERFCTR_UFC_SEL",
|
||||
"counter": "RBBM_PERFCTR2_UFC",
|
||||
"countable_type": "a8xx_ufc_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_TSE",
|
||||
"pipe": "BV",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_TSE_SEL",
|
||||
"slice_select": [ "GRAS_PERFCTR_TSEFE_SEL" ],
|
||||
"counter": "RBBM_PERFCTR_BV_TSE",
|
||||
"countable_type": "a8xx_tse_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_RAS",
|
||||
"pipe": "BV",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_RAS_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_RAS",
|
||||
"countable_type": "a8xx_ras_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_LRZ",
|
||||
"pipe": "BV",
|
||||
"num": 4,
|
||||
"select": "GRAS_PERFCTR_LRZ_SEL",
|
||||
"counter": "RBBM_PERFCTR_BV_LRZ",
|
||||
"countable_type": "a8xx_lrz_perfcounter_select"
|
||||
},
|
||||
{
|
||||
"name": "BV_HLSQ",
|
||||
"pipe": "BV",
|
||||
"num": 6,
|
||||
"select": "SP_PERFCTR_HLSQ_SEL",
|
||||
"slice_select": [ "SP_PERFCTR_HLSQ_SEL_2" ],
|
||||
"counter": "RBBM_PERFCTR2_HLSQ",
|
||||
"countable_type": "a8xx_hlsq_perfcounter_select"
|
||||
}
|
||||
]
|
||||
}
|
||||
1929
drivers/gpu/drm/msm/registers/adreno/a8xx_perfcntrs.xml
Normal file
1929
drivers/gpu/drm/msm/registers/adreno/a8xx_perfcntrs.xml
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -14,6 +14,27 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<value name="A8XX" value="8"/>
|
||||
</enum>
|
||||
|
||||
<enum name="desctype" bare="yes">
|
||||
<value name="DESC_NONE" value="0"/>
|
||||
<doc>
|
||||
TEX_MEMOBJ descriptor types. These are used
|
||||
to mark fields that only apply to certain
|
||||
descriptor types, and potentially overlap
|
||||
with fields in other types.
|
||||
</doc>
|
||||
<value name="DESC_SINGLE_PLANE" value="1"/>
|
||||
<value name="DESC_MULTI_PLANE" value="2"/>
|
||||
<value name="DESC_BUFFER" value="3"/>
|
||||
<value name="DESC_WEIGHT" value="4"/>
|
||||
<doc>
|
||||
Additional descriptor types not part of
|
||||
TEX_MEMOBJ. These are described by their
|
||||
own toplevel domain.
|
||||
</doc>
|
||||
<value name="DESC_SAMPLER" value="10"/> <!-- AxXX_UBO -->
|
||||
<value name="DESC_UBO" value="11"/> <!-- A6XX_UBO, same on gen8 -->
|
||||
</enum>
|
||||
|
||||
<enum name="adreno_pa_su_sc_draw">
|
||||
<value name="PC_DRAW_POINTS" value="0"/>
|
||||
<value name="PC_DRAW_LINES" value="1"/>
|
||||
|
|
@ -409,4 +430,25 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<value value="7" name="PIPE_DDE_BV"/>
|
||||
</enum>
|
||||
|
||||
<!--
|
||||
A fake domain for giving lua scripts access to the shader_stats struct
|
||||
-->
|
||||
<domain name="ir3_shader_stats" width="32">
|
||||
<!-- indx 0 is bindful, indx N+1 is .baseN -->
|
||||
<array offset="0" name="descriptor_stats" stride="8" length="9">
|
||||
<reg64 offset="0" name="img"/>
|
||||
<reg64 offset="2" name="tex"/>
|
||||
<reg64 offset="4" name="samp"/>
|
||||
<reg64 offset="6" name="ubo"/>
|
||||
</array>
|
||||
<reg32 offset="72" name="has_img"/>
|
||||
<reg32 offset="73" name="has_tex"/>
|
||||
<reg32 offset="74" name="has_samp"/>
|
||||
<reg32 offset="74" name="has_ubo"/>
|
||||
<!--
|
||||
other following fields can be added as needed, but we
|
||||
might need to take care of padding/alignment.
|
||||
-->
|
||||
</domain>
|
||||
|
||||
</database>
|
||||
|
|
|
|||
|
|
@ -152,6 +152,8 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<!-- TODO: deal with name conflicts with other gens -->
|
||||
<value name="CACHE_FLUSH7" value="0x32" variants="A7XX-"/>
|
||||
<value name="CACHE_INVALIDATE7" value="0x33" variants="A7XX-"/>
|
||||
<value name="SUBPASS_FENCE" value="0x35" variants="A7XX-"/>
|
||||
<value name="SUBPASS_SLICE_FENCE" value="0x36" variants="A8XX-"/>
|
||||
<value name="DEPTH_BUFFER_FLIP" value="0x3d" variants="A8XX-"/>
|
||||
<value name="CCH_FAST_CLEAR_CLEAN" value="0x1b" variants="A8XX-"/>
|
||||
</enum>
|
||||
|
|
@ -1095,7 +1097,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<bitfield name="DIRTY" pos="16" type="boolean"/>
|
||||
<bitfield name="DISABLE" pos="17" type="boolean"/>
|
||||
<bitfield name="DISABLE_ALL_GROUPS" pos="18" type="boolean"/>
|
||||
<bitfield name="LOAD_IMMED" pos="19" type="boolean"/>
|
||||
<bitfield name="LOAD_IMMED" pos="19" type="boolean" variants="A5XX"/>
|
||||
<bitfield name="BINNING" pos="20" varset="chip" variants="A6XX-" type="boolean"/>
|
||||
<bitfield name="GMEM" pos="21" varset="chip" variants="A6XX-" type="boolean"/>
|
||||
<bitfield name="SYSMEM" pos="22" varset="chip" variants="A6XX-" type="boolean"/>
|
||||
|
|
@ -1275,8 +1277,15 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<domain name="CP_REG_TO_MEM" width="32" prefix="chip">
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="REG" low="0" high="17" type="hex"/>
|
||||
<!-- number of registers/dwords copied is max(CNT, 1). -->
|
||||
<!--
|
||||
Number of registers/dwords copied is max(CNT, 1).
|
||||
With 64B it gets rounded to the next 64B boundary.
|
||||
-->
|
||||
<bitfield name="CNT" low="18" high="29" type="uint"/>
|
||||
<!--
|
||||
Treat things as 64B, allowing for a 64B atomic read of
|
||||
registers.
|
||||
-->
|
||||
<bitfield name="64B" pos="30" type="boolean"/>
|
||||
<bitfield name="ACCUMULATE" pos="31" type="boolean"/>
|
||||
</reg32>
|
||||
|
|
@ -1469,6 +1478,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<value value="1" name="POLL_MEMORY"/>
|
||||
<value value="2" name="POLL_SCRATCH"/>
|
||||
<value value="3" name="POLL_ON_CHIP" varset="chip" variants="A7XX-"/>
|
||||
<value value="4" name="POLL_SYSTEM_VARIABLE" varset="chip" variants="A8XX-"/>
|
||||
</enum>
|
||||
|
||||
<domain name="CP_COND_WRITE5" width="32">
|
||||
|
|
@ -1476,7 +1486,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<bitfield name="FUNCTION" low="0" high="2" type="cp_cond_function"/>
|
||||
<bitfield name="SIGNED_COMPARE" pos="3" type="boolean"/>
|
||||
<!-- POLL_REGISTER polls a register at POLL_ADDR_LO. -->
|
||||
<bitfield name="POLL" low="4" high="5" type="poll_memory_type"/>
|
||||
<bitfield name="POLL" low="4" high="6" type="poll_memory_type"/>
|
||||
<bitfield name="WRITE_MEMORY" pos="8" type="boolean"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="POLL_ADDR" type="address"/>
|
||||
|
|
@ -2055,28 +2065,20 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
|
||||
<domain name="CP_COND_EXEC" width="32">
|
||||
<doc>
|
||||
Executes the following DWORDs of commands if the dword at ADDR0
|
||||
is not equal to 0 and the dword at ADDR1 is less than REF
|
||||
(signed comparison).
|
||||
Executes the following DWORDs of commands if the dword
|
||||
at BOOL_ADDR is not equal to 0 and the the timestamp
|
||||
value ACTIVE_TIMESTAMP is ahead of the value fetched
|
||||
from TIMESTAMP_ADDR.
|
||||
|
||||
The timestamp comparision is an unsigned compare with
|
||||
wraparound, ie:
|
||||
|
||||
(ACTIVE_TIMESTAMP - *TIMESTAMP_ADDR) < 0x80000000
|
||||
</doc>
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="ADDR0_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="ADDR0_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="ADDR1_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="ADDR1_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="4" name="4">
|
||||
<bitfield name="REF" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="5" name="5">
|
||||
<bitfield name="DWORDS" low="0" high="31" type="uint"/>
|
||||
</reg32>
|
||||
<reg64 offset="0" name="BOOL_ADDR" type="address"/>
|
||||
<reg64 offset="2" name="TIMESTAMP_ADDR" type="address"/>
|
||||
<reg32 offset="4" name="ACTIVE_TIMESTAMP"/>
|
||||
<reg32 offset="5" name="DWORDS"/>
|
||||
</domain>
|
||||
|
||||
<domain name="CP_SET_AMBLE" width="32">
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -50,6 +50,7 @@ struct qcom_ubwc_cfg_data {
|
|||
#define UBWC_1_0 0x10000000
|
||||
#define UBWC_2_0 0x20000000
|
||||
#define UBWC_3_0 0x30000000
|
||||
#define UBWC_3_1 0x30010000 /* UBWC 3.0 + Macrotile mode */
|
||||
#define UBWC_4_0 0x40000000
|
||||
#define UBWC_4_3 0x40030000
|
||||
#define UBWC_5_0 0x50000000
|
||||
|
|
@ -99,4 +100,25 @@ static inline u32 qcom_ubwc_swizzle(const struct qcom_ubwc_cfg_data *cfg)
|
|||
return cfg->ubwc_swizzle;
|
||||
}
|
||||
|
||||
static inline u32 qcom_ubwc_version_tag(const struct qcom_ubwc_cfg_data *cfg)
|
||||
{
|
||||
if (cfg->ubwc_enc_version >= UBWC_6_0)
|
||||
return 5;
|
||||
if (cfg->ubwc_enc_version >= UBWC_5_0)
|
||||
return 4;
|
||||
if (cfg->ubwc_enc_version >= UBWC_4_3)
|
||||
return 3;
|
||||
if (cfg->ubwc_enc_version >= UBWC_4_0)
|
||||
return 2;
|
||||
if (cfg->ubwc_enc_version >= UBWC_3_0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool qcom_ubwc_enable_amsbc(const struct qcom_ubwc_cfg_data *cfg)
|
||||
{
|
||||
return cfg->ubwc_enc_version >= UBWC_3_0;
|
||||
}
|
||||
|
||||
#endif /* __QCOM_UBWC_H__ */
|
||||
|
|
|
|||
|
|
@ -491,6 +491,52 @@ struct drm_msm_submitqueue_query {
|
|||
__u32 pad;
|
||||
};
|
||||
|
||||
#define MSM_PERFCNTR_STREAM 0x00000001
|
||||
#define MSM_PERFCNTR_UPDATE 0x00000002
|
||||
#define MSM_PERFCNTR_FLAGS ( \
|
||||
MSM_PERFCNTR_STREAM | \
|
||||
MSM_PERFCNTR_UPDATE | \
|
||||
0)
|
||||
|
||||
struct drm_msm_perfcntr_group {
|
||||
char group_name[16];
|
||||
__u32 nr_countables;
|
||||
__u32 pad; /* mbz */
|
||||
__u64 countables; /* pointer to an array of nr_countables u32 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Note, for MSM_PERFCNTR_STREAM, the ioctl returns an fd to read recorded
|
||||
* counters. This only works because the ioctl is DRM_IOW(), if we returned
|
||||
* a out param in the ioctl struct the copy_to_user() (in drm_ioctl())
|
||||
* could fault, causing us to leak the fd.
|
||||
*
|
||||
* If the ioctl returns with error E2BIG, that means more counters/countables
|
||||
* are requested than are currently available. If MSM_PERFCNTR_UPDATE flag
|
||||
* is set, drm_msm_perfcntr_group::nr_countables will be updated to return
|
||||
* the actual # of counters available.
|
||||
*
|
||||
* The data read from the has the following format for each sampling period:
|
||||
*
|
||||
* uint64_t timestamp; // CP_ALWAYS_ON_COUNTER captured at sample time
|
||||
* uint32_t seqno; // increments by 1 each period, reset to 0 on discontinuity
|
||||
* uint32_t mbz; // pad out counters to 64b
|
||||
* struct {
|
||||
* uint64_t counter[nr_countables];
|
||||
* } groups[nr_groups];
|
||||
*
|
||||
* The ordering of groups and counters matches the order in PERFCNTR_CONFIG
|
||||
* ioctl.
|
||||
*/
|
||||
struct drm_msm_perfcntr_config {
|
||||
__u32 flags; /* bitmask of MSM_PERFCNTR_x */
|
||||
__u32 nr_groups; /* # of entries in groups array */
|
||||
__u64 groups; /* pointer to array of drm_msm_perfcntr_group */
|
||||
__u64 period; /* sampling period in ns */
|
||||
__u32 bufsz_shift; /* sample buffer size in bytes is 1<<bufsz_shift */
|
||||
__u32 group_stride; /* sizeof(struct drm_msm_perfcntr_group) */
|
||||
};
|
||||
|
||||
#define DRM_MSM_GET_PARAM 0x00
|
||||
#define DRM_MSM_SET_PARAM 0x01
|
||||
#define DRM_MSM_GEM_NEW 0x02
|
||||
|
|
@ -507,6 +553,7 @@ struct drm_msm_submitqueue_query {
|
|||
#define DRM_MSM_SUBMITQUEUE_CLOSE 0x0B
|
||||
#define DRM_MSM_SUBMITQUEUE_QUERY 0x0C
|
||||
#define DRM_MSM_VM_BIND 0x0D
|
||||
#define DRM_MSM_PERFCNTR_CONFIG 0x0E
|
||||
|
||||
#define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
|
||||
#define DRM_IOCTL_MSM_SET_PARAM DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SET_PARAM, struct drm_msm_param)
|
||||
|
|
@ -521,6 +568,7 @@ struct drm_msm_submitqueue_query {
|
|||
#define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32)
|
||||
#define DRM_IOCTL_MSM_SUBMITQUEUE_QUERY DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_QUERY, struct drm_msm_submitqueue_query)
|
||||
#define DRM_IOCTL_MSM_VM_BIND DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_VM_BIND, struct drm_msm_vm_bind)
|
||||
#define DRM_IOCTL_MSM_PERFCNTR_CONFIG DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_PERFCNTR_CONFIG, struct drm_msm_perfcntr_config)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user