mirror of
https://github.com/torvalds/linux.git
synced 2026-03-13 21:26:14 +01:00
Merge tag 'drm-msm-next-2025-09-12' of https://gitlab.freedesktop.org/drm/msm into drm-next
Changes for v6.18 GPU and Core: - in DT bindings describe clocks per GPU type - GMU bandwidth voting for x1-85 - a663 speedbins - a623 speedbins - cleanup some remaining no-iommu leftovers after VM_BIND conversion - fix GEM obj 32b size truncation - add missing VM_BIND param validation - various fixes - IFPC for x1-85 and a750 - register xml and gen_header.py sync from mesa Display: - add missing bindings for display on SC8180X - added DisplayPort MST bindings - conversion from round_rate() to determine_rate() - DSI PHY fixes, correcting programming glitches - misc small fixes Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rob Clark <rob.clark@oss.qualcomm.com> Link: https://lore.kernel.org/r/CACSVV01FgXN+fD6U1Hi6Tj4WCf=V-+NO8BXi+80iS4qOZwpaGg@mail.gmail.com
This commit is contained in:
commit
8299ee7ff7
67 changed files with 2347 additions and 953 deletions
|
|
@ -29,15 +29,30 @@ properties:
|
|||
- qcom,sdm845-dp
|
||||
- qcom,sm8350-dp
|
||||
- qcom,sm8650-dp
|
||||
- qcom,x1e80100-dp
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sm6350-dp
|
||||
- const: qcom,sc7180-dp
|
||||
|
||||
# deprecated entry for compatibility with old DT
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sm6350-dp
|
||||
- const: qcom,sm8350-dp
|
||||
deprecated: true
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sar2130p-dp
|
||||
- qcom,sm6350-dp
|
||||
- qcom,sm7150-dp
|
||||
- qcom,sm8150-dp
|
||||
- qcom,sm8250-dp
|
||||
- qcom,sm8450-dp
|
||||
- qcom,sm8550-dp
|
||||
- const: qcom,sm8350-dp
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sm8750-dp
|
||||
|
|
@ -51,35 +66,37 @@ properties:
|
|||
- description: link register block
|
||||
- description: p0 register block
|
||||
- description: p1 register block
|
||||
- description: p2 register block
|
||||
- description: p3 register block
|
||||
- description: mst2link register block
|
||||
- description: mst3link register block
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 5
|
||||
items:
|
||||
- description: AHB clock to enable register access
|
||||
- description: Display Port AUX clock
|
||||
- description: Display Port Link clock
|
||||
- description: Link interface clock between DP and PHY
|
||||
- description: Display Port Pixel clock
|
||||
- description: Display Port stream 0 Pixel clock
|
||||
- description: Display Port stream 1 Pixel clock
|
||||
- description: Display Port stream 2 Pixel clock
|
||||
- description: Display Port stream 3 Pixel clock
|
||||
|
||||
clock-names:
|
||||
minItems: 5
|
||||
items:
|
||||
- const: core_iface
|
||||
- const: core_aux
|
||||
- const: ctrl_link
|
||||
- const: ctrl_link_iface
|
||||
- const: stream_pixel
|
||||
|
||||
assigned-clocks:
|
||||
items:
|
||||
- description: link clock source
|
||||
- description: pixel clock source
|
||||
|
||||
assigned-clock-parents:
|
||||
items:
|
||||
- description: phy 0 parent
|
||||
- description: phy 1 parent
|
||||
- const: stream_1_pixel
|
||||
- const: stream_2_pixel
|
||||
- const: stream_3_pixel
|
||||
|
||||
phys:
|
||||
maxItems: 1
|
||||
|
|
@ -161,7 +178,6 @@ required:
|
|||
allOf:
|
||||
# AUX BUS does not exist on DP controllers
|
||||
# Audio output also is present only on DP output
|
||||
# p1 regions is present on DP, but not on eDP
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -174,12 +190,110 @@ allOf:
|
|||
properties:
|
||||
"#sound-dai-cells": false
|
||||
else:
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sa8775p-dp
|
||||
- qcom,x1e80100-dp
|
||||
then:
|
||||
oneOf:
|
||||
- required:
|
||||
- aux-bus
|
||||
- required:
|
||||
- "#sound-dai-cells"
|
||||
else:
|
||||
properties:
|
||||
aux-bus: false
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
# these platforms support SST only
|
||||
- qcom,sc7180-dp
|
||||
- qcom,sc7280-dp
|
||||
- qcom,sc7280-edp
|
||||
- qcom,sc8180x-edp
|
||||
- qcom,sc8280xp-edp
|
||||
then:
|
||||
properties:
|
||||
aux-bus: false
|
||||
reg:
|
||||
minItems: 5
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
maxItems: 5
|
||||
clocks:
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
clocks-names:
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
# these platforms support 2 streams MST on some interfaces,
|
||||
# others are SST only
|
||||
- qcom,sc8280xp-dp
|
||||
- qcom,x1e80100-dp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
clocks:
|
||||
minItems: 5
|
||||
maxItems: 6
|
||||
clocks-names:
|
||||
minItems: 5
|
||||
maxItems: 6
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
# 2 streams MST
|
||||
enum:
|
||||
- qcom,sc8180x-dp
|
||||
- qcom,sdm845-dp
|
||||
- qcom,sm8350-dp
|
||||
- qcom,sm8650-dp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
clocks:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
clocks-names:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
# these platforms support 4 stream MST on first DP,
|
||||
# 2 streams MST on the second one.
|
||||
- qcom,sa8775p-dp
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 9
|
||||
maxItems: 9
|
||||
clocks:
|
||||
minItems: 6
|
||||
maxItems: 8
|
||||
clocks-names:
|
||||
minItems: 6
|
||||
maxItems: 8
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ properties:
|
|||
- qcom,sar2130p-dsi-ctrl
|
||||
- qcom,sc7180-dsi-ctrl
|
||||
- qcom,sc7280-dsi-ctrl
|
||||
- qcom,sc8180x-dsi-ctrl
|
||||
- qcom,sdm660-dsi-ctrl
|
||||
- qcom,sdm670-dsi-ctrl
|
||||
- qcom,sdm845-dsi-ctrl
|
||||
|
|
@ -332,6 +333,7 @@ allOf:
|
|||
- qcom,sar2130p-dsi-ctrl
|
||||
- qcom,sc7180-dsi-ctrl
|
||||
- qcom,sc7280-dsi-ctrl
|
||||
- qcom,sc8180x-dsi-ctrl
|
||||
- qcom,sdm845-dsi-ctrl
|
||||
- qcom,sm6115-dsi-ctrl
|
||||
- qcom,sm6125-dsi-ctrl
|
||||
|
|
|
|||
|
|
@ -124,6 +124,40 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- qcom,adreno-gmu-623.0
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: Core GMU registers
|
||||
- description: Resource controller registers
|
||||
- description: GMU PDC registers
|
||||
reg-names:
|
||||
items:
|
||||
- const: gmu
|
||||
- const: rscc
|
||||
- const: gmu_pdc
|
||||
clocks:
|
||||
items:
|
||||
- description: GMU clock
|
||||
- description: GPU CX clock
|
||||
- description: GPU AXI clock
|
||||
- description: GPU MEMNOC clock
|
||||
- description: GPU AHB clock
|
||||
- description: GPU HUB CX clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: gmu
|
||||
- const: cxo
|
||||
- const: axi
|
||||
- const: memnoc
|
||||
- const: ahb
|
||||
- const: hub
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,adreno-gmu-635.0
|
||||
- qcom,adreno-gmu-660.1
|
||||
- qcom,adreno-gmu-663.0
|
||||
|
|
|
|||
|
|
@ -146,39 +146,209 @@ allOf:
|
|||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-[3-5][0-9][0-9]\.[0-9]+$'
|
||||
|
||||
oneOf:
|
||||
- pattern: '^qcom,adreno-305\.[0-9]+$'
|
||||
- pattern: '^qcom,adreno-330\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 7
|
||||
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
anyOf:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem
|
||||
description: GPU Memory clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
- const: alt_mem_iface
|
||||
description: GPU Alternative Memory Interface clock
|
||||
- const: gfx3d
|
||||
description: GPU 3D engine clock
|
||||
- const: rbbmtimer
|
||||
description: GPU RBBM Timer for Adreno 5xx series
|
||||
- const: rbcpr
|
||||
description: GPU RB Core Power Reduction clock
|
||||
minItems: 2
|
||||
maxItems: 7
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-306\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 5
|
||||
maxItems: 6
|
||||
clock-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
- const: alt_mem_iface
|
||||
description: GPU Alternative Memory Interface clock
|
||||
- const: gfx3d
|
||||
description: GPU 3D engine clock
|
||||
- items:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem
|
||||
description: GPU Memory clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
- const: alt_mem_iface
|
||||
description: GPU Alternative Memory Interface clock
|
||||
- const: gfx3d
|
||||
description: GPU 3D engine clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-320\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem
|
||||
description: GPU Memory clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-405\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 7
|
||||
maxItems: 7
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem
|
||||
description: GPU Memory clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
- const: alt_mem_iface
|
||||
description: GPU Alternative Memory Interface clock
|
||||
- const: gfx3d
|
||||
description: GPU 3D engine clock
|
||||
- const: rbbmtimer
|
||||
description: GPU RBBM Timer for Adreno 5xx series
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-50[56]\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
- const: alt_mem_iface
|
||||
description: GPU Alternative Memory Interface clock
|
||||
- const: rbbmtimer
|
||||
description: GPU RBBM Timer for Adreno 5xx series
|
||||
- const: alwayson
|
||||
description: GPU AON clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
oneOf:
|
||||
- pattern: '^qcom,adreno-508\.[0-9]+$'
|
||||
- pattern: '^qcom,adreno-509\.[0-9]+$'
|
||||
- pattern: '^qcom,adreno-512\.[0-9]+$'
|
||||
- pattern: '^qcom,adreno-540\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
clock-names:
|
||||
items:
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: rbbmtimer
|
||||
description: GPU RBBM Timer for Adreno 5xx series
|
||||
- const: mem
|
||||
description: GPU Memory clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
- const: rbcpr
|
||||
description: GPU RB Core Power Reduction clock
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-510\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: mem
|
||||
description: GPU Memory clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
- const: rbbmtimer
|
||||
description: GPU RBBM Timer for Adreno 5xx series
|
||||
- const: alwayson
|
||||
description: GPU AON clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-530\.[0-9]+$'
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
description: GPU Core clock
|
||||
- const: iface
|
||||
description: GPU Interface clock
|
||||
- const: rbbmtimer
|
||||
description: GPU RBBM Timer for Adreno 5xx series
|
||||
- const: mem
|
||||
description: GPU Memory clock
|
||||
- const: mem_iface
|
||||
description: GPU Memory Interface clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -187,6 +357,7 @@ allOf:
|
|||
enum:
|
||||
- qcom,adreno-610.0
|
||||
- qcom,adreno-619.1
|
||||
- qcom,adreno-07000200
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
|
|
@ -222,7 +393,9 @@ allOf:
|
|||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
pattern: '^qcom,adreno-[67][0-9][0-9]\.[0-9]+$'
|
||||
oneOf:
|
||||
- pattern: '^qcom,adreno-[67][0-9][0-9]\.[0-9]+$'
|
||||
- pattern: '^qcom,adreno-[0-9a-f]{8}$'
|
||||
|
||||
then: # Starting with A6xx, the clocks are usually defined in the GMU node
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -375,7 +375,11 @@ examples:
|
|||
<0xaf54200 0x0c0>,
|
||||
<0xaf55000 0x770>,
|
||||
<0xaf56000 0x09c>,
|
||||
<0xaf57000 0x09c>;
|
||||
<0xaf57000 0x09c>,
|
||||
<0xaf58000 0x09c>,
|
||||
<0xaf59000 0x09c>,
|
||||
<0xaf5a000 0x23c>,
|
||||
<0xaf5b000 0x23c>;
|
||||
|
||||
interrupt-parent = <&mdss0>;
|
||||
interrupts = <12>;
|
||||
|
|
@ -384,16 +388,28 @@ examples:
|
|||
<&dispcc_dptx0_aux_clk>,
|
||||
<&dispcc_dptx0_link_clk>,
|
||||
<&dispcc_dptx0_link_intf_clk>,
|
||||
<&dispcc_dptx0_pixel0_clk>;
|
||||
<&dispcc_dptx0_pixel0_clk>,
|
||||
<&dispcc_dptx0_pixel1_clk>,
|
||||
<&dispcc_dptx0_pixel2_clk>,
|
||||
<&dispcc_dptx0_pixel3_clk>;
|
||||
clock-names = "core_iface",
|
||||
"core_aux",
|
||||
"ctrl_link",
|
||||
"ctrl_link_iface",
|
||||
"stream_pixel";
|
||||
"stream_pixel",
|
||||
"stream_1_pixel",
|
||||
"stream_2_pixel",
|
||||
"stream_3_pixel";
|
||||
|
||||
assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
|
||||
<&dispcc_mdss_dptx0_pixel0_clk_src>;
|
||||
assigned-clock-parents = <&mdss0_dp0_phy 0>, <&mdss0_dp0_phy 1>;
|
||||
<&dispcc_mdss_dptx0_pixel0_clk_src>,
|
||||
<&dispcc_mdss_dptx0_pixel1_clk_src>,
|
||||
<&dispcc_mdss_dptx0_pixel2_clk_src>,
|
||||
<&dispcc_mdss_dptx0_pixel3_clk_src>;
|
||||
assigned-clock-parents = <&mdss0_dp0_phy 0>,
|
||||
<&mdss0_dp0_phy 1>,
|
||||
<&mdss0_dp0_phy 1>,
|
||||
<&mdss0_dp0_phy 1>;
|
||||
|
||||
phys = <&mdss0_dp0_phy>;
|
||||
phy-names = "dp";
|
||||
|
|
|
|||
|
|
@ -207,16 +207,20 @@ examples:
|
|||
<&dispcc_disp_cc_mdss_dptx0_aux_clk>,
|
||||
<&dispcc_disp_cc_mdss_dptx0_link_clk>,
|
||||
<&dispcc_disp_cc_mdss_dptx0_link_intf_clk>,
|
||||
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk>;
|
||||
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk>,
|
||||
<&dispcc_disp_cc_mdss_dptx0_pixel1_clk>;
|
||||
clock-names = "core_iface",
|
||||
"core_aux",
|
||||
"ctrl_link",
|
||||
"ctrl_link_iface",
|
||||
"stream_pixel";
|
||||
"stream_pixel",
|
||||
"stream_1_pixel";
|
||||
|
||||
assigned-clocks = <&dispcc_disp_cc_mdss_dptx0_link_clk_src>,
|
||||
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>;
|
||||
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>,
|
||||
<&dispcc_disp_cc_mdss_dptx0_pixel1_clk_src>;
|
||||
assigned-clock-parents = <&usb_dp_qmpphy_QMP_USB43DP_DP_LINK_CLK>,
|
||||
<&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>,
|
||||
<&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>;
|
||||
|
||||
phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
|
||||
|
|
|
|||
|
|
@ -281,7 +281,8 @@ examples:
|
|||
reg = <0xaea0000 0x200>,
|
||||
<0xaea0200 0x200>,
|
||||
<0xaea0400 0xc00>,
|
||||
<0xaea1000 0x400>;
|
||||
<0xaea1000 0x400>,
|
||||
<0xaea1400 0x400>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <14>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sc8180x-dpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SC8180X Display DPU
|
||||
|
||||
maintainers:
|
||||
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
|
||||
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sc8180x-dpu
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Address offset and size for mdp register set
|
||||
- description: Address offset and size for vbif register set
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: mdp
|
||||
- const: vbif
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display AHB clock
|
||||
- description: Display HF AXI clock
|
||||
- description: Display core clock
|
||||
- description: Display vsync clock
|
||||
- description: Display rotator clock
|
||||
- description: Display LUT clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: iface
|
||||
- const: bus
|
||||
- const: core
|
||||
- const: vsync
|
||||
- const: rot
|
||||
- const: lut
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,dispcc-sm8250.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sc8180x.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interconnect/qcom,sc8180x.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sc8180x-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_VSYNC_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_ROT_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>;
|
||||
clock-names = "iface",
|
||||
"bus",
|
||||
"core",
|
||||
"vsync",
|
||||
"rot",
|
||||
"lut";
|
||||
|
||||
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dsi1_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,359 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,sc8180x-mdss.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SC8180X Display MDSS
|
||||
|
||||
maintainers:
|
||||
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
|
||||
description:
|
||||
Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
|
||||
sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
|
||||
bindings of MDSS are mentioned for SC8180X target.
|
||||
|
||||
$ref: /schemas/display/msm/mdss-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: qcom,sc8180x-mdss
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display AHB clock from gcc
|
||||
- description: Display hf axi clock
|
||||
- description: Display sf axi clock
|
||||
- description: Display core clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: iface
|
||||
- const: bus
|
||||
- const: nrt_bus
|
||||
- const: core
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
interconnects:
|
||||
maxItems: 3
|
||||
|
||||
interconnect-names:
|
||||
maxItems: 3
|
||||
|
||||
patternProperties:
|
||||
"^display-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sc8180x-dpu
|
||||
|
||||
"^displayport-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sc8180x-dp
|
||||
- qcom,sc8180x-edp
|
||||
|
||||
"^dsi@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,sc8180x-dsi-ctrl
|
||||
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,dsi-phy-7nm
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,dispcc-sm8250.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sc8180x.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interconnect/qcom,sc8180x.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
display-subsystem@ae00000 {
|
||||
compatible = "qcom,sc8180x-mdss";
|
||||
reg = <0x0ae00000 0x1000>;
|
||||
reg-names = "mdss";
|
||||
|
||||
interconnects = <&mmss_noc MASTER_MDP_PORT0 &mc_virt SLAVE_EBI_CH0>,
|
||||
<&mmss_noc MASTER_MDP_PORT1 &mc_virt SLAVE_EBI_CH0>,
|
||||
<&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_DISPLAY_CFG>;
|
||||
interconnect-names = "mdp0-mem",
|
||||
"mdp1-mem",
|
||||
"cpu-cfg";
|
||||
|
||||
power-domains = <&dispcc MDSS_GDSC>;
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&gcc GCC_DISP_SF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>;
|
||||
clock-names = "iface", "bus", "nrt_bus", "core";
|
||||
|
||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
iommus = <&apps_smmu 0x800 0x420>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
display-controller@ae01000 {
|
||||
compatible = "qcom,sc8180x-dpu";
|
||||
reg = <0x0ae01000 0x8f000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp", "vbif";
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_VSYNC_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_ROT_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>;
|
||||
clock-names = "iface",
|
||||
"bus",
|
||||
"core",
|
||||
"vsync",
|
||||
"rot",
|
||||
"lut";
|
||||
|
||||
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dpu_intf1_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dpu_intf2_out: endpoint {
|
||||
remote-endpoint = <&dsi1_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-171428571 {
|
||||
opp-hz = /bits/ 64 <171428571>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-345000000 {
|
||||
opp-hz = /bits/ 64 <345000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-460000000 {
|
||||
opp-hz = /bits/ 64 <460000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dsi@ae94000 {
|
||||
compatible = "qcom,sc8180x-dsi-ctrl",
|
||||
"qcom,mdss-dsi-ctrl";
|
||||
reg = <0x0ae94000 0x400>;
|
||||
reg-names = "dsi_ctrl";
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <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 = <&dsi0_phy 0>, <&dsi0_phy 1>;
|
||||
|
||||
operating-points-v2 = <&dsi_opp_table>;
|
||||
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||
|
||||
phys = <&dsi0_phy>;
|
||||
phy-names = "dsi";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi0_in: endpoint {
|
||||
remote-endpoint = <&dpu_intf1_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dsi0_out: endpoint {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dsi0_phy: phy@ae94400 {
|
||||
compatible = "qcom,dsi-phy-7nm";
|
||||
reg = <0x0ae94400 0x200>,
|
||||
<0x0ae94600 0x280>,
|
||||
<0x0ae94900 0x260>;
|
||||
reg-names = "dsi_phy",
|
||||
"dsi_phy_lane",
|
||||
"dsi_pll";
|
||||
|
||||
#clock-cells = <1>;
|
||||
#phy-cells = <0>;
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&rpmhcc RPMH_CXO_CLK>;
|
||||
clock-names = "iface", "ref";
|
||||
vdds-supply = <&vreg_dsi_phy>;
|
||||
};
|
||||
|
||||
dsi@ae96000 {
|
||||
compatible = "qcom,sc8180x-dsi-ctrl",
|
||||
"qcom,mdss-dsi-ctrl";
|
||||
reg = <0x0ae96000 0x400>;
|
||||
reg-names = "dsi_ctrl";
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <5>;
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_PCLK1_CLK>,
|
||||
<&dispcc DISP_CC_MDSS_ESC1_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_BYTE1_CLK_SRC>,
|
||||
<&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
|
||||
assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
|
||||
|
||||
operating-points-v2 = <&dsi_opp_table>;
|
||||
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||
|
||||
phys = <&dsi1_phy>;
|
||||
phy-names = "dsi";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi1_in: endpoint {
|
||||
remote-endpoint = <&dpu_intf2_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dsi1_out: endpoint {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dsi1_phy: phy@ae96400 {
|
||||
compatible = "qcom,dsi-phy-7nm";
|
||||
reg = <0x0ae96400 0x200>,
|
||||
<0x0ae96600 0x280>,
|
||||
<0x0ae96900 0x260>;
|
||||
reg-names = "dsi_phy",
|
||||
"dsi_phy_lane",
|
||||
"dsi_pll";
|
||||
|
||||
#clock-cells = <1>;
|
||||
#phy-cells = <0>;
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&rpmhcc RPMH_CXO_CLK>;
|
||||
clock-names = "iface", "ref";
|
||||
vdds-supply = <&vreg_dsi_phy>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -61,7 +61,8 @@ patternProperties:
|
|||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm7150-dp
|
||||
contains:
|
||||
const: qcom,sm7150-dp
|
||||
|
||||
"^dsi@[0-9a-f]+$":
|
||||
type: object
|
||||
|
|
@ -378,7 +379,8 @@ examples:
|
|||
};
|
||||
|
||||
displayport-controller@ae90000 {
|
||||
compatible = "qcom,sm7150-dp";
|
||||
compatible = "qcom,sm7150-dp",
|
||||
"qcom,sm8350-dp";
|
||||
reg = <0xae90000 0x200>,
|
||||
<0xae90200 0x200>,
|
||||
<0xae90400 0xc00>,
|
||||
|
|
@ -392,16 +394,20 @@ examples:
|
|||
<&dispcc_mdss_dp_aux_clk>,
|
||||
<&dispcc_mdss_dp_link_clk>,
|
||||
<&dispcc_mdss_dp_link_intf_clk>,
|
||||
<&dispcc_mdss_dp_pixel_clk>;
|
||||
<&dispcc_mdss_dp_pixel_clk>,
|
||||
<&dispcc_mdss_dp_pixel1_clk>;
|
||||
clock-names = "core_iface",
|
||||
"core_aux",
|
||||
"ctrl_link",
|
||||
"ctrl_link_iface",
|
||||
"stream_pixel";
|
||||
"stream_pixel",
|
||||
"stream_1_pixel";
|
||||
|
||||
assigned-clocks = <&dispcc_mdss_dp_link_clk_src>,
|
||||
<&dispcc_mdss_dp_pixel_clk_src>;
|
||||
<&dispcc_mdss_dp_pixel_clk_src>,
|
||||
<&dispcc_mdss_dp_pixel1_clk_src>;
|
||||
assigned-clock-parents = <&dp_phy 0>,
|
||||
<&dp_phy 1>,
|
||||
<&dp_phy 1>;
|
||||
|
||||
operating-points-v2 = <&dp_opp_table>;
|
||||
|
|
|
|||
|
|
@ -401,16 +401,20 @@ examples:
|
|||
<&disp_cc_mdss_dptx0_aux_clk>,
|
||||
<&disp_cc_mdss_dptx0_link_clk>,
|
||||
<&disp_cc_mdss_dptx0_link_intf_clk>,
|
||||
<&disp_cc_mdss_dptx0_pixel0_clk>;
|
||||
<&disp_cc_mdss_dptx0_pixel0_clk>,
|
||||
<&disp_cc_mdss_dptx0_pixel1_clk>;
|
||||
clock-names = "core_iface",
|
||||
"core_aux",
|
||||
"ctrl_link",
|
||||
"ctrl_link_iface",
|
||||
"stream_pixel";
|
||||
"stream_pixel",
|
||||
"stream_1_pixel";
|
||||
|
||||
assigned-clocks = <&disp_cc_mdss_dptx0_link_clk_src>,
|
||||
<&disp_cc_mdss_dptx0_pixel0_clk_src>;
|
||||
<&disp_cc_mdss_dptx0_pixel0_clk_src>,
|
||||
<&disp_cc_mdss_dptx0_pixel1_clk_src>;
|
||||
assigned-clock-parents = <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
|
||||
<&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
|
||||
<&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
|
||||
|
||||
operating-points-v2 = <&dp_opp_table>;
|
||||
|
|
|
|||
|
|
@ -170,11 +170,11 @@ examples:
|
|||
|
||||
displayport-controller@ae90000 {
|
||||
compatible = "qcom,x1e80100-dp";
|
||||
reg = <0 0xae90000 0 0x200>,
|
||||
<0 0xae90200 0 0x200>,
|
||||
<0 0xae90400 0 0x600>,
|
||||
<0 0xae91000 0 0x400>,
|
||||
<0 0xae91400 0 0x400>;
|
||||
reg = <0xae90000 0x200>,
|
||||
<0xae90200 0x200>,
|
||||
<0xae90400 0x600>,
|
||||
<0xae91000 0x400>,
|
||||
<0xae91400 0x400>;
|
||||
|
||||
interrupt-parent = <&mdss>;
|
||||
interrupts = <12>;
|
||||
|
|
@ -183,15 +183,19 @@ examples:
|
|||
<&dispcc_dptx0_aux_clk>,
|
||||
<&dispcc_dptx0_link_clk>,
|
||||
<&dispcc_dptx0_link_intf_clk>,
|
||||
<&dispcc_dptx0_pixel0_clk>;
|
||||
<&dispcc_dptx0_pixel0_clk>,
|
||||
<&dispcc_dptx0_pixel1_clk>;
|
||||
clock-names = "core_iface", "core_aux",
|
||||
"ctrl_link",
|
||||
"ctrl_link_iface",
|
||||
"stream_pixel";
|
||||
"stream_pixel",
|
||||
"stream_1_pixel";
|
||||
|
||||
assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
|
||||
<&dispcc_mdss_dptx0_pixel0_clk_src>;
|
||||
<&dispcc_mdss_dptx0_pixel0_clk_src>,
|
||||
<&dispcc_mdss_dptx0_pixel1_clk_src>;
|
||||
assigned-clock-parents = <&usb_1_ss0_qmpphy QMP_USB43DP_DP_LINK_CLK>,
|
||||
<&usb_1_ss0_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
|
||||
<&usb_1_ss0_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
|
||||
|
||||
operating-points-v2 = <&mdss_dp0_opp_table>;
|
||||
|
|
|
|||
|
|
@ -913,6 +913,11 @@ static const struct adreno_info a6xx_gpus[] = {
|
|||
{ /* sentinel */ },
|
||||
},
|
||||
},
|
||||
.speedbins = ADRENO_SPEEDBINS(
|
||||
{ 0, 0 },
|
||||
{ 185, 0 },
|
||||
{ 127, 1 },
|
||||
),
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(
|
||||
0x06030001,
|
||||
|
|
@ -1024,6 +1029,11 @@ static const struct adreno_info a6xx_gpus[] = {
|
|||
.gmu_cgc_mode = 0x00020200,
|
||||
.prim_fifo_threshold = 0x00300200,
|
||||
},
|
||||
.speedbins = ADRENO_SPEEDBINS(
|
||||
{ 0, 0 },
|
||||
{ 169, 0 },
|
||||
{ 113, 1 },
|
||||
),
|
||||
}, {
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x06030500),
|
||||
.family = ADRENO_6XX_GEN4,
|
||||
|
|
@ -1343,6 +1353,69 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
|
|||
|
||||
DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist);
|
||||
|
||||
/* Applicable for X185, A750 */
|
||||
static const u32 a750_ifpc_reglist_regs[] = {
|
||||
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(0),
|
||||
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(1),
|
||||
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
|
||||
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
|
||||
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
|
||||
REG_A6XX_TPL1_NC_MODE_CNTL,
|
||||
REG_A6XX_SP_NC_MODE_CNTL,
|
||||
REG_A6XX_CP_DBG_ECO_CNTL,
|
||||
REG_A6XX_CP_PROTECT_CNTL,
|
||||
REG_A6XX_CP_PROTECT(0),
|
||||
REG_A6XX_CP_PROTECT(1),
|
||||
REG_A6XX_CP_PROTECT(2),
|
||||
REG_A6XX_CP_PROTECT(3),
|
||||
REG_A6XX_CP_PROTECT(4),
|
||||
REG_A6XX_CP_PROTECT(5),
|
||||
REG_A6XX_CP_PROTECT(6),
|
||||
REG_A6XX_CP_PROTECT(7),
|
||||
REG_A6XX_CP_PROTECT(8),
|
||||
REG_A6XX_CP_PROTECT(9),
|
||||
REG_A6XX_CP_PROTECT(10),
|
||||
REG_A6XX_CP_PROTECT(11),
|
||||
REG_A6XX_CP_PROTECT(12),
|
||||
REG_A6XX_CP_PROTECT(13),
|
||||
REG_A6XX_CP_PROTECT(14),
|
||||
REG_A6XX_CP_PROTECT(15),
|
||||
REG_A6XX_CP_PROTECT(16),
|
||||
REG_A6XX_CP_PROTECT(17),
|
||||
REG_A6XX_CP_PROTECT(18),
|
||||
REG_A6XX_CP_PROTECT(19),
|
||||
REG_A6XX_CP_PROTECT(20),
|
||||
REG_A6XX_CP_PROTECT(21),
|
||||
REG_A6XX_CP_PROTECT(22),
|
||||
REG_A6XX_CP_PROTECT(23),
|
||||
REG_A6XX_CP_PROTECT(24),
|
||||
REG_A6XX_CP_PROTECT(25),
|
||||
REG_A6XX_CP_PROTECT(26),
|
||||
REG_A6XX_CP_PROTECT(27),
|
||||
REG_A6XX_CP_PROTECT(28),
|
||||
REG_A6XX_CP_PROTECT(29),
|
||||
REG_A6XX_CP_PROTECT(30),
|
||||
REG_A6XX_CP_PROTECT(31),
|
||||
REG_A6XX_CP_PROTECT(32),
|
||||
REG_A6XX_CP_PROTECT(33),
|
||||
REG_A6XX_CP_PROTECT(34),
|
||||
REG_A6XX_CP_PROTECT(35),
|
||||
REG_A6XX_CP_PROTECT(36),
|
||||
REG_A6XX_CP_PROTECT(37),
|
||||
REG_A6XX_CP_PROTECT(38),
|
||||
REG_A6XX_CP_PROTECT(39),
|
||||
REG_A6XX_CP_PROTECT(40),
|
||||
REG_A6XX_CP_PROTECT(41),
|
||||
REG_A6XX_CP_PROTECT(42),
|
||||
REG_A6XX_CP_PROTECT(43),
|
||||
REG_A6XX_CP_PROTECT(44),
|
||||
REG_A6XX_CP_PROTECT(45),
|
||||
REG_A6XX_CP_PROTECT(46),
|
||||
REG_A6XX_CP_PROTECT(47),
|
||||
};
|
||||
|
||||
DECLARE_ADRENO_REGLIST_LIST(a750_ifpc_reglist);
|
||||
|
||||
static const struct adreno_info a7xx_gpus[] = {
|
||||
{
|
||||
.chip_ids = ADRENO_CHIP_IDS(0x07000200),
|
||||
|
|
@ -1432,14 +1505,27 @@ static const struct adreno_info a7xx_gpus[] = {
|
|||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV |
|
||||
ADRENO_QUIRK_PREEMPTION,
|
||||
ADRENO_QUIRK_PREEMPTION |
|
||||
ADRENO_QUIRK_IFPC,
|
||||
.init = a6xx_gpu_init,
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.hwcg = a740_hwcg,
|
||||
.protect = &a730_protect,
|
||||
.pwrup_reglist = &a7xx_pwrup_reglist,
|
||||
.ifpc_reglist = &a750_ifpc_reglist,
|
||||
.gmu_chipid = 0x7050001,
|
||||
.gmu_cgc_mode = 0x00020202,
|
||||
.bcms = (const struct a6xx_bcm[]) {
|
||||
{ .name = "SH0", .buswidth = 16 },
|
||||
{ .name = "MC0", .buswidth = 4 },
|
||||
{
|
||||
.name = "ACV",
|
||||
.fixed = true,
|
||||
.perfmode = BIT(3),
|
||||
.perfmode_bw = 16500000,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
},
|
||||
},
|
||||
.preempt_record_size = 4192 * SZ_1K,
|
||||
.speedbins = ADRENO_SPEEDBINS(
|
||||
|
|
@ -1460,12 +1546,14 @@ static const struct adreno_info a7xx_gpus[] = {
|
|||
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
|
||||
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
|
||||
ADRENO_QUIRK_HAS_HW_APRIV |
|
||||
ADRENO_QUIRK_PREEMPTION,
|
||||
ADRENO_QUIRK_PREEMPTION |
|
||||
ADRENO_QUIRK_IFPC,
|
||||
.init = a6xx_gpu_init,
|
||||
.zapfw = "gen70900_zap.mbn",
|
||||
.a6xx = &(const struct a6xx_info) {
|
||||
.protect = &a730_protect,
|
||||
.pwrup_reglist = &a7xx_pwrup_reglist,
|
||||
.ifpc_reglist = &a750_ifpc_reglist,
|
||||
.gmu_chipid = 0x7090100,
|
||||
.gmu_cgc_mode = 0x00020202,
|
||||
.bcms = (const struct a6xx_bcm[]) {
|
||||
|
|
|
|||
|
|
@ -93,14 +93,25 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu)
|
|||
/* Check to see if the GX rail is still powered */
|
||||
bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
|
||||
{
|
||||
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
u32 val;
|
||||
|
||||
/* This can be called from gpu state code so make sure GMU is valid */
|
||||
if (!gmu->initialized)
|
||||
return false;
|
||||
|
||||
/* If GMU is absent, then GX power domain is ON as long as GPU is in active state */
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
return true;
|
||||
|
||||
val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
|
||||
|
||||
if (adreno_is_a7xx(adreno_gpu))
|
||||
return !(val &
|
||||
(A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
|
||||
A7XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
|
||||
|
||||
return !(val &
|
||||
(A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
|
||||
A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
|
||||
|
|
@ -272,6 +283,8 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
|
|||
if (ret)
|
||||
DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
|
||||
|
||||
set_bit(GMU_STATUS_FW_START, &gmu->status);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +416,10 @@ int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
|
|||
int ret;
|
||||
u32 val;
|
||||
|
||||
if (!gmu->legacy)
|
||||
WARN_ON(!gmu->legacy);
|
||||
|
||||
/* Nothing to do if GMU does the power management */
|
||||
if (gmu->idle_level > GMU_IDLE_STATE_ACTIVE)
|
||||
return 0;
|
||||
|
||||
gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);
|
||||
|
|
@ -518,6 +534,9 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
|
|||
int ret;
|
||||
u32 val;
|
||||
|
||||
if (!test_and_clear_bit(GMU_STATUS_PDC_SLEEP, &gmu->status))
|
||||
return 0;
|
||||
|
||||
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
|
||||
|
||||
ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
|
||||
|
|
@ -545,6 +564,9 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
|
|||
int ret;
|
||||
u32 val;
|
||||
|
||||
if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
|
||||
return;
|
||||
|
||||
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
|
||||
|
||||
ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
|
||||
|
|
@ -553,6 +575,8 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
|
|||
DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
|
||||
|
||||
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
|
||||
|
||||
set_bit(GMU_STATUS_PDC_SLEEP, &gmu->status);
|
||||
}
|
||||
|
||||
static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
|
||||
|
|
@ -681,8 +705,6 @@ setup_pdc:
|
|||
/* ensure no writes happen before the uCode is fully written */
|
||||
wmb();
|
||||
|
||||
a6xx_rpmh_stop(gmu);
|
||||
|
||||
err:
|
||||
if (!IS_ERR_OR_NULL(pdcptr))
|
||||
iounmap(pdcptr);
|
||||
|
|
@ -842,19 +864,15 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
|
|||
else
|
||||
gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
|
||||
|
||||
if (state == GMU_WARM_BOOT) {
|
||||
ret = a6xx_rpmh_start(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = a6xx_rpmh_start(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (state == GMU_COLD_BOOT) {
|
||||
if (WARN(!adreno_gpu->fw[ADRENO_FW_GMU],
|
||||
"GMU firmware is not loaded\n"))
|
||||
return -ENOENT;
|
||||
|
||||
ret = a6xx_rpmh_start(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = a6xx_gmu_fw_load(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -925,10 +943,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
|
|||
ret = a6xx_gmu_gfx_rail_on(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable SPTP_PC if the CPU is responsible for it */
|
||||
if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {
|
||||
ret = a6xx_sptprac_enable(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -980,6 +995,22 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
|
|||
val, (val & 1), 100, 10000);
|
||||
gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS + seqmem_off,
|
||||
val, (val & 1), 100, 1000);
|
||||
|
||||
if (!adreno_is_a740_family(adreno_gpu))
|
||||
return;
|
||||
|
||||
gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS4_DRV0_STATUS + seqmem_off,
|
||||
val, (val & 1), 100, 10000);
|
||||
gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS5_DRV0_STATUS + seqmem_off,
|
||||
val, (val & 1), 100, 10000);
|
||||
gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS6_DRV0_STATUS + seqmem_off,
|
||||
val, (val & 1), 100, 10000);
|
||||
gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS7_DRV0_STATUS + seqmem_off,
|
||||
val, (val & 1), 100, 1000);
|
||||
gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS8_DRV0_STATUS + seqmem_off,
|
||||
val, (val & 1), 100, 10000);
|
||||
gmu_poll_timeout_rscc(gmu, REG_A7XX_RSCC_TCS9_DRV0_STATUS + seqmem_off,
|
||||
val, (val & 1), 100, 1000);
|
||||
}
|
||||
|
||||
/* Force the GMU off in case it isn't responsive */
|
||||
|
|
@ -1023,6 +1054,8 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
|
|||
|
||||
/* Reset GPU core blocks */
|
||||
a6xx_gpu_sw_reset(gpu, true);
|
||||
|
||||
a6xx_rpmh_stop(gmu);
|
||||
}
|
||||
|
||||
static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
|
||||
|
|
@ -1128,6 +1161,11 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
|
|||
/* Set the GPU to the current freq */
|
||||
a6xx_gmu_set_initial_freq(gpu, gmu);
|
||||
|
||||
if (refcount_read(&gpu->sysprof_active) > 1) {
|
||||
ret = a6xx_gmu_set_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
if (!ret)
|
||||
set_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status);
|
||||
}
|
||||
out:
|
||||
/* On failure, shut down the GMU to leave it in a good state */
|
||||
if (ret) {
|
||||
|
|
@ -1175,6 +1213,9 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
|
|||
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(GMU_STATUS_OOB_PERF_SET, &gmu->status))
|
||||
a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
ret = a6xx_gmu_wait_for_idle(gmu);
|
||||
|
||||
/* If the GMU isn't responding assume it is hung */
|
||||
|
|
@ -1318,8 +1359,6 @@ static int a6xx_gmu_memory_probe(struct drm_device *drm, struct a6xx_gmu *gmu)
|
|||
struct msm_mmu *mmu;
|
||||
|
||||
mmu = msm_iommu_new(gmu->dev, 0);
|
||||
if (!mmu)
|
||||
return -ENODEV;
|
||||
if (IS_ERR(mmu))
|
||||
return PTR_ERR(mmu);
|
||||
|
||||
|
|
@ -1692,6 +1731,7 @@ static int a6xx_gmu_acd_probe(struct a6xx_gmu *gmu)
|
|||
u32 val;
|
||||
|
||||
freq = gmu->gpu_freqs[i];
|
||||
/* This is unlikely to fail because we are passing back a known freq */
|
||||
opp = dev_pm_opp_find_freq_exact(&gpu->pdev->dev, freq, true);
|
||||
np = dev_pm_opp_get_of_node(opp);
|
||||
|
||||
|
|
@ -1790,6 +1830,35 @@ 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)
|
||||
{
|
||||
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))
|
||||
return;
|
||||
|
||||
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))
|
||||
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))
|
||||
a6xx_gmu_clear_oob(gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
mutex_unlock(&gmu->lock);
|
||||
|
||||
pm_runtime_put(&gpu->pdev->dev);
|
||||
}
|
||||
|
||||
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
|
|
@ -1932,8 +2001,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Fow now, don't do anything fancy until we get our feet under us */
|
||||
gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
|
||||
/* Set GMU idle level */
|
||||
gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ?
|
||||
GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE;
|
||||
|
||||
pm_runtime_enable(gmu->dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ struct a6xx_bcm {
|
|||
/* The GMU does not do any idle state management */
|
||||
#define GMU_IDLE_STATE_ACTIVE 0
|
||||
|
||||
/* Unknown power state. Not exposed by the firmware. For documentation purpose only */
|
||||
#define GMU_IDLE_STATE_RESERVED 1
|
||||
|
||||
/* The GMU manages SPTP power collapse */
|
||||
#define GMU_IDLE_STATE_SPTP 2
|
||||
|
||||
|
|
@ -117,6 +120,14 @@ struct a6xx_gmu {
|
|||
|
||||
struct qmp *qmp;
|
||||
struct a6xx_hfi_msg_bw_table *bw_table;
|
||||
|
||||
/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */
|
||||
#define GMU_STATUS_FW_START 0
|
||||
/* To track if PDC sleep seq was done */
|
||||
#define GMU_STATUS_PDC_SLEEP 1
|
||||
/* To track Perfcounter OOB set status */
|
||||
#define GMU_STATUS_OOB_PERF_SET 2
|
||||
unsigned long status;
|
||||
};
|
||||
|
||||
static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
|
||||
|
|
@ -158,6 +169,9 @@ static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi)
|
|||
#define gmu_poll_timeout(gmu, addr, val, cond, interval, timeout) \
|
||||
readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \
|
||||
interval, timeout)
|
||||
#define gmu_poll_timeout_atomic(gmu, addr, val, cond, interval, timeout) \
|
||||
readl_poll_timeout_atomic((gmu)->mmio + ((addr) << 2), val, cond, \
|
||||
interval, timeout)
|
||||
|
||||
static inline u32 gmu_read_rscc(struct a6xx_gmu *gmu, u32 offset)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,6 +16,97 @@
|
|||
|
||||
#define GPU_PAS_ID 13
|
||||
|
||||
static u64 read_gmu_ao_counter(struct a6xx_gpu *a6xx_gpu)
|
||||
{
|
||||
u64 count_hi, count_lo, temp;
|
||||
|
||||
do {
|
||||
count_hi = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
|
||||
count_lo = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_L);
|
||||
temp = gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_H);
|
||||
} while (unlikely(count_hi != temp));
|
||||
|
||||
return (count_hi << 32) | count_lo;
|
||||
}
|
||||
|
||||
static bool fence_status_check(struct msm_gpu *gpu, u32 offset, u32 value, u32 status, u32 mask)
|
||||
{
|
||||
/* Success if !writedropped0/1 */
|
||||
if (!(status & mask))
|
||||
return true;
|
||||
|
||||
udelay(10);
|
||||
|
||||
/* Try to update fenced register again */
|
||||
gpu_write(gpu, offset, value);
|
||||
|
||||
/* We can't do a posted write here because the power domain could be
|
||||
* in collapse state. So use the heaviest barrier instead
|
||||
*/
|
||||
mb();
|
||||
return false;
|
||||
}
|
||||
|
||||
static int fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u32 value, u32 mask)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
struct msm_gpu *gpu = &adreno_gpu->base;
|
||||
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
|
||||
u32 status;
|
||||
|
||||
gpu_write(gpu, offset, value);
|
||||
|
||||
/* Nothing else to be done in the case of no-GMU */
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
return 0;
|
||||
|
||||
/* We can't do a posted write here because the power domain could be
|
||||
* in collapse state. So use the heaviest barrier instead
|
||||
*/
|
||||
mb();
|
||||
|
||||
if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
|
||||
fence_status_check(gpu, offset, value, status, mask), 0, 1000))
|
||||
return 0;
|
||||
|
||||
/* Try again for another 1ms before failing */
|
||||
gpu_write(gpu, offset, value);
|
||||
mb();
|
||||
|
||||
if (!gmu_poll_timeout(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS, status,
|
||||
fence_status_check(gpu, offset, value, status, mask), 0, 1000)) {
|
||||
/*
|
||||
* The 'delay' warning is here because the pause to print this
|
||||
* warning will allow gpu to move to power collapse which
|
||||
* defeats the purpose of continuous polling for 2 ms
|
||||
*/
|
||||
dev_err_ratelimited(gmu->dev, "delay in fenced register write (0x%x)\n",
|
||||
offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_err_ratelimited(gmu->dev, "fenced register write (0x%x) fail\n",
|
||||
offset);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
int a6xx_fenced_write(struct a6xx_gpu *a6xx_gpu, u32 offset, u64 value, u32 mask, bool is_64b)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fenced_write(a6xx_gpu, offset, lower_32_bits(value), mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!is_64b)
|
||||
return 0;
|
||||
|
||||
ret = fenced_write(a6xx_gpu, offset + 1, upper_32_bits(value), mask);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
|
|
@ -86,7 +177,7 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
/* Update HW if this is the current ring and we are not in preempt*/
|
||||
if (!a6xx_in_preempt(a6xx_gpu)) {
|
||||
if (a6xx_gpu->cur_ring == ring)
|
||||
gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
|
||||
a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
|
||||
else
|
||||
ring->restore_wptr = true;
|
||||
} else {
|
||||
|
|
@ -173,8 +264,8 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
|||
* Needed for preemption
|
||||
*/
|
||||
OUT_PKT7(ring, CP_MEM_WRITE, 5);
|
||||
OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr)));
|
||||
OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr)));
|
||||
OUT_RING(ring, A5XX_CP_MEM_WRITE_ADDR_LO(lower_32_bits(memptr)));
|
||||
OUT_RING(ring, A5XX_CP_MEM_WRITE_ADDR_HI(upper_32_bits(memptr)));
|
||||
OUT_RING(ring, lower_32_bits(ttbr));
|
||||
OUT_RING(ring, upper_32_bits(ttbr));
|
||||
OUT_RING(ring, ctx->seqno);
|
||||
|
|
@ -204,9 +295,9 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
|||
*/
|
||||
OUT_PKT7(ring, CP_WAIT_REG_MEM, 6);
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ));
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_1_POLL_ADDR_LO(
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_POLL_ADDR_LO(
|
||||
REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS));
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_2_POLL_ADDR_HI(0));
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_POLL_ADDR_HI(0));
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_3_REF(0x1));
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_4_MASK(0x1));
|
||||
OUT_RING(ring, CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0));
|
||||
|
|
@ -298,8 +389,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
|
||||
OUT_RING(ring, submit->seqno);
|
||||
|
||||
trace_msm_gpu_submit_flush(submit,
|
||||
gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER));
|
||||
trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu));
|
||||
|
||||
a6xx_flush(gpu, ring);
|
||||
}
|
||||
|
|
@ -499,8 +589,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
}
|
||||
|
||||
|
||||
trace_msm_gpu_submit_flush(submit,
|
||||
gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER));
|
||||
trace_msm_gpu_submit_flush(submit, read_gmu_ao_counter(a6xx_gpu));
|
||||
|
||||
a6xx_flush(gpu, ring);
|
||||
|
||||
|
|
@ -739,11 +828,10 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
|
|||
u32 *dest = (u32 *)&lock->regs[0];
|
||||
int i;
|
||||
|
||||
reglist = adreno_gpu->info->a6xx->pwrup_reglist;
|
||||
|
||||
lock->gpu_req = lock->cpu_req = lock->turn = 0;
|
||||
lock->ifpc_list_len = 0;
|
||||
lock->preemption_list_len = reglist->count;
|
||||
|
||||
reglist = adreno_gpu->info->a6xx->ifpc_reglist;
|
||||
lock->ifpc_list_len = reglist->count;
|
||||
|
||||
/*
|
||||
* For each entry in each of the lists, write the offset and the current
|
||||
|
|
@ -754,6 +842,14 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
|
|||
*dest++ = gpu_read(gpu, reglist->regs[i]);
|
||||
}
|
||||
|
||||
reglist = adreno_gpu->info->a6xx->pwrup_reglist;
|
||||
lock->preemption_list_len = reglist->count;
|
||||
|
||||
for (i = 0; i < reglist->count; i++) {
|
||||
*dest++ = reglist->regs[i];
|
||||
*dest++ = gpu_read(gpu, reglist->regs[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The overall register list is composed of
|
||||
* 1. Static IFPC-only registers
|
||||
|
|
@ -1241,14 +1337,14 @@ static int hw_init(struct msm_gpu *gpu)
|
|||
|
||||
/* Set weights for bicubic filtering */
|
||||
if (adreno_is_a650_family(adreno_gpu) || adreno_is_x185(adreno_gpu)) {
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0);
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(0), 0);
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(1),
|
||||
0x3fe05ff4);
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2,
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
|
||||
0x3fa0ebee);
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3,
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
|
||||
0x3f5193ed);
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4,
|
||||
gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
|
||||
0x3f0243f0);
|
||||
}
|
||||
|
||||
|
|
@ -1448,21 +1544,25 @@ static void a6xx_recover(struct msm_gpu *gpu)
|
|||
|
||||
adreno_dump_info(gpu);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
DRM_DEV_INFO(&gpu->pdev->dev, "CP_SCRATCH_REG%d: %u\n", i,
|
||||
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(i)));
|
||||
if (a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) {
|
||||
/* Sometimes crashstate capture is skipped, so SQE should be halted here again */
|
||||
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
|
||||
|
||||
if (hang_debug)
|
||||
a6xx_dump(gpu);
|
||||
for (i = 0; i < 8; i++)
|
||||
DRM_DEV_INFO(&gpu->pdev->dev, "CP_SCRATCH_REG%d: %u\n", i,
|
||||
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(i)));
|
||||
|
||||
if (hang_debug)
|
||||
a6xx_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_A6XX_CP_SQE_CNTL, 3);
|
||||
a6xx_gpu->hung = true;
|
||||
|
||||
pm_runtime_dont_use_autosuspend(&gpu->pdev->dev);
|
||||
|
||||
|
|
@ -1693,8 +1793,6 @@ static void a6xx_cp_hw_err_irq(struct msm_gpu *gpu)
|
|||
|
||||
static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
|
||||
|
||||
/*
|
||||
|
|
@ -1706,13 +1804,6 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
|
|||
if (gpu_read(gpu, REG_A6XX_RBBM_STATUS3) & A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Force the GPU to stay on until after we finish
|
||||
* collecting information
|
||||
*/
|
||||
if (!adreno_has_gmu_wrapper(adreno_gpu))
|
||||
gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1);
|
||||
|
||||
DRM_DEV_ERROR(&gpu->pdev->dev,
|
||||
"gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
|
||||
ring ? ring->id : -1, ring ? ring->fctx->last_fence : 0,
|
||||
|
|
@ -1727,6 +1818,9 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
|
|||
/* Turn off the hangcheck timer to keep it from bothering us */
|
||||
timer_delete(&gpu->hangcheck_timer);
|
||||
|
||||
/* Turn off interrupts to avoid triggering recovery again */
|
||||
gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, 0);
|
||||
|
||||
kthread_queue_work(gpu->worker, &gpu->recover_work);
|
||||
}
|
||||
|
||||
|
|
@ -1751,9 +1845,49 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu)
|
|||
}
|
||||
}
|
||||
|
||||
static void a6xx_gpu_keepalive_vote(struct msm_gpu *gpu, bool on)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
return;
|
||||
|
||||
gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, on);
|
||||
}
|
||||
|
||||
static int irq_poll_fence(struct msm_gpu *gpu)
|
||||
{
|
||||
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;
|
||||
u32 status;
|
||||
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
return 0;
|
||||
|
||||
if (gmu_poll_timeout_atomic(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, status, !status, 1, 100)) {
|
||||
u32 rbbm_unmasked = gmu_read(gmu, REG_A6XX_GMU_RBBM_INT_UNMASKED_STATUS);
|
||||
|
||||
dev_err_ratelimited(&gpu->pdev->dev,
|
||||
"irq fence poll timeout, fence_ctrl=0x%x, unmasked_status=0x%x\n",
|
||||
status, rbbm_unmasked);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_drm_private *priv = gpu->dev->dev_private;
|
||||
|
||||
/* Set keepalive vote to avoid power collapse after RBBM_INT_0_STATUS is read */
|
||||
a6xx_gpu_keepalive_vote(gpu, true);
|
||||
|
||||
if (irq_poll_fence(gpu))
|
||||
goto done;
|
||||
|
||||
u32 status = gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS);
|
||||
|
||||
gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status);
|
||||
|
|
@ -1790,6 +1924,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
|
|||
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
|
||||
a6xx_preempt_irq(gpu);
|
||||
|
||||
done:
|
||||
a6xx_gpu_keepalive_vote(gpu, false);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -2179,16 +2316,7 @@ static int a6xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
|
|||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
|
||||
mutex_lock(&a6xx_gpu->gmu.lock);
|
||||
|
||||
/* Force the GPU power on so we can read this register */
|
||||
a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
*value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER);
|
||||
|
||||
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
mutex_unlock(&a6xx_gpu->gmu.lock);
|
||||
*value = read_gmu_ao_counter(a6xx_gpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2298,18 +2426,36 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami)
|
||||
return a6xx_gpu->shadow[ring->id];
|
||||
|
||||
/*
|
||||
* This is true only on an A6XX_GEN1 with GMU, has IFPC enabled and a super old SQE firmware
|
||||
* without 'whereami' support
|
||||
*/
|
||||
WARN_ONCE((to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC),
|
||||
"Can't read CP_RB_RPTR register reliably\n");
|
||||
|
||||
return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR);
|
||||
}
|
||||
|
||||
static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
||||
{
|
||||
struct msm_cp_state cp_state = {
|
||||
struct msm_cp_state cp_state;
|
||||
bool progress;
|
||||
|
||||
/*
|
||||
* With IFPC, KMD doesn't know whether GX power domain is collapsed
|
||||
* or not. So, we can't blindly read the below registers in GX domain.
|
||||
* Lets trust the hang detection in HW and lie to the caller that
|
||||
* there was progress.
|
||||
*/
|
||||
if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
|
||||
return true;
|
||||
|
||||
cp_state = (struct msm_cp_state) {
|
||||
.ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE),
|
||||
.ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE),
|
||||
.ib1_rem = gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE),
|
||||
.ib2_rem = gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE),
|
||||
};
|
||||
bool progress;
|
||||
|
||||
/*
|
||||
* Adjust the remaining data to account for what has already been
|
||||
|
|
@ -2408,6 +2554,7 @@ static const struct adreno_gpu_funcs funcs = {
|
|||
.create_private_vm = a6xx_create_private_vm,
|
||||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a6xx_progress,
|
||||
.sysprof_setup = a6xx_gmu_sysprof_setup,
|
||||
},
|
||||
.get_timestamp = a6xx_gmu_get_timestamp,
|
||||
};
|
||||
|
|
@ -2468,6 +2615,7 @@ static const struct adreno_gpu_funcs funcs_a7xx = {
|
|||
.create_private_vm = a6xx_create_private_vm,
|
||||
.get_rptr = a6xx_get_rptr,
|
||||
.progress = a6xx_progress,
|
||||
.sysprof_setup = a6xx_gmu_sysprof_setup,
|
||||
},
|
||||
.get_timestamp = a6xx_gmu_get_timestamp,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ struct a6xx_info {
|
|||
const struct adreno_reglist *hwcg;
|
||||
const struct adreno_protect *protect;
|
||||
const struct adreno_reglist_list *pwrup_reglist;
|
||||
const struct adreno_reglist_list *ifpc_reglist;
|
||||
u32 gmu_chipid;
|
||||
u32 gmu_cgc_mode;
|
||||
u32 prim_fifo_threshold;
|
||||
|
|
@ -254,6 +255,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_preempt_init(struct msm_gpu *gpu);
|
||||
void a6xx_preempt_hw_init(struct msm_gpu *gpu);
|
||||
|
|
@ -295,5 +297,6 @@ int a6xx_gpu_state_put(struct msm_gpu_state *state);
|
|||
|
||||
void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off);
|
||||
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);
|
||||
|
||||
#endif /* __A6XX_GPU_H__ */
|
||||
|
|
|
|||
|
|
@ -1586,8 +1586,7 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
|
|||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
struct a6xx_gpu_state *a6xx_state = kzalloc(sizeof(*a6xx_state),
|
||||
GFP_KERNEL);
|
||||
bool stalled = !!(gpu_read(gpu, REG_A6XX_RBBM_STATUS3) &
|
||||
A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT);
|
||||
bool stalled;
|
||||
|
||||
if (!a6xx_state)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
|
@ -1608,15 +1607,20 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
|
|||
}
|
||||
|
||||
/* If GX isn't on the rest of the data isn't going to be accessible */
|
||||
if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
|
||||
if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
|
||||
return &a6xx_state->base;
|
||||
|
||||
/* Halt SQE first */
|
||||
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
|
||||
|
||||
/* Get the banks of indexed registers */
|
||||
if (adreno_is_a7xx(adreno_gpu))
|
||||
a7xx_get_indexed_registers(gpu, a6xx_state);
|
||||
else
|
||||
a6xx_get_indexed_registers(gpu, a6xx_state);
|
||||
|
||||
stalled = !!(gpu_read(gpu, REG_A6XX_RBBM_STATUS3) &
|
||||
A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT);
|
||||
/*
|
||||
* Try to initialize the crashdumper, if we are not dumping state
|
||||
* with the SMMU stalled. The crashdumper needs memory access to
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ static const char * const a6xx_hfi_msg_id[] = {
|
|||
HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
|
||||
HFI_MSG_ID(HFI_H2F_MSG_TEST),
|
||||
HFI_MSG_ID(HFI_H2F_MSG_START),
|
||||
HFI_MSG_ID(HFI_H2F_FEATURE_CTRL),
|
||||
HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
|
||||
HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
|
||||
HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
|
||||
|
|
@ -765,23 +766,40 @@ send:
|
|||
NULL, 0);
|
||||
}
|
||||
|
||||
static int a6xx_hfi_feature_ctrl_msg(struct a6xx_gmu *gmu, u32 feature, u32 enable, u32 data)
|
||||
{
|
||||
struct a6xx_hfi_msg_feature_ctrl msg = {
|
||||
.feature = feature,
|
||||
.enable = enable,
|
||||
.data = data,
|
||||
};
|
||||
|
||||
return a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
|
||||
}
|
||||
|
||||
#define HFI_FEATURE_IFPC 9
|
||||
#define IFPC_LONG_HYST 0x1680
|
||||
|
||||
static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu)
|
||||
{
|
||||
if (gmu->idle_level != GMU_IDLE_STATE_IFPC)
|
||||
return 0;
|
||||
|
||||
return a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_IFPC, 1, IFPC_LONG_HYST);
|
||||
}
|
||||
|
||||
#define HFI_FEATURE_ACD 12
|
||||
|
||||
static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu)
|
||||
{
|
||||
struct a6xx_hfi_acd_table *acd_table = &gmu->acd_table;
|
||||
struct a6xx_hfi_msg_feature_ctrl msg = {
|
||||
.feature = HFI_FEATURE_ACD,
|
||||
.enable = 1,
|
||||
.data = 0,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!acd_table->enable_by_level)
|
||||
return 0;
|
||||
|
||||
/* Enable ACD feature at GMU */
|
||||
ret = a6xx_hfi_send_msg(gmu, HFI_H2F_FEATURE_CTRL, &msg, sizeof(msg), NULL, 0);
|
||||
ret = a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_ACD, 1, 0);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(gmu->dev, "Unable to enable ACD (%d)\n", ret);
|
||||
return ret;
|
||||
|
|
@ -898,6 +916,10 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = a6xx_hfi_enable_ifpc(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = a6xx_hfi_send_core_fw_start(gmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ static inline void set_preempt_state(struct a6xx_gpu *gpu,
|
|||
}
|
||||
|
||||
/* Write the most recent wptr for the given ring into the hardware */
|
||||
static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
||||
static inline void update_wptr(struct a6xx_gpu *a6xx_gpu, struct msm_ringbuffer *ring)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint32_t wptr;
|
||||
|
|
@ -51,7 +51,7 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
if (ring->restore_wptr) {
|
||||
wptr = get_wptr(ring);
|
||||
|
||||
gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
|
||||
a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_RB_WPTR, wptr, BIT(0), false);
|
||||
|
||||
ring->restore_wptr = false;
|
||||
}
|
||||
|
|
@ -111,9 +111,9 @@ static void preempt_prepare_postamble(struct a6xx_gpu *a6xx_gpu)
|
|||
|
||||
postamble[count++] = PKT7(CP_WAIT_REG_MEM, 6);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_1_POLL_ADDR_LO(
|
||||
postamble[count++] = CP_WAIT_REG_MEM_POLL_ADDR_LO(
|
||||
REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_2_POLL_ADDR_HI(0);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_POLL_ADDR_HI(0);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_3_REF(0x1);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_4_MASK(0x1);
|
||||
postamble[count++] = CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0);
|
||||
|
|
@ -136,6 +136,21 @@ static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu)
|
|||
a6xx_gpu->postamble_enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set preemption keepalive vote. Please note that this vote is different from the one used in
|
||||
* a6xx_irq()
|
||||
*/
|
||||
static void a6xx_preempt_keepalive_vote(struct msm_gpu *gpu, bool on)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
|
||||
|
||||
if (adreno_has_gmu_wrapper(adreno_gpu))
|
||||
return;
|
||||
|
||||
gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_PWR_COL_PREEMPT_KEEPALIVE, on);
|
||||
}
|
||||
|
||||
void a6xx_preempt_irq(struct msm_gpu *gpu)
|
||||
{
|
||||
uint32_t status;
|
||||
|
|
@ -172,10 +187,12 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
|
|||
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
|
||||
|
||||
update_wptr(gpu, a6xx_gpu->cur_ring);
|
||||
update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
|
||||
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
|
||||
|
||||
a6xx_preempt_keepalive_vote(gpu, false);
|
||||
|
||||
trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id);
|
||||
|
||||
/*
|
||||
|
|
@ -268,7 +285,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
|
|||
*/
|
||||
if (!ring || (a6xx_gpu->cur_ring == ring)) {
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
|
||||
update_wptr(gpu, a6xx_gpu->cur_ring);
|
||||
update_wptr(a6xx_gpu, a6xx_gpu->cur_ring);
|
||||
set_preempt_state(a6xx_gpu, PREEMPT_NONE);
|
||||
spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
|
||||
return;
|
||||
|
|
@ -302,13 +319,16 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
|
|||
|
||||
spin_unlock_irqrestore(&ring->preempt_lock, flags);
|
||||
|
||||
gpu_write64(gpu,
|
||||
REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO,
|
||||
a6xx_gpu->preempt_smmu_iova[ring->id]);
|
||||
/* Set the keepalive bit to keep the GPU ON until preemption is complete */
|
||||
a6xx_preempt_keepalive_vote(gpu, true);
|
||||
|
||||
gpu_write64(gpu,
|
||||
a6xx_fenced_write(a6xx_gpu,
|
||||
REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, a6xx_gpu->preempt_smmu_iova[ring->id],
|
||||
BIT(1), true);
|
||||
|
||||
a6xx_fenced_write(a6xx_gpu,
|
||||
REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR,
|
||||
a6xx_gpu->preempt_iova[ring->id]);
|
||||
a6xx_gpu->preempt_iova[ring->id], BIT(1), true);
|
||||
|
||||
a6xx_gpu->next_ring = ring;
|
||||
|
||||
|
|
@ -328,7 +348,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
|
|||
set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
|
||||
|
||||
/* Trigger the preemption */
|
||||
gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl);
|
||||
a6xx_fenced_write(a6xx_gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl, BIT(1), false);
|
||||
}
|
||||
|
||||
static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ bool disable_acd;
|
|||
MODULE_PARM_DESC(disable_acd, "Forcefully disable GPU ACD");
|
||||
module_param_unsafe(disable_acd, bool, 0400);
|
||||
|
||||
static bool skip_gpu;
|
||||
MODULE_PARM_DESC(no_gpu, "Disable GPU driver register (0=enable GPU driver register (default), 1=skip GPU driver register");
|
||||
module_param(skip_gpu, bool, 0400);
|
||||
|
||||
extern const struct adreno_gpulist a2xx_gpulist;
|
||||
extern const struct adreno_gpulist a3xx_gpulist;
|
||||
extern const struct adreno_gpulist a4xx_gpulist;
|
||||
|
|
@ -184,6 +188,9 @@ bool adreno_has_gpu(struct device_node *node)
|
|||
uint32_t chip_id;
|
||||
int ret;
|
||||
|
||||
if (skip_gpu)
|
||||
return false;
|
||||
|
||||
ret = find_chipid(node, &chip_id);
|
||||
if (ret)
|
||||
return false;
|
||||
|
|
@ -404,10 +411,16 @@ static struct platform_driver adreno_driver = {
|
|||
|
||||
void __init adreno_register(void)
|
||||
{
|
||||
if (skip_gpu)
|
||||
return;
|
||||
|
||||
platform_driver_register(&adreno_driver);
|
||||
}
|
||||
|
||||
void __exit adreno_unregister(void)
|
||||
{
|
||||
if (skip_gpu)
|
||||
return;
|
||||
|
||||
platform_driver_unregister(&adreno_driver);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <linux/interconnect.h>
|
||||
#include <linux/firmware/qcom/qcom_scm.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/mdt_loader.h>
|
||||
|
|
@ -33,7 +33,7 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname,
|
|||
struct device *dev = &gpu->pdev->dev;
|
||||
const struct firmware *fw;
|
||||
const char *signed_fwname = NULL;
|
||||
struct device_node *np, *mem_np;
|
||||
struct device_node *np;
|
||||
struct resource r;
|
||||
phys_addr_t mem_phys;
|
||||
ssize_t mem_size;
|
||||
|
|
@ -51,18 +51,11 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
mem_np = of_parse_phandle(np, "memory-region", 0);
|
||||
of_node_put(np);
|
||||
if (!mem_np) {
|
||||
ret = of_reserved_mem_region_to_resource(np, 0, &r);
|
||||
if (ret) {
|
||||
zap_available = false;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(mem_np, 0, &r);
|
||||
of_node_put(mem_np);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
}
|
||||
mem_phys = r.start;
|
||||
|
||||
/*
|
||||
|
|
@ -209,9 +202,7 @@ adreno_iommu_create_vm(struct msm_gpu *gpu,
|
|||
u64 start, size;
|
||||
|
||||
mmu = msm_iommu_gpu_new(&pdev->dev, gpu, quirks);
|
||||
if (!mmu)
|
||||
return ERR_PTR(-ENODEV);
|
||||
else if (IS_ERR_OR_NULL(mmu))
|
||||
if (IS_ERR(mmu))
|
||||
return ERR_CAST(mmu);
|
||||
|
||||
geometry = msm_iommu_get_geometry(mmu);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ enum adreno_family {
|
|||
#define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4)
|
||||
#define ADRENO_QUIRK_PREEMPTION BIT(5)
|
||||
#define ADRENO_QUIRK_4GB_VA BIT(6)
|
||||
#define ADRENO_QUIRK_IFPC BIT(7)
|
||||
|
||||
/* Helper for formating the chip_id in the way that userspace tools like
|
||||
* crashdec expect.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,26 @@ enum dpu_perf_mode {
|
|||
DPU_PERF_MODE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* dpu_core_perf_adjusted_mode_clk - Adjust given mode clock rate according to
|
||||
* the perf clock factor.
|
||||
* @crtc_clk_rate - Unadjusted mode clock rate
|
||||
* @perf_cfg: performance configuration
|
||||
*/
|
||||
u64 dpu_core_perf_adjusted_mode_clk(u64 mode_clk_rate,
|
||||
const struct dpu_perf_cfg *perf_cfg)
|
||||
{
|
||||
u32 clk_factor;
|
||||
|
||||
clk_factor = perf_cfg->clk_inefficiency_factor;
|
||||
if (clk_factor) {
|
||||
mode_clk_rate *= clk_factor;
|
||||
do_div(mode_clk_rate, 100);
|
||||
}
|
||||
|
||||
return mode_clk_rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* _dpu_core_perf_calc_bw() - to calculate BW per crtc
|
||||
* @perf_cfg: performance configuration
|
||||
|
|
@ -75,28 +95,21 @@ static u64 _dpu_core_perf_calc_clk(const struct dpu_perf_cfg *perf_cfg,
|
|||
struct drm_plane *plane;
|
||||
struct dpu_plane_state *pstate;
|
||||
struct drm_display_mode *mode;
|
||||
u64 crtc_clk;
|
||||
u32 clk_factor;
|
||||
u64 mode_clk;
|
||||
|
||||
mode = &state->adjusted_mode;
|
||||
|
||||
crtc_clk = (u64)mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
|
||||
mode_clk = (u64)mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
|
||||
|
||||
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
||||
pstate = to_dpu_plane_state(plane->state);
|
||||
if (!pstate)
|
||||
continue;
|
||||
|
||||
crtc_clk = max(pstate->plane_clk, crtc_clk);
|
||||
mode_clk = max(pstate->plane_clk, mode_clk);
|
||||
}
|
||||
|
||||
clk_factor = perf_cfg->clk_inefficiency_factor;
|
||||
if (clk_factor) {
|
||||
crtc_clk *= clk_factor;
|
||||
do_div(crtc_clk, 100);
|
||||
}
|
||||
|
||||
return crtc_clk;
|
||||
return dpu_core_perf_adjusted_mode_clk(mode_clk, perf_cfg);
|
||||
}
|
||||
|
||||
static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ struct dpu_core_perf {
|
|||
u32 fix_core_ab_vote;
|
||||
};
|
||||
|
||||
u64 dpu_core_perf_adjusted_mode_clk(u64 clk_rate,
|
||||
const struct dpu_perf_cfg *perf_cfg);
|
||||
|
||||
int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
|
||||
|
|
|
|||
|
|
@ -377,11 +377,10 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer,
|
|||
static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
|
||||
{
|
||||
struct dpu_crtc_state *crtc_state;
|
||||
int lm_idx, lm_horiz_position;
|
||||
int lm_idx;
|
||||
|
||||
crtc_state = to_dpu_crtc_state(crtc->state);
|
||||
|
||||
lm_horiz_position = 0;
|
||||
for (lm_idx = 0; lm_idx < crtc_state->num_mixers; lm_idx++) {
|
||||
const struct drm_rect *lm_roi = &crtc_state->lm_bounds[lm_idx];
|
||||
struct dpu_hw_mixer *hw_lm = crtc_state->mixers[lm_idx].hw_lm;
|
||||
|
|
@ -392,7 +391,7 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
|
|||
|
||||
cfg.out_width = drm_rect_width(lm_roi);
|
||||
cfg.out_height = drm_rect_height(lm_roi);
|
||||
cfg.right_mixer = lm_horiz_position++;
|
||||
cfg.right_mixer = lm_idx & 0x1;
|
||||
cfg.flags = 0;
|
||||
hw_lm->ops.setup_mixer_out(hw_lm, &cfg);
|
||||
}
|
||||
|
|
@ -1534,6 +1533,7 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc,
|
|||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
|
||||
u64 adjusted_mode_clk;
|
||||
|
||||
/* if there is no 3d_mux block we cannot merge LMs so we cannot
|
||||
* split the large layer into 2 LMs, filter out such modes
|
||||
|
|
@ -1541,6 +1541,17 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc,
|
|||
if (!dpu_kms->catalog->caps->has_3d_merge &&
|
||||
mode->hdisplay > dpu_kms->catalog->caps->max_mixer_width)
|
||||
return MODE_BAD_HVALUE;
|
||||
|
||||
adjusted_mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock,
|
||||
dpu_kms->perf.perf_cfg);
|
||||
|
||||
/*
|
||||
* The given mode, adjusted for the perf clock factor, should not exceed
|
||||
* the max core clock rate
|
||||
*/
|
||||
if (dpu_kms->perf.max_core_clk_rate < adjusted_mode_clk * 1000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
/*
|
||||
* max crtc width is equal to the max mixer width * 2 and max height is 4K
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ static void _dpu_encoder_phys_wb_handle_wbdone_timeout(
|
|||
static int dpu_encoder_phys_wb_wait_for_commit_done(
|
||||
struct dpu_encoder_phys *phys_enc)
|
||||
{
|
||||
unsigned long ret;
|
||||
int ret;
|
||||
struct dpu_encoder_wait_info wait_info;
|
||||
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
|
||||
|
||||
|
|
|
|||
|
|
@ -338,7 +338,6 @@ static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK();
|
|||
*************************************************************/
|
||||
|
||||
static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.maxblendstages = 7, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
0x20, 0x50, 0x80, 0xb0, 0x230,
|
||||
|
|
@ -347,7 +346,6 @@ static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
|
|||
};
|
||||
|
||||
static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.maxblendstages = 11, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
0x20, 0x38, 0x50, 0x68, 0x80, 0x98,
|
||||
|
|
@ -356,7 +354,6 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
|
|||
};
|
||||
|
||||
static const struct dpu_lm_sub_blks sc7180_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.maxblendstages = 7, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
0x20, 0x38, 0x50, 0x68, 0x80, 0x98, 0xb0
|
||||
|
|
@ -364,7 +361,6 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = {
|
|||
};
|
||||
|
||||
static const struct dpu_lm_sub_blks sm8750_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.maxblendstages = 11, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
/* 0x40 + n*0x30 */
|
||||
|
|
@ -374,7 +370,6 @@ static const struct dpu_lm_sub_blks sm8750_lm_sblk = {
|
|||
};
|
||||
|
||||
static const struct dpu_lm_sub_blks qcm2290_lm_sblk = {
|
||||
.maxwidth = DEFAULT_DPU_LINE_WIDTH,
|
||||
.maxblendstages = 4, /* excluding base layer */
|
||||
.blendstage_base = { /* offsets relative to mixer base */
|
||||
0x20, 0x38, 0x50, 0x68
|
||||
|
|
|
|||
|
|
@ -307,7 +307,6 @@ struct dpu_sspp_sub_blks {
|
|||
* @blendstage_base: Blend-stage register base offset
|
||||
*/
|
||||
struct dpu_lm_sub_blks {
|
||||
u32 maxwidth;
|
||||
u32 maxblendstages;
|
||||
u32 blendstage_base[MAX_BLOCKS];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1110,7 +1110,7 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
|
|||
{
|
||||
struct drm_gpuvm *vm;
|
||||
|
||||
vm = msm_kms_init_vm(dpu_kms->dev);
|
||||
vm = msm_kms_init_vm(dpu_kms->dev, dpu_kms->dev->dev->parent);
|
||||
if (IS_ERR(vm))
|
||||
return PTR_ERR(vm);
|
||||
|
||||
|
|
|
|||
|
|
@ -922,6 +922,9 @@ static int dpu_plane_is_multirect_capable(struct dpu_hw_sspp *sspp,
|
|||
if (MSM_FORMAT_IS_YUV(fmt))
|
||||
return false;
|
||||
|
||||
if (!sspp)
|
||||
return true;
|
||||
|
||||
if (!test_bit(DPU_SSPP_SMART_DMA_V1, &sspp->cap->features) &&
|
||||
!test_bit(DPU_SSPP_SMART_DMA_V2, &sspp->cap->features))
|
||||
return false;
|
||||
|
|
@ -1028,6 +1031,7 @@ static int dpu_plane_try_multirect_shared(struct dpu_plane_state *pstate,
|
|||
prev_pipe->multirect_mode != DPU_SSPP_MULTIRECT_NONE)
|
||||
return false;
|
||||
|
||||
/* Do not validate SSPP of current plane when it is not ready */
|
||||
if (!dpu_plane_is_multirect_capable(pipe->sspp, pipe_cfg, fmt) ||
|
||||
!dpu_plane_is_multirect_capable(prev_pipe->sspp, prev_pipe_cfg, prev_fmt))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -865,6 +865,21 @@ void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
|
|||
ARRAY_SIZE(global_state->sspp_to_crtc_id), crtc_id);
|
||||
}
|
||||
|
||||
static char *dpu_hw_blk_type_name[] = {
|
||||
[DPU_HW_BLK_TOP] = "TOP",
|
||||
[DPU_HW_BLK_SSPP] = "SSPP",
|
||||
[DPU_HW_BLK_LM] = "LM",
|
||||
[DPU_HW_BLK_CTL] = "CTL",
|
||||
[DPU_HW_BLK_PINGPONG] = "pingpong",
|
||||
[DPU_HW_BLK_INTF] = "INTF",
|
||||
[DPU_HW_BLK_WB] = "WB",
|
||||
[DPU_HW_BLK_DSPP] = "DSPP",
|
||||
[DPU_HW_BLK_MERGE_3D] = "merge_3d",
|
||||
[DPU_HW_BLK_DSC] = "DSC",
|
||||
[DPU_HW_BLK_CDM] = "CDM",
|
||||
[DPU_HW_BLK_MAX] = "unknown",
|
||||
};
|
||||
|
||||
/**
|
||||
* dpu_rm_get_assigned_resources - Get hw resources of the given type that are
|
||||
* assigned to this encoder
|
||||
|
|
@ -946,13 +961,13 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
|
|||
}
|
||||
|
||||
if (num_blks == blks_size) {
|
||||
DPU_ERROR("More than %d resources assigned to crtc %d\n",
|
||||
blks_size, crtc_id);
|
||||
DPU_ERROR("More than %d %s assigned to crtc %d\n",
|
||||
blks_size, dpu_hw_blk_type_name[type], crtc_id);
|
||||
break;
|
||||
}
|
||||
if (!hw_blks[i]) {
|
||||
DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
|
||||
type, crtc_id);
|
||||
DPU_ERROR("%s unavailable to assign to crtc %d\n",
|
||||
dpu_hw_blk_type_name[type], crtc_id);
|
||||
break;
|
||||
}
|
||||
blks[num_blks++] = hw_blks[i];
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ static int dpu_wb_conn_atomic_check(struct drm_connector *connector,
|
|||
static const struct drm_connector_funcs dpu_wb_conn_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
|
@ -131,12 +130,9 @@ int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc,
|
|||
|
||||
drm_connector_helper_add(&dpu_wb_conn->base.base, &dpu_wb_conn_helper_funcs);
|
||||
|
||||
/* DPU initializes the encoder and sets it up completely for writeback
|
||||
* cases and hence should use the new API drm_writeback_connector_init_with_encoder
|
||||
* to initialize the writeback connector
|
||||
*/
|
||||
rc = drm_writeback_connector_init_with_encoder(dev, &dpu_wb_conn->base, enc,
|
||||
&dpu_wb_conn_funcs, format_list, num_formats);
|
||||
rc = drmm_writeback_connector_init(dev, &dpu_wb_conn->base,
|
||||
&dpu_wb_conn_funcs, enc,
|
||||
format_list, num_formats);
|
||||
|
||||
if (!rc)
|
||||
dpu_wb_conn->wb_enc = enc;
|
||||
|
|
|
|||
|
|
@ -391,11 +391,9 @@ static void read_mdp_hw_revision(struct mdp4_kms *mdp4_kms,
|
|||
|
||||
static int mdp4_kms_init(struct drm_device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev->dev);
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(priv->kms));
|
||||
struct msm_kms *kms = NULL;
|
||||
struct msm_mmu *mmu;
|
||||
struct drm_gpuvm *vm;
|
||||
int ret;
|
||||
u32 major, minor;
|
||||
|
|
@ -458,29 +456,14 @@ static int mdp4_kms_init(struct drm_device *dev)
|
|||
mdp4_disable(mdp4_kms);
|
||||
mdelay(16);
|
||||
|
||||
mmu = msm_iommu_new(&pdev->dev, 0);
|
||||
if (IS_ERR(mmu)) {
|
||||
ret = PTR_ERR(mmu);
|
||||
vm = msm_kms_init_vm(mdp4_kms->dev, NULL);
|
||||
if (IS_ERR(vm)) {
|
||||
ret = PTR_ERR(vm);
|
||||
goto fail;
|
||||
} else if (!mmu) {
|
||||
DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys "
|
||||
"contig buffers for scanout\n");
|
||||
vm = NULL;
|
||||
} else {
|
||||
vm = msm_gem_vm_create(dev, mmu, "mdp4",
|
||||
0x1000, 0x100000000 - 0x1000,
|
||||
true);
|
||||
|
||||
if (IS_ERR(vm)) {
|
||||
if (!IS_ERR(mmu))
|
||||
mmu->funcs->destroy(mmu);
|
||||
ret = PTR_ERR(vm);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
kms->vm = vm;
|
||||
}
|
||||
|
||||
kms->vm = vm;
|
||||
|
||||
ret = modeset_init(mdp4_kms);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev->dev, "modeset_init failed: %d\n", ret);
|
||||
|
|
@ -529,7 +512,7 @@ static int mdp4_probe(struct platform_device *pdev)
|
|||
|
||||
mdp4_kms = devm_kzalloc(dev, sizeof(*mdp4_kms), GFP_KERNEL);
|
||||
if (!mdp4_kms)
|
||||
return dev_err_probe(dev, -ENOMEM, "failed to allocate kms\n");
|
||||
return -ENOMEM;
|
||||
|
||||
mdp4_kms->mmio = msm_ioremap(pdev, NULL);
|
||||
if (IS_ERR(mdp4_kms->mmio))
|
||||
|
|
|
|||
|
|
@ -202,6 +202,6 @@ static inline struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct clk *mpd4_get_lcdc_clock(struct drm_device *dev);
|
||||
struct clk *mdp4_get_lcdc_clock(struct drm_device *dev);
|
||||
|
||||
#endif /* __MDP4_KMS_H__ */
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev)
|
|||
|
||||
drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs);
|
||||
|
||||
mdp4_lcdc_encoder->lcdc_clk = mpd4_get_lcdc_clock(dev);
|
||||
mdp4_lcdc_encoder->lcdc_clk = mdp4_get_lcdc_clock(dev);
|
||||
if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) {
|
||||
DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n");
|
||||
return ERR_CAST(mdp4_lcdc_encoder->lcdc_clk);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ static const struct pll_rate *find_rate(unsigned long rate)
|
|||
return &freqtbl[i-1];
|
||||
}
|
||||
|
||||
static int mpd4_lvds_pll_enable(struct clk_hw *hw)
|
||||
static int mdp4_lvds_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
|
||||
struct mdp4_kms *mdp4_kms = get_kms(lvds_pll);
|
||||
|
|
@ -80,7 +80,7 @@ static int mpd4_lvds_pll_enable(struct clk_hw *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void mpd4_lvds_pll_disable(struct clk_hw *hw)
|
||||
static void mdp4_lvds_pll_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
|
||||
struct mdp4_kms *mdp4_kms = get_kms(lvds_pll);
|
||||
|
|
@ -91,21 +91,24 @@ static void mpd4_lvds_pll_disable(struct clk_hw *hw)
|
|||
mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_PLL_CTRL_0, 0x0);
|
||||
}
|
||||
|
||||
static unsigned long mpd4_lvds_pll_recalc_rate(struct clk_hw *hw,
|
||||
static unsigned long mdp4_lvds_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
|
||||
return lvds_pll->pixclk;
|
||||
}
|
||||
|
||||
static long mpd4_lvds_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
static int mdp4_lvds_pll_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
const struct pll_rate *pll_rate = find_rate(rate);
|
||||
return pll_rate->rate;
|
||||
const struct pll_rate *pll_rate = find_rate(req->rate);
|
||||
|
||||
req->rate = pll_rate->rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpd4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
static int mdp4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
|
||||
|
|
@ -114,26 +117,26 @@ static int mpd4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
}
|
||||
|
||||
|
||||
static const struct clk_ops mpd4_lvds_pll_ops = {
|
||||
.enable = mpd4_lvds_pll_enable,
|
||||
.disable = mpd4_lvds_pll_disable,
|
||||
.recalc_rate = mpd4_lvds_pll_recalc_rate,
|
||||
.round_rate = mpd4_lvds_pll_round_rate,
|
||||
.set_rate = mpd4_lvds_pll_set_rate,
|
||||
static const struct clk_ops mdp4_lvds_pll_ops = {
|
||||
.enable = mdp4_lvds_pll_enable,
|
||||
.disable = mdp4_lvds_pll_disable,
|
||||
.recalc_rate = mdp4_lvds_pll_recalc_rate,
|
||||
.determine_rate = mdp4_lvds_pll_determine_rate,
|
||||
.set_rate = mdp4_lvds_pll_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_parent_data mpd4_lvds_pll_parents[] = {
|
||||
static const struct clk_parent_data mdp4_lvds_pll_parents[] = {
|
||||
{ .fw_name = "pxo", .name = "pxo", },
|
||||
};
|
||||
|
||||
static struct clk_init_data pll_init = {
|
||||
.name = "mpd4_lvds_pll",
|
||||
.ops = &mpd4_lvds_pll_ops,
|
||||
.parent_data = mpd4_lvds_pll_parents,
|
||||
.num_parents = ARRAY_SIZE(mpd4_lvds_pll_parents),
|
||||
.name = "mdp4_lvds_pll",
|
||||
.ops = &mdp4_lvds_pll_ops,
|
||||
.parent_data = mdp4_lvds_pll_parents,
|
||||
.num_parents = ARRAY_SIZE(mdp4_lvds_pll_parents),
|
||||
};
|
||||
|
||||
static struct clk_hw *mpd4_lvds_pll_init(struct drm_device *dev)
|
||||
static struct clk_hw *mdp4_lvds_pll_init(struct drm_device *dev)
|
||||
{
|
||||
struct mdp4_lvds_pll *lvds_pll;
|
||||
int ret;
|
||||
|
|
@ -156,14 +159,14 @@ static struct clk_hw *mpd4_lvds_pll_init(struct drm_device *dev)
|
|||
return &lvds_pll->pll_hw;
|
||||
}
|
||||
|
||||
struct clk *mpd4_get_lcdc_clock(struct drm_device *dev)
|
||||
struct clk *mdp4_get_lcdc_clock(struct drm_device *dev)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
struct clk *clk;
|
||||
|
||||
|
||||
/* TODO: do we need different pll in other cases? */
|
||||
hw = mpd4_lvds_pll_init(dev);
|
||||
hw = mdp4_lvds_pll_init(dev);
|
||||
if (IS_ERR(hw)) {
|
||||
DRM_DEV_ERROR(dev->dev, "failed to register LVDS PLL\n");
|
||||
return ERR_CAST(hw);
|
||||
|
|
|
|||
|
|
@ -534,7 +534,7 @@ static int mdp5_kms_init(struct drm_device *dev)
|
|||
}
|
||||
mdelay(16);
|
||||
|
||||
vm = msm_kms_init_vm(mdp5_kms->dev);
|
||||
vm = msm_kms_init_vm(mdp5_kms->dev, pdev->dev.parent);
|
||||
if (IS_ERR(vm)) {
|
||||
ret = PTR_ERR(vm);
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ struct msm_dsi_phy {
|
|||
struct msm_dsi_dphy_timing timing;
|
||||
const struct msm_dsi_phy_cfg *cfg;
|
||||
void *tuning_cfg;
|
||||
void *pll_data;
|
||||
|
||||
enum msm_dsi_phy_usecase usecase;
|
||||
bool regulator_ldo_mode;
|
||||
|
|
|
|||
|
|
@ -444,21 +444,19 @@ static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,
|
|||
return (unsigned long)vco_rate;
|
||||
}
|
||||
|
||||
static long dsi_pll_10nm_clk_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *parent_rate)
|
||||
static int dsi_pll_10nm_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct dsi_pll_10nm *pll_10nm = to_pll_10nm(hw);
|
||||
|
||||
if (rate < pll_10nm->phy->cfg->min_pll_rate)
|
||||
return pll_10nm->phy->cfg->min_pll_rate;
|
||||
else if (rate > pll_10nm->phy->cfg->max_pll_rate)
|
||||
return pll_10nm->phy->cfg->max_pll_rate;
|
||||
else
|
||||
return rate;
|
||||
req->rate = clamp_t(unsigned long, req->rate,
|
||||
pll_10nm->phy->cfg->min_pll_rate, pll_10nm->phy->cfg->max_pll_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ops_dsi_pll_10nm_vco = {
|
||||
.round_rate = dsi_pll_10nm_clk_round_rate,
|
||||
.determine_rate = dsi_pll_10nm_clk_determine_rate,
|
||||
.set_rate = dsi_pll_10nm_vco_set_rate,
|
||||
.recalc_rate = dsi_pll_10nm_vco_recalc_rate,
|
||||
.prepare = dsi_pll_10nm_vco_prepare,
|
||||
|
|
|
|||
|
|
@ -578,21 +578,19 @@ static void dsi_pll_14nm_vco_unprepare(struct clk_hw *hw)
|
|||
pll_14nm->phy->pll_on = false;
|
||||
}
|
||||
|
||||
static long dsi_pll_14nm_clk_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *parent_rate)
|
||||
static int dsi_pll_14nm_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct dsi_pll_14nm *pll_14nm = to_pll_14nm(hw);
|
||||
|
||||
if (rate < pll_14nm->phy->cfg->min_pll_rate)
|
||||
return pll_14nm->phy->cfg->min_pll_rate;
|
||||
else if (rate > pll_14nm->phy->cfg->max_pll_rate)
|
||||
return pll_14nm->phy->cfg->max_pll_rate;
|
||||
else
|
||||
return rate;
|
||||
req->rate = clamp_t(unsigned long, req->rate,
|
||||
pll_14nm->phy->cfg->min_pll_rate, pll_14nm->phy->cfg->max_pll_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ops_dsi_pll_14nm_vco = {
|
||||
.round_rate = dsi_pll_14nm_clk_round_rate,
|
||||
.determine_rate = dsi_pll_14nm_clk_determine_rate,
|
||||
.set_rate = dsi_pll_14nm_vco_set_rate,
|
||||
.recalc_rate = dsi_pll_14nm_vco_recalc_rate,
|
||||
.prepare = dsi_pll_14nm_vco_prepare,
|
||||
|
|
@ -622,18 +620,20 @@ static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw *hw,
|
|||
postdiv->flags, width);
|
||||
}
|
||||
|
||||
static long dsi_pll_14nm_postdiv_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *prate)
|
||||
static int dsi_pll_14nm_postdiv_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);
|
||||
struct dsi_pll_14nm *pll_14nm = postdiv->pll;
|
||||
|
||||
DBG("DSI%d PLL parent rate=%lu", pll_14nm->phy->id, rate);
|
||||
DBG("DSI%d PLL parent rate=%lu", pll_14nm->phy->id, req->rate);
|
||||
|
||||
return divider_round_rate(hw, rate, prate, NULL,
|
||||
postdiv->width,
|
||||
postdiv->flags);
|
||||
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
|
||||
NULL,
|
||||
postdiv->width,
|
||||
postdiv->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
|
@ -680,7 +680,7 @@ static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
|
||||
static const struct clk_ops clk_ops_dsi_pll_14nm_postdiv = {
|
||||
.recalc_rate = dsi_pll_14nm_postdiv_recalc_rate,
|
||||
.round_rate = dsi_pll_14nm_postdiv_round_rate,
|
||||
.determine_rate = dsi_pll_14nm_postdiv_determine_rate,
|
||||
.set_rate = dsi_pll_14nm_postdiv_set_rate,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -533,21 +533,20 @@ static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw)
|
|||
pll_28nm->phy->pll_on = false;
|
||||
}
|
||||
|
||||
static long dsi_pll_28nm_clk_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *parent_rate)
|
||||
static int dsi_pll_28nm_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
|
||||
|
||||
if (rate < pll_28nm->phy->cfg->min_pll_rate)
|
||||
return pll_28nm->phy->cfg->min_pll_rate;
|
||||
else if (rate > pll_28nm->phy->cfg->max_pll_rate)
|
||||
return pll_28nm->phy->cfg->max_pll_rate;
|
||||
else
|
||||
return rate;
|
||||
req->rate = clamp_t(unsigned long, req->rate,
|
||||
pll_28nm->phy->cfg->min_pll_rate,
|
||||
pll_28nm->phy->cfg->max_pll_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ops_dsi_pll_28nm_vco_hpm = {
|
||||
.round_rate = dsi_pll_28nm_clk_round_rate,
|
||||
.determine_rate = dsi_pll_28nm_clk_determine_rate,
|
||||
.set_rate = dsi_pll_28nm_clk_set_rate,
|
||||
.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
|
||||
.prepare = dsi_pll_28nm_vco_prepare_hpm,
|
||||
|
|
@ -556,7 +555,7 @@ static const struct clk_ops clk_ops_dsi_pll_28nm_vco_hpm = {
|
|||
};
|
||||
|
||||
static const struct clk_ops clk_ops_dsi_pll_28nm_vco_lp = {
|
||||
.round_rate = dsi_pll_28nm_clk_round_rate,
|
||||
.determine_rate = dsi_pll_28nm_clk_determine_rate,
|
||||
.set_rate = dsi_pll_28nm_clk_set_rate,
|
||||
.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
|
||||
.prepare = dsi_pll_28nm_vco_prepare_lp,
|
||||
|
|
@ -565,7 +564,7 @@ static const struct clk_ops clk_ops_dsi_pll_28nm_vco_lp = {
|
|||
};
|
||||
|
||||
static const struct clk_ops clk_ops_dsi_pll_28nm_vco_8226 = {
|
||||
.round_rate = dsi_pll_28nm_clk_round_rate,
|
||||
.determine_rate = dsi_pll_28nm_clk_determine_rate,
|
||||
.set_rate = dsi_pll_28nm_clk_set_rate,
|
||||
.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
|
||||
.prepare = dsi_pll_28nm_vco_prepare_8226,
|
||||
|
|
|
|||
|
|
@ -231,21 +231,19 @@ static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw)
|
|||
pll_28nm->phy->pll_on = false;
|
||||
}
|
||||
|
||||
static long dsi_pll_28nm_clk_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *parent_rate)
|
||||
static int dsi_pll_28nm_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
|
||||
|
||||
if (rate < pll_28nm->phy->cfg->min_pll_rate)
|
||||
return pll_28nm->phy->cfg->min_pll_rate;
|
||||
else if (rate > pll_28nm->phy->cfg->max_pll_rate)
|
||||
return pll_28nm->phy->cfg->max_pll_rate;
|
||||
else
|
||||
return rate;
|
||||
req->rate = clamp_t(unsigned long, req->rate,
|
||||
pll_28nm->phy->cfg->min_pll_rate, pll_28nm->phy->cfg->max_pll_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
|
||||
.round_rate = dsi_pll_28nm_clk_round_rate,
|
||||
.determine_rate = dsi_pll_28nm_clk_determine_rate,
|
||||
.set_rate = dsi_pll_28nm_clk_set_rate,
|
||||
.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
|
||||
.prepare = dsi_pll_28nm_vco_prepare,
|
||||
|
|
@ -296,18 +294,20 @@ static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate)
|
|||
return 8;
|
||||
}
|
||||
|
||||
static long clk_bytediv_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
static int clk_bytediv_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long best_parent;
|
||||
unsigned int factor;
|
||||
|
||||
factor = get_vco_mul_factor(rate);
|
||||
factor = get_vco_mul_factor(req->rate);
|
||||
|
||||
best_parent = rate * factor;
|
||||
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
|
||||
best_parent = req->rate * factor;
|
||||
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
|
||||
|
||||
return *prate / factor;
|
||||
req->rate = req->best_parent_rate / factor;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
|
@ -328,7 +328,7 @@ static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
|
||||
/* Our special byte clock divider ops */
|
||||
static const struct clk_ops clk_bytediv_ops = {
|
||||
.round_rate = clk_bytediv_round_rate,
|
||||
.determine_rate = clk_bytediv_determine_rate,
|
||||
.set_rate = clk_bytediv_set_rate,
|
||||
.recalc_rate = clk_bytediv_recalc_rate,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,6 +90,13 @@ struct dsi_pll_7nm {
|
|||
/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG1 register */
|
||||
spinlock_t pclk_mux_lock;
|
||||
|
||||
/*
|
||||
* protects REG_DSI_7nm_PHY_CMN_CTRL_0 register and pll_enable_cnt
|
||||
* member
|
||||
*/
|
||||
spinlock_t pll_enable_lock;
|
||||
int pll_enable_cnt;
|
||||
|
||||
struct pll_7nm_cached_state cached_state;
|
||||
|
||||
struct dsi_pll_7nm *slave;
|
||||
|
|
@ -103,6 +110,9 @@ struct dsi_pll_7nm {
|
|||
*/
|
||||
static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];
|
||||
|
||||
static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll);
|
||||
static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll);
|
||||
|
||||
static void dsi_pll_setup_config(struct dsi_pll_config *config)
|
||||
{
|
||||
config->ssc_freq = 31500;
|
||||
|
|
@ -340,6 +350,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw);
|
||||
struct dsi_pll_config config;
|
||||
|
||||
dsi_pll_enable_pll_bias(pll_7nm);
|
||||
DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->phy->id, rate,
|
||||
parent_rate);
|
||||
|
||||
|
|
@ -357,6 +368,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
|
||||
dsi_pll_ssc_commit(pll_7nm, &config);
|
||||
|
||||
dsi_pll_disable_pll_bias(pll_7nm);
|
||||
/* flush, ensure all register writes are done*/
|
||||
wmb();
|
||||
|
||||
|
|
@ -385,19 +397,47 @@ static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)
|
|||
|
||||
static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll)
|
||||
{
|
||||
u32 data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
spin_lock_irqsave(&pll->pll_enable_lock, flags);
|
||||
--pll->pll_enable_cnt;
|
||||
if (pll->pll_enable_cnt < 0) {
|
||||
spin_unlock_irqrestore(&pll->pll_enable_lock, flags);
|
||||
DRM_DEV_ERROR_RATELIMITED(&pll->phy->pdev->dev,
|
||||
"bug: imbalance in disabling PLL bias\n");
|
||||
return;
|
||||
} else if (pll->pll_enable_cnt > 0) {
|
||||
spin_unlock_irqrestore(&pll->pll_enable_lock, flags);
|
||||
return;
|
||||
} /* else: == 0 */
|
||||
|
||||
data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
data &= ~DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB;
|
||||
writel(0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES);
|
||||
writel(data & ~BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
spin_unlock_irqrestore(&pll->pll_enable_lock, flags);
|
||||
ndelay(250);
|
||||
}
|
||||
|
||||
static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
|
||||
{
|
||||
u32 data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
spin_lock_irqsave(&pll->pll_enable_lock, flags);
|
||||
if (pll->pll_enable_cnt++) {
|
||||
spin_unlock_irqrestore(&pll->pll_enable_lock, flags);
|
||||
WARN_ON(pll->pll_enable_cnt == INT_MAX);
|
||||
return;
|
||||
}
|
||||
|
||||
data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
data |= DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB;
|
||||
writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
|
||||
writel(data | BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
writel(0xc0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES);
|
||||
spin_unlock_irqrestore(&pll->pll_enable_lock, flags);
|
||||
ndelay(250);
|
||||
}
|
||||
|
||||
|
|
@ -491,6 +531,10 @@ static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw)
|
|||
if (pll_7nm->slave)
|
||||
dsi_pll_enable_global_clk(pll_7nm->slave);
|
||||
|
||||
writel(0x1, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL);
|
||||
if (pll_7nm->slave)
|
||||
writel(0x1, pll_7nm->slave->phy->base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL);
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -534,6 +578,7 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
|
|||
u32 dec;
|
||||
u64 pll_freq, tmp64;
|
||||
|
||||
dsi_pll_enable_pll_bias(pll_7nm);
|
||||
dec = readl(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);
|
||||
dec &= 0xff;
|
||||
|
||||
|
|
@ -558,24 +603,24 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
|
|||
DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
|
||||
pll_7nm->phy->id, (unsigned long)vco_rate, dec, frac);
|
||||
|
||||
dsi_pll_disable_pll_bias(pll_7nm);
|
||||
|
||||
return (unsigned long)vco_rate;
|
||||
}
|
||||
|
||||
static long dsi_pll_7nm_clk_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *parent_rate)
|
||||
static int dsi_pll_7nm_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw);
|
||||
|
||||
if (rate < pll_7nm->phy->cfg->min_pll_rate)
|
||||
return pll_7nm->phy->cfg->min_pll_rate;
|
||||
else if (rate > pll_7nm->phy->cfg->max_pll_rate)
|
||||
return pll_7nm->phy->cfg->max_pll_rate;
|
||||
else
|
||||
return rate;
|
||||
req->rate = clamp_t(unsigned long, req->rate,
|
||||
pll_7nm->phy->cfg->min_pll_rate, pll_7nm->phy->cfg->max_pll_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ops_dsi_pll_7nm_vco = {
|
||||
.round_rate = dsi_pll_7nm_clk_round_rate,
|
||||
.determine_rate = dsi_pll_7nm_clk_determine_rate,
|
||||
.set_rate = dsi_pll_7nm_vco_set_rate,
|
||||
.recalc_rate = dsi_pll_7nm_vco_recalc_rate,
|
||||
.prepare = dsi_pll_7nm_vco_prepare,
|
||||
|
|
@ -593,6 +638,7 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
|
|||
void __iomem *phy_base = pll_7nm->phy->base;
|
||||
u32 cmn_clk_cfg0, cmn_clk_cfg1;
|
||||
|
||||
dsi_pll_enable_pll_bias(pll_7nm);
|
||||
cached->pll_out_div = readl(pll_7nm->phy->pll_base +
|
||||
REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
|
||||
cached->pll_out_div &= 0x3;
|
||||
|
|
@ -604,6 +650,7 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
|
|||
cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
cached->pll_mux = FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, cmn_clk_cfg1);
|
||||
|
||||
dsi_pll_disable_pll_bias(pll_7nm);
|
||||
DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
|
||||
pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div,
|
||||
cached->pix_clk_div, cached->pll_mux);
|
||||
|
|
@ -826,8 +873,10 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy)
|
|||
|
||||
spin_lock_init(&pll_7nm->postdiv_lock);
|
||||
spin_lock_init(&pll_7nm->pclk_mux_lock);
|
||||
spin_lock_init(&pll_7nm->pll_enable_lock);
|
||||
|
||||
pll_7nm->phy = phy;
|
||||
phy->pll_data = pll_7nm;
|
||||
|
||||
ret = pll_7nm_register(pll_7nm, phy->provided_clocks->hws);
|
||||
if (ret) {
|
||||
|
|
@ -839,6 +888,12 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy)
|
|||
|
||||
/* TODO: Remove this when we have proper display handover support */
|
||||
msm_dsi_phy_pll_save_state(phy);
|
||||
/*
|
||||
* Store also proper vco_current_rate, because its value will be used in
|
||||
* dsi_7nm_pll_restore_state().
|
||||
*/
|
||||
if (!dsi_pll_7nm_vco_recalc_rate(&pll_7nm->clk_hw, VCO_REF_CLK_RATE))
|
||||
pll_7nm->vco_current_rate = pll_7nm->phy->cfg->min_pll_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -910,8 +965,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
|
|||
u32 const delay_us = 5;
|
||||
u32 const timeout_us = 1000;
|
||||
struct msm_dsi_dphy_timing *timing = &phy->timing;
|
||||
struct dsi_pll_7nm *pll = phy->pll_data;
|
||||
void __iomem *base = phy->base;
|
||||
bool less_than_1500_mhz;
|
||||
unsigned long flags;
|
||||
u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0;
|
||||
u32 glbl_pemph_ctrl_0;
|
||||
u32 glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0;
|
||||
|
|
@ -1033,9 +1090,13 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
|
|||
glbl_rescode_bot_ctrl = 0x3c;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&pll->pll_enable_lock, flags);
|
||||
pll->pll_enable_cnt = 1;
|
||||
/* de-assert digital and pll power down */
|
||||
data = BIT(6) | BIT(5);
|
||||
data = DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B |
|
||||
DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB;
|
||||
writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
spin_unlock_irqrestore(&pll->pll_enable_lock, flags);
|
||||
|
||||
/* Assert PLL core reset */
|
||||
writel(0x00, base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL);
|
||||
|
|
@ -1148,7 +1209,9 @@ static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
|
|||
|
||||
static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
|
||||
{
|
||||
struct dsi_pll_7nm *pll = phy->pll_data;
|
||||
void __iomem *base = phy->base;
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
DBG("");
|
||||
|
|
@ -1175,8 +1238,12 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
|
|||
writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
writel(0, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0);
|
||||
|
||||
spin_lock_irqsave(&pll->pll_enable_lock, flags);
|
||||
pll->pll_enable_cnt = 0;
|
||||
/* Turn off all PHY blocks */
|
||||
writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0);
|
||||
spin_unlock_irqrestore(&pll->pll_enable_lock, flags);
|
||||
|
||||
/* make sure phy is turned off */
|
||||
wmb();
|
||||
|
||||
|
|
|
|||
|
|
@ -629,16 +629,12 @@ static int hdmi_8996_pll_prepare(struct clk_hw *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long hdmi_8996_pll_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
static int hdmi_8996_pll_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
if (rate < HDMI_PCLK_MIN_FREQ)
|
||||
return HDMI_PCLK_MIN_FREQ;
|
||||
else if (rate > HDMI_PCLK_MAX_FREQ)
|
||||
return HDMI_PCLK_MAX_FREQ;
|
||||
else
|
||||
return rate;
|
||||
req->rate = clamp_t(unsigned long, req->rate, HDMI_PCLK_MIN_FREQ, HDMI_PCLK_MAX_FREQ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw,
|
||||
|
|
@ -684,7 +680,7 @@ static int hdmi_8996_pll_is_enabled(struct clk_hw *hw)
|
|||
|
||||
static const struct clk_ops hdmi_8996_pll_ops = {
|
||||
.set_rate = hdmi_8996_pll_set_clk_rate,
|
||||
.round_rate = hdmi_8996_pll_round_rate,
|
||||
.determine_rate = hdmi_8996_pll_determine_rate,
|
||||
.recalc_rate = hdmi_8996_pll_recalc_rate,
|
||||
.prepare = hdmi_8996_pll_prepare,
|
||||
.unprepare = hdmi_8996_pll_unprepare,
|
||||
|
|
|
|||
|
|
@ -646,16 +646,12 @@ static int hdmi_8998_pll_prepare(struct clk_hw *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long hdmi_8998_pll_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
static int hdmi_8998_pll_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
if (rate < HDMI_PCLK_MIN_FREQ)
|
||||
return HDMI_PCLK_MIN_FREQ;
|
||||
else if (rate > HDMI_PCLK_MAX_FREQ)
|
||||
return HDMI_PCLK_MAX_FREQ;
|
||||
else
|
||||
return rate;
|
||||
req->rate = clamp_t(unsigned long, req->rate, HDMI_PCLK_MIN_FREQ, HDMI_PCLK_MAX_FREQ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long hdmi_8998_pll_recalc_rate(struct clk_hw *hw,
|
||||
|
|
@ -688,7 +684,7 @@ static int hdmi_8998_pll_is_enabled(struct clk_hw *hw)
|
|||
|
||||
static const struct clk_ops hdmi_8998_pll_ops = {
|
||||
.set_rate = hdmi_8998_pll_set_clk_rate,
|
||||
.round_rate = hdmi_8998_pll_round_rate,
|
||||
.determine_rate = hdmi_8998_pll_determine_rate,
|
||||
.recalc_rate = hdmi_8998_pll_recalc_rate,
|
||||
.prepare = hdmi_8998_pll_prepare,
|
||||
.unprepare = hdmi_8998_pll_unprepare,
|
||||
|
|
|
|||
|
|
@ -373,12 +373,14 @@ static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
|
|||
return pll->pixclk;
|
||||
}
|
||||
|
||||
static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
static int hdmi_pll_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
const struct pll_rate *pll_rate = find_rate(rate);
|
||||
const struct pll_rate *pll_rate = find_rate(req->rate);
|
||||
|
||||
return pll_rate->rate;
|
||||
req->rate = pll_rate->rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
|
@ -402,7 +404,7 @@ static const struct clk_ops hdmi_pll_ops = {
|
|||
.enable = hdmi_pll_enable,
|
||||
.disable = hdmi_pll_disable,
|
||||
.recalc_rate = hdmi_pll_recalc_rate,
|
||||
.round_rate = hdmi_pll_round_rate,
|
||||
.determine_rate = hdmi_pll_determine_rate,
|
||||
.set_rate = hdmi_pll_set_rate,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -826,6 +826,7 @@ static const struct file_operations fops = {
|
|||
|
||||
#define DRIVER_FEATURES_KMS ( \
|
||||
DRIVER_GEM | \
|
||||
DRIVER_GEM_GPUVA | \
|
||||
DRIVER_ATOMIC | \
|
||||
DRIVER_MODESET | \
|
||||
0 )
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ void msm_crtc_disable_vblank(struct drm_crtc *crtc);
|
|||
int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
|
||||
void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu);
|
||||
|
||||
struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev);
|
||||
struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev, struct device *mdss_dev);
|
||||
bool msm_use_mmu(struct drm_device *dev);
|
||||
|
||||
int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ static struct page **get_pages(struct drm_gem_object *obj)
|
|||
if (!msm_obj->pages) {
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct page **p;
|
||||
int npages = obj->size >> PAGE_SHIFT;
|
||||
size_t npages = obj->size >> PAGE_SHIFT;
|
||||
|
||||
p = drm_gem_get_pages(obj);
|
||||
|
||||
|
|
@ -1148,7 +1148,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
|
|||
|
||||
/* convenience method to construct a GEM buffer object, and userspace handle */
|
||||
int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
|
||||
uint32_t size, uint32_t flags, uint32_t *handle,
|
||||
size_t size, uint32_t flags, uint32_t *handle,
|
||||
char *name)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
|
|
@ -1214,9 +1214,8 @@ static const struct drm_gem_object_funcs msm_gem_object_funcs = {
|
|||
.vm_ops = &vm_ops,
|
||||
};
|
||||
|
||||
static int msm_gem_new_impl(struct drm_device *dev,
|
||||
uint32_t size, uint32_t flags,
|
||||
struct drm_gem_object **obj)
|
||||
static int msm_gem_new_impl(struct drm_device *dev, uint32_t flags,
|
||||
struct drm_gem_object **obj)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_gem_object *msm_obj;
|
||||
|
|
@ -1250,7 +1249,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags)
|
||||
struct drm_gem_object *msm_gem_new(struct drm_device *dev, size_t size, uint32_t flags)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_gem_object *msm_obj;
|
||||
|
|
@ -1265,7 +1264,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32
|
|||
if (size == 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
ret = msm_gem_new_impl(dev, size, flags, &obj);
|
||||
ret = msm_gem_new_impl(dev, flags, &obj);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
|
@ -1305,12 +1304,12 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
|
|||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_gem_object *msm_obj;
|
||||
struct drm_gem_object *obj;
|
||||
uint32_t size;
|
||||
int ret, npages;
|
||||
size_t size, npages;
|
||||
int ret;
|
||||
|
||||
size = PAGE_ALIGN(dmabuf->size);
|
||||
|
||||
ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);
|
||||
ret = msm_gem_new_impl(dev, MSM_BO_WC, &obj);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
|
@ -1353,7 +1352,7 @@ fail:
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, uint32_t flags,
|
||||
void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags,
|
||||
struct drm_gpuvm *vm, struct drm_gem_object **bo,
|
||||
uint64_t *iova)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -297,10 +297,10 @@ bool msm_gem_active(struct drm_gem_object *obj);
|
|||
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
|
||||
int msm_gem_cpu_fini(struct drm_gem_object *obj);
|
||||
int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
|
||||
uint32_t size, uint32_t flags, uint32_t *handle, char *name);
|
||||
size_t size, uint32_t flags, uint32_t *handle, char *name);
|
||||
struct drm_gem_object *msm_gem_new(struct drm_device *dev,
|
||||
uint32_t size, uint32_t flags);
|
||||
void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, uint32_t flags,
|
||||
size_t size, uint32_t flags);
|
||||
void *msm_gem_kernel_new(struct drm_device *dev, size_t size, uint32_t flags,
|
||||
struct drm_gpuvm *vm, struct drm_gem_object **bo,
|
||||
uint64_t *iova);
|
||||
void msm_gem_kernel_put(struct drm_gem_object *bo, struct drm_gpuvm *vm);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
|
||||
{
|
||||
struct msm_gem_object *msm_obj = to_msm_bo(obj);
|
||||
int npages = obj->size >> PAGE_SHIFT;
|
||||
size_t npages = obj->size >> PAGE_SHIFT;
|
||||
|
||||
if (msm_obj->flags & MSM_BO_NO_SHARE)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
|
|||
|
|
@ -1030,6 +1030,7 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
|
|||
struct drm_device *dev = job->vm->drm;
|
||||
int ret = 0;
|
||||
int cnt = 0;
|
||||
int i = -1;
|
||||
|
||||
if (args->nr_ops == 1) {
|
||||
/* Single op case, the op is inlined: */
|
||||
|
|
@ -1063,11 +1064,12 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
|
|||
|
||||
spin_lock(&file->table_lock);
|
||||
|
||||
for (unsigned i = 0; i < args->nr_ops; i++) {
|
||||
for (i = 0; i < args->nr_ops; i++) {
|
||||
struct msm_vm_bind_op *op = &job->ops[i];
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
if (!job->ops[i].handle) {
|
||||
job->ops[i].obj = NULL;
|
||||
if (!op->handle) {
|
||||
op->obj = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1075,16 +1077,22 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
|
|||
* normally use drm_gem_object_lookup(), but for bulk lookup
|
||||
* all under single table_lock just hit object_idr directly:
|
||||
*/
|
||||
obj = idr_find(&file->object_idr, job->ops[i].handle);
|
||||
obj = idr_find(&file->object_idr, op->handle);
|
||||
if (!obj) {
|
||||
ret = UERR(EINVAL, dev, "invalid handle %u at index %u\n", job->ops[i].handle, i);
|
||||
ret = UERR(EINVAL, dev, "invalid handle %u at index %u\n", op->handle, i);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
drm_gem_object_get(obj);
|
||||
|
||||
job->ops[i].obj = obj;
|
||||
op->obj = obj;
|
||||
cnt++;
|
||||
|
||||
if ((op->range + op->obj_offset) > obj->size) {
|
||||
ret = UERR(EINVAL, dev, "invalid range: %016llx + %016llx > %016zx\n",
|
||||
op->range, op->obj_offset, obj->size);
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
*nr_bos = cnt;
|
||||
|
|
@ -1092,6 +1100,17 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
|
|||
out_unlock:
|
||||
spin_unlock(&file->table_lock);
|
||||
|
||||
if (ret) {
|
||||
for (; i >= 0; i--) {
|
||||
struct msm_vm_bind_op *op = &job->ops[i];
|
||||
|
||||
if (!op->obj)
|
||||
continue;
|
||||
|
||||
drm_gem_object_put(op->obj);
|
||||
op->obj = NULL;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ static void crashstate_get_bos(struct msm_gpu_state *state, struct msm_gem_submi
|
|||
sizeof(struct msm_gpu_state_bo), GFP_KERNEL);
|
||||
|
||||
for (int i = 0; state->bos && i < submit->nr_bos; i++) {
|
||||
struct drm_gem_object *obj = submit->bos[i].obj;;
|
||||
struct drm_gem_object *obj = submit->bos[i].obj;
|
||||
bool dump = rd_full || (submit->bos[i].flags & MSM_SUBMIT_BO_DUMP);
|
||||
|
||||
msm_gem_lock(obj);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "msm_drv.h"
|
||||
#include "msm_fence.h"
|
||||
#include "msm_gpu_trace.h"
|
||||
#include "msm_ringbuffer.h"
|
||||
#include "msm_gem.h"
|
||||
|
||||
|
|
@ -91,6 +92,7 @@ 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);
|
||||
};
|
||||
|
||||
/* Additional state for iommu faults: */
|
||||
|
|
@ -613,16 +615,19 @@ struct msm_gpu_state {
|
|||
|
||||
static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data)
|
||||
{
|
||||
trace_msm_gpu_regaccess(reg);
|
||||
writel(data, gpu->mmio + (reg << 2));
|
||||
}
|
||||
|
||||
static inline u32 gpu_read(struct msm_gpu *gpu, u32 reg)
|
||||
{
|
||||
trace_msm_gpu_regaccess(reg);
|
||||
return readl(gpu->mmio + (reg << 2));
|
||||
}
|
||||
|
||||
static inline void gpu_rmw(struct msm_gpu *gpu, u32 reg, u32 mask, u32 or)
|
||||
{
|
||||
trace_msm_gpu_regaccess(reg);
|
||||
msm_rmw(gpu->mmio + (reg << 2), mask, or);
|
||||
}
|
||||
|
||||
|
|
@ -644,7 +649,9 @@ static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg)
|
|||
* when the lo is read, so make sure to read the lo first to trigger
|
||||
* that
|
||||
*/
|
||||
trace_msm_gpu_regaccess(reg);
|
||||
val = (u64) readl(gpu->mmio + (reg << 2));
|
||||
trace_msm_gpu_regaccess(reg+1);
|
||||
val |= ((u64) readl(gpu->mmio + ((reg + 1) << 2)) << 32);
|
||||
|
||||
return val;
|
||||
|
|
@ -652,8 +659,10 @@ static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg)
|
|||
|
||||
static inline void gpu_write64(struct msm_gpu *gpu, u32 reg, u64 val)
|
||||
{
|
||||
trace_msm_gpu_regaccess(reg);
|
||||
/* Why not a writeq here? Read the screed above */
|
||||
writel(lower_32_bits(val), gpu->mmio + (reg << 2));
|
||||
trace_msm_gpu_regaccess(reg+1);
|
||||
writel(upper_32_bits(val), gpu->mmio + ((reg + 1) << 2));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -219,6 +219,18 @@ TRACE_EVENT(msm_mmu_prealloc_cleanup,
|
|||
TP_printk("count=%u, remaining=%u", __entry->count, __entry->remaining)
|
||||
);
|
||||
|
||||
TRACE_EVENT(msm_gpu_regaccess,
|
||||
TP_PROTO(u32 offset),
|
||||
TP_ARGS(offset),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, offset)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->offset = offset;
|
||||
),
|
||||
TP_printk("offset=0x%x", __entry->offset)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
|
|
|||
|
|
@ -721,7 +721,7 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
|
|||
int ret;
|
||||
|
||||
if (!device_iommu_mapped(dev))
|
||||
return NULL;
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
domain = iommu_paging_domain_alloc(dev);
|
||||
if (IS_ERR(domain))
|
||||
|
|
@ -756,7 +756,7 @@ struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks)
|
|||
struct msm_mmu *mmu;
|
||||
|
||||
mmu = msm_iommu_new(dev, quirks);
|
||||
if (IS_ERR_OR_NULL(mmu))
|
||||
if (IS_ERR(mmu))
|
||||
return mmu;
|
||||
|
||||
iommu = to_msm_iommu(mmu);
|
||||
|
|
@ -772,11 +772,11 @@ struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsig
|
|||
struct msm_mmu *mmu;
|
||||
|
||||
mmu = msm_iommu_new(dev, quirks);
|
||||
if (IS_ERR_OR_NULL(mmu))
|
||||
if (IS_ERR(mmu))
|
||||
return mmu;
|
||||
|
||||
iommu = to_msm_iommu(mmu);
|
||||
if (adreno_smmu && adreno_smmu->cookie) {
|
||||
if (adreno_smmu->cookie) {
|
||||
const struct io_pgtable_cfg *cfg =
|
||||
adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie);
|
||||
size_t tblsz = get_tblsz(cfg);
|
||||
|
|
|
|||
|
|
@ -177,12 +177,11 @@ static int msm_kms_fault_handler(void *arg, unsigned long iova, int flags, void
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev)
|
||||
struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev, struct device *mdss_dev)
|
||||
{
|
||||
struct drm_gpuvm *vm;
|
||||
struct msm_mmu *mmu;
|
||||
struct device *mdp_dev = dev->dev;
|
||||
struct device *mdss_dev = mdp_dev->parent;
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_kms *kms = priv->kms;
|
||||
struct device *iommu_dev;
|
||||
|
|
@ -193,18 +192,17 @@ struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev)
|
|||
*/
|
||||
if (device_iommu_mapped(mdp_dev))
|
||||
iommu_dev = mdp_dev;
|
||||
else
|
||||
else if (mdss_dev && device_iommu_mapped(mdss_dev))
|
||||
iommu_dev = mdss_dev;
|
||||
else {
|
||||
drm_info(dev, "no IOMMU, bailing out\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
mmu = msm_iommu_disp_new(iommu_dev, 0);
|
||||
if (IS_ERR(mmu))
|
||||
return ERR_CAST(mmu);
|
||||
|
||||
if (!mmu) {
|
||||
drm_info(dev, "no IOMMU, fallback to phys contig buffers for scanout\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vm = msm_gem_vm_create(dev, mmu, "mdp_kms",
|
||||
0x1000, 0x100000000 - 0x1000, true);
|
||||
if (IS_ERR(vm)) {
|
||||
|
|
|
|||
|
|
@ -154,8 +154,7 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
|
|||
|
||||
dev = msm_mdss->dev;
|
||||
|
||||
domain = irq_domain_create_linear(of_fwnode_handle(dev->of_node), 32,
|
||||
&msm_mdss_irqdomain_ops, msm_mdss);
|
||||
domain = irq_domain_create_linear(dev_fwnode(dev), 32, &msm_mdss_irqdomain_ops, msm_mdss);
|
||||
if (!domain) {
|
||||
dev_err(dev, "failed to add irq_domain\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sy
|
|||
break;
|
||||
}
|
||||
|
||||
/* Some gpu families require additional setup for sysprof */
|
||||
if (gpu->funcs->sysprof_setup)
|
||||
gpu->funcs->sysprof_setup(gpu);
|
||||
|
||||
ctx->sysprof = sysprof;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,38 +9,6 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
|
||||
<domain name="A6XX_TEX_SAMP" width="32">
|
||||
<doc>Texture sampler dwords</doc>
|
||||
<enum name="a6xx_tex_filter"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_NEAREST" value="0"/>
|
||||
<value name="A6XX_TEX_LINEAR" value="1"/>
|
||||
<value name="A6XX_TEX_ANISO" value="2"/>
|
||||
<value name="A6XX_TEX_CUBIC" value="3"/> <!-- a650 only -->
|
||||
</enum>
|
||||
<enum name="a6xx_tex_clamp"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_REPEAT" value="0"/>
|
||||
<value name="A6XX_TEX_CLAMP_TO_EDGE" value="1"/>
|
||||
<value name="A6XX_TEX_MIRROR_REPEAT" value="2"/>
|
||||
<value name="A6XX_TEX_CLAMP_TO_BORDER" value="3"/>
|
||||
<value name="A6XX_TEX_MIRROR_CLAMP" value="4"/>
|
||||
</enum>
|
||||
<enum name="a6xx_tex_aniso"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_ANISO_1" value="0"/>
|
||||
<value name="A6XX_TEX_ANISO_2" value="1"/>
|
||||
<value name="A6XX_TEX_ANISO_4" value="2"/>
|
||||
<value name="A6XX_TEX_ANISO_8" value="3"/>
|
||||
<value name="A6XX_TEX_ANISO_16" value="4"/>
|
||||
</enum>
|
||||
<enum name="a6xx_reduction_mode">
|
||||
<value name="A6XX_REDUCTION_MODE_AVERAGE" value="0"/>
|
||||
<value name="A6XX_REDUCTION_MODE_MIN" value="1"/>
|
||||
<value name="A6XX_REDUCTION_MODE_MAX" value="2"/>
|
||||
</enum>
|
||||
<enum name="a6xx_fast_border_color">
|
||||
<!-- R B G A -->
|
||||
<value name="A6XX_BORDER_COLOR_0_0_0_0" value="0"/>
|
||||
<value name="A6XX_BORDER_COLOR_0_0_0_1" value="1"/>
|
||||
<value name="A6XX_BORDER_COLOR_1_1_1_0" value="2"/>
|
||||
<value name="A6XX_BORDER_COLOR_1_1_1_1" value="3"/>
|
||||
</enum>
|
||||
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="MIPFILTER_LINEAR_NEAR" pos="0" type="boolean"/>
|
||||
|
|
@ -79,14 +47,6 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
|
||||
<domain name="A6XX_TEX_CONST" width="32" varset="chip">
|
||||
<doc>Texture constant dwords</doc>
|
||||
<enum name="a6xx_tex_swiz"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_X" value="0"/>
|
||||
<value name="A6XX_TEX_Y" value="1"/>
|
||||
<value name="A6XX_TEX_Z" value="2"/>
|
||||
<value name="A6XX_TEX_W" value="3"/>
|
||||
<value name="A6XX_TEX_ZERO" value="4"/>
|
||||
<value name="A6XX_TEX_ONE" value="5"/>
|
||||
</enum>
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="TILE_MODE" low="0" high="1" type="a6xx_tile_mode"/>
|
||||
<bitfield name="SRGB" pos="2" type="boolean"/>
|
||||
|
|
|
|||
|
|
@ -320,14 +320,14 @@ to upconvert to 32b float internally?
|
|||
16b float: 3
|
||||
-->
|
||||
<enum name="a6xx_2d_ifmt">
|
||||
<value value="0x10" name="R2D_UNORM8"/>
|
||||
<value value="0x7" name="R2D_INT32"/>
|
||||
<value value="0x6" name="R2D_INT16"/>
|
||||
<value value="0x5" name="R2D_INT8"/>
|
||||
<value value="0x4" name="R2D_FLOAT32"/>
|
||||
<value value="0x3" name="R2D_FLOAT16"/>
|
||||
<value value="0x2" name="R2D_SNORM8"/>
|
||||
<value value="0x1" name="R2D_UNORM8_SRGB"/>
|
||||
<value value="0x0" name="R2D_RAW"/>
|
||||
<value value="0x0" name="R2D_UNORM8"/>
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_tex_type">
|
||||
|
|
@ -380,4 +380,50 @@ to upconvert to 32b float internally?
|
|||
<value value="0x3" name="TESS_CCW_TRIS"/>
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_tex_filter"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_NEAREST" value="0"/>
|
||||
<value name="A6XX_TEX_LINEAR" value="1"/>
|
||||
<value name="A6XX_TEX_ANISO" value="2"/>
|
||||
<value name="A6XX_TEX_CUBIC" value="3"/> <!-- a650 only -->
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_tex_clamp"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_REPEAT" value="0"/>
|
||||
<value name="A6XX_TEX_CLAMP_TO_EDGE" value="1"/>
|
||||
<value name="A6XX_TEX_MIRROR_REPEAT" value="2"/>
|
||||
<value name="A6XX_TEX_CLAMP_TO_BORDER" value="3"/>
|
||||
<value name="A6XX_TEX_MIRROR_CLAMP" value="4"/>
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_tex_aniso"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_ANISO_1" value="0"/>
|
||||
<value name="A6XX_TEX_ANISO_2" value="1"/>
|
||||
<value name="A6XX_TEX_ANISO_4" value="2"/>
|
||||
<value name="A6XX_TEX_ANISO_8" value="3"/>
|
||||
<value name="A6XX_TEX_ANISO_16" value="4"/>
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_reduction_mode">
|
||||
<value name="A6XX_REDUCTION_MODE_AVERAGE" value="0"/>
|
||||
<value name="A6XX_REDUCTION_MODE_MIN" value="1"/>
|
||||
<value name="A6XX_REDUCTION_MODE_MAX" value="2"/>
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_fast_border_color">
|
||||
<!-- R B G A -->
|
||||
<value name="A6XX_BORDER_COLOR_0_0_0_0" value="0"/>
|
||||
<value name="A6XX_BORDER_COLOR_0_0_0_1" value="1"/>
|
||||
<value name="A6XX_BORDER_COLOR_1_1_1_0" value="2"/>
|
||||
<value name="A6XX_BORDER_COLOR_1_1_1_1" value="3"/>
|
||||
</enum>
|
||||
|
||||
<enum name="a6xx_tex_swiz"> <!-- same as a4xx? -->
|
||||
<value name="A6XX_TEX_X" value="0"/>
|
||||
<value name="A6XX_TEX_Y" value="1"/>
|
||||
<value name="A6XX_TEX_Z" value="2"/>
|
||||
<value name="A6XX_TEX_W" value="3"/>
|
||||
<value name="A6XX_TEX_ZERO" value="4"/>
|
||||
<value name="A6XX_TEX_ONE" value="5"/>
|
||||
</enum>
|
||||
|
||||
</database>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,10 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<bitfield name="GX_HM_GDSC_POWER_OFF" pos="6" type="boolean"/>
|
||||
<bitfield name="GX_HM_CLK_OFF" pos="7" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="0x50d0" name="GMU_SPTPRAC_PWR_CLK_STATUS" variants="A7XX">
|
||||
<bitfield name="GX_HM_GDSC_POWER_OFF" pos="0" type="boolean"/>
|
||||
<bitfield name="GX_HM_CLK_OFF" pos="1" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="0x50e4" name="GMU_GPU_NAP_CTRL">
|
||||
<bitfield name="HW_NAP_ENABLE" pos="0"/>
|
||||
<bitfield name="SID" low="4" high="8"/>
|
||||
|
|
@ -127,6 +131,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 offset="0x5088" name="GMU_ALWAYS_ON_COUNTER_L"/>
|
||||
<reg32 offset="0x5089" name="GMU_ALWAYS_ON_COUNTER_H"/>
|
||||
<reg32 offset="0x50c3" name="GMU_GMU_PWR_COL_KEEPALIVE"/>
|
||||
<reg32 offset="0x50c4" name="GMU_PWR_COL_PREEMPT_KEEPALIVE"/>
|
||||
<reg32 offset="0x5180" name="GMU_HFI_CTRL_STATUS"/>
|
||||
<reg32 offset="0x5181" name="GMU_HFI_VERSION_INFO"/>
|
||||
<reg32 offset="0x5182" name="GMU_HFI_SFR_ADDR"/>
|
||||
|
|
@ -228,6 +233,12 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 offset="0x03ee" name="RSCC_TCS1_DRV0_STATUS"/>
|
||||
<reg32 offset="0x0496" name="RSCC_TCS2_DRV0_STATUS"/>
|
||||
<reg32 offset="0x053e" name="RSCC_TCS3_DRV0_STATUS"/>
|
||||
<reg32 offset="0x05e6" name="RSCC_TCS4_DRV0_STATUS" variants="A7XX"/>
|
||||
<reg32 offset="0x068e" name="RSCC_TCS5_DRV0_STATUS" variants="A7XX"/>
|
||||
<reg32 offset="0x0736" name="RSCC_TCS6_DRV0_STATUS" variants="A7XX"/>
|
||||
<reg32 offset="0x07de" name="RSCC_TCS7_DRV0_STATUS" variants="A7XX"/>
|
||||
<reg32 offset="0x0886" name="RSCC_TCS8_DRV0_STATUS" variants="A7XX"/>
|
||||
<reg32 offset="0x092e" name="RSCC_TCS9_DRV0_STATUS" variants="A7XX"/>
|
||||
</domain>
|
||||
|
||||
</database>
|
||||
|
|
|
|||
|
|
@ -120,12 +120,12 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<value name="LRZ_FLUSH" value="38" variants="A5XX-"/>
|
||||
<value name="BLIT_OP_FILL_2D" value="39" variants="A5XX-"/>
|
||||
<value name="BLIT_OP_COPY_2D" value="40" variants="A5XX-A6XX"/>
|
||||
<value name="UNK_40" value="40" variants="A7XX"/>
|
||||
<value name="LRZ_CACHE_INVALIDATE" value="40" variants="A7XX"/>
|
||||
<value name="LRZ_Q_CACHE_INVALIDATE" value="41" variants="A7XX"/>
|
||||
<value name="BLIT_OP_SCALE_2D" value="42" variants="A5XX-"/>
|
||||
<value name="CONTEXT_DONE_2D" value="43" variants="A5XX-"/>
|
||||
<value name="UNK_2C" value="44" variants="A5XX-"/>
|
||||
<value name="UNK_2D" value="45" variants="A5XX-"/>
|
||||
<value name="VSC_BINNING_START" value="44" variants="A5XX-"/>
|
||||
<value name="VSC_BINNING_END" value="45" variants="A5XX-"/>
|
||||
|
||||
<!-- a6xx events -->
|
||||
<doc>
|
||||
|
|
@ -523,7 +523,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<!--
|
||||
Seems to set the mode flags which control which CP_SET_DRAW_STATE
|
||||
packets are executed, based on their ENABLE_MASK values
|
||||
|
||||
|
||||
CP_SET_MODE w/ payload of 0x1 seems to cause CP_SET_DRAW_STATE
|
||||
packets w/ ENABLE_MASK & 0x6 to execute immediately
|
||||
-->
|
||||
|
|
@ -640,8 +640,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<value name="CP_BV_BR_COUNT_OPS" value="0x1b" variants="A7XX-"/>
|
||||
<doc> Clears, adds to local, or adds to global timestamp </doc>
|
||||
<value name="CP_MODIFY_TIMESTAMP" value="0x1c" variants="A7XX-"/>
|
||||
<!-- similar to CP_CONTEXT_REG_BUNCH, but discards first two dwords?? -->
|
||||
<value name="CP_CONTEXT_REG_BUNCH2" value="0x5d" variants="A7XX-"/>
|
||||
<value name="CP_NON_CONTEXT_REG_BUNCH" value="0x5d" variants="A7XX-"/>
|
||||
<doc>
|
||||
Write to a scratch memory that is read by CP_REG_TEST with
|
||||
SOURCE_SCRATCH_MEM set. It's not the same scratch as scratch registers.
|
||||
|
|
@ -918,12 +917,6 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
</reg32>
|
||||
|
||||
<stripe varset="chip" variants="A5XX-">
|
||||
<reg32 offset="4" name="4">
|
||||
<bitfield name="INDX_BASE_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="5" name="5">
|
||||
<bitfield name="INDX_BASE_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="4" name="INDX_BASE" type="address"/>
|
||||
<reg32 offset="6" name="6">
|
||||
<!-- max # of elements in index buffer -->
|
||||
|
|
@ -1099,8 +1092,10 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<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"/>
|
||||
<bitfield name="GROUP_ID" low="24" high="28" type="uint"/>
|
||||
<!-- high bit is 28 until a750: -->
|
||||
<bitfield name="GROUP_ID" low="24" high="29" type="uint"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="ADDR" type="address"/>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="ADDR_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
|
|
@ -1166,26 +1161,11 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
</reg32>
|
||||
<stripe varset="a7xx_abs_mask_mode" variants="NO_ABS_MASK">
|
||||
<!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS -->
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="BIN_DATA_ADDR_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="BIN_DATA_ADDR_HI" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="BIN_DATA_ADDR" type="address"/>
|
||||
<!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)-->
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="BIN_SIZE_ADDRESS_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="4" name="4">
|
||||
<bitfield name="BIN_SIZE_ADDRESS_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="3" name="BIN_SIZE_ADDR" type="address"/>
|
||||
<!-- new on a6xx, where BIN_DATA_ADDR is the DRAW_STRM: -->
|
||||
<reg32 offset="5" name="5">
|
||||
<bitfield name="BIN_PRIM_STRM_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="6" name="6">
|
||||
<bitfield name="BIN_PRIM_STRM_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="5" name="BIN_PRIM_STRM" type="address"/>
|
||||
<!--
|
||||
a7xx adds a few more addresses to the end of the pkt
|
||||
-->
|
||||
|
|
@ -1195,26 +1175,11 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<stripe varset="a7xx_abs_mask_mode" variants="ABS_MASK">
|
||||
<reg32 offset="1" name="ABS_MASK"/>
|
||||
<!-- BIN_DATA_ADDR -> VSC_PIPE[p].DATA_ADDRESS -->
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="BIN_DATA_ADDR_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="BIN_DATA_ADDR_HI" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg64 offset="2" name="BIN_DATA_ADDR" type="address"/>
|
||||
<!-- BIN_SIZE_ADDRESS -> VSC_SIZE_ADDRESS + (p * 4)-->
|
||||
<reg32 offset="4" name="4">
|
||||
<bitfield name="BIN_SIZE_ADDRESS_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="5" name="5">
|
||||
<bitfield name="BIN_SIZE_ADDRESS_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="4" name="BIN_SIZE_ADDR" type="address"/>
|
||||
<!-- new on a6xx, where BIN_DATA_ADDR is the DRAW_STRM: -->
|
||||
<reg32 offset="6" name="6">
|
||||
<bitfield name="BIN_PRIM_STRM_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="7" name="7">
|
||||
<bitfield name="BIN_PRIM_STRM_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="6" name="BIN_PRIM_STRM" type="address"/>
|
||||
<!--
|
||||
a7xx adds a few more addresses to the end of the pkt
|
||||
-->
|
||||
|
|
@ -1300,7 +1265,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
</reg32>
|
||||
</domain>
|
||||
|
||||
<domain name="CP_REG_TO_MEM" width="32">
|
||||
<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). -->
|
||||
|
|
@ -1308,12 +1273,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<bitfield name="64B" pos="30" type="boolean"/>
|
||||
<bitfield name="ACCUMULATE" pos="31" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="DEST" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2" varset="chip" variants="A5XX-">
|
||||
<bitfield name="DEST_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<stripe varset="chip" variants="A2XX-A4XX">
|
||||
<reg32 offset="1" name="DEST" type="address"/>
|
||||
</stripe>
|
||||
<stripe varset="chip" variants="A5XX-">
|
||||
<reg64 offset="1" name="DEST" type="address"/>
|
||||
</stripe>
|
||||
</domain>
|
||||
|
||||
<domain name="CP_REG_TO_MEM_OFFSET_REG" width="32">
|
||||
|
|
@ -1329,12 +1294,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<bitfield name="64B" pos="30" type="boolean"/>
|
||||
<bitfield name="ACCUMULATE" pos="31" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="DEST" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2" varset="chip" variants="A5XX-">
|
||||
<bitfield name="DEST_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="DEST" type="waddress"/>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="OFFSET0" low="0" high="17" type="hex"/>
|
||||
<bitfield name="OFFSET0_SCRATCH" pos="19" type="boolean"/>
|
||||
|
|
@ -1354,18 +1314,8 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<bitfield name="64B" pos="30" type="boolean"/>
|
||||
<bitfield name="ACCUMULATE" pos="31" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="DEST" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2" varset="chip" variants="A5XX-">
|
||||
<bitfield name="DEST_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="OFFSET_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="4" name="4">
|
||||
<bitfield name="OFFSET_HI" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="DEST" type="waddress"/>
|
||||
<reg64 offset="3" name="OFFSET" type="waddress"/>
|
||||
</domain>
|
||||
|
||||
<domain name="CP_MEM_TO_REG" width="32">
|
||||
|
|
@ -1378,12 +1328,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<!-- does the same thing as CP_MEM_TO_MEM::UNK31 -->
|
||||
<bitfield name="UNK31" pos="31" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="SRC" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2" varset="chip" variants="A5XX-">
|
||||
<bitfield name="SRC_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<stripe varset="chip" variants="A2XX-A4XX">
|
||||
<reg32 offset="1" name="SRC" type="address"/>
|
||||
</stripe>
|
||||
<stripe varset="chip" variants="A5XX-">
|
||||
<reg64 offset="1" name="SRC" type="address"/>
|
||||
</stripe>
|
||||
</domain>
|
||||
|
||||
<domain name="CP_MEM_TO_MEM" width="32">
|
||||
|
|
@ -1403,6 +1353,10 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<!-- some other kind of wait -->
|
||||
<bitfield name="UNK31" pos="31" type="boolean"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="DST" type="waddress"/>
|
||||
<reg64 offset="3" name="SRC_A" type="address"/>
|
||||
<reg64 offset="5" name="SRC_B" type="address"/>
|
||||
<reg64 offset="7" name="SRC_C" type="address"/>
|
||||
<!--
|
||||
followed by sequence of addresses.. the first is the
|
||||
destination and the rest are N src addresses which are
|
||||
|
|
@ -1461,12 +1415,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
</domain>
|
||||
|
||||
<domain name="CP_MEM_WRITE" width="32">
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="ADDR_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="ADDR_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<stripe varset="chip" variants="A2XX-A4XX">
|
||||
<reg32 offset="0" name="ADDR" type="address"/>
|
||||
</stripe>
|
||||
<stripe varset="chip" variants="A5XX-">
|
||||
<reg64 offset="0" name="ADDR" type="address"/>
|
||||
</stripe>
|
||||
<!-- followed by the DWORDs to write -->
|
||||
</domain>
|
||||
|
||||
|
|
@ -1518,24 +1472,14 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<bitfield name="POLL" low="4" high="5" type="poll_memory_type"/>
|
||||
<bitfield name="WRITE_MEMORY" pos="8" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="POLL_ADDR_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="POLL_ADDR_HI" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="POLL_ADDR" type="address"/>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="REF" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="4" name="4">
|
||||
<bitfield name="MASK" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="5" name="5">
|
||||
<bitfield name="WRITE_ADDR_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="6" name="6">
|
||||
<bitfield name="WRITE_ADDR_HI" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg64 offset="5" name="WRITE_ADDR" type="waddress"/>
|
||||
<reg32 offset="7" name="7">
|
||||
<bitfield name="WRITE_DATA" low="0" high="31"/>
|
||||
</reg32>
|
||||
|
|
@ -1550,12 +1494,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<!-- Reserved for flags, presumably? Unused in FW -->
|
||||
<bitfield name="RESERVED" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="POLL_ADDR_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="POLL_ADDR_HI" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="POLL_ADDR" type="address"/>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="REF" low="0" high="31"/>
|
||||
</reg32>
|
||||
|
|
@ -1573,12 +1512,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<bitfield name="POLL" low="4" high="5" type="poll_memory_type"/>
|
||||
<bitfield name="WRITE_MEMORY" pos="8" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="POLL_ADDR_LO" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="POLL_ADDR_HI" low="0" high="31" type="hex"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="POLL_ADDR" type="address"/>
|
||||
<reg32 offset="3" name="3">
|
||||
<bitfield name="REF" low="0" high="31"/>
|
||||
</reg32>
|
||||
|
|
@ -1712,12 +1646,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
TODO what is gpuaddr for, seems to be all 0's.. maybe needed for
|
||||
context switch?
|
||||
-->
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="ADDR_0_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="ADDR_0_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="ADDR" type="waddress"/>
|
||||
<reg32 offset="3" name="3">
|
||||
<!-- ??? -->
|
||||
</reg32>
|
||||
|
|
@ -1832,9 +1761,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<reg32 offset="0" name="0">
|
||||
</reg32>
|
||||
<stripe varset="chip" variants="A4XX">
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="ADDR" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="ADDR" type="address"/>
|
||||
<reg32 offset="2" name="2">
|
||||
<!-- localsize is value minus one: -->
|
||||
<bitfield name="LOCALSIZEX" low="2" high="11" type="uint"/>
|
||||
|
|
@ -1843,12 +1770,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
</reg32>
|
||||
</stripe>
|
||||
<stripe varset="chip" variants="A5XX-">
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="ADDR_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="ADDR_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="1" name="ADDR" type="address"/>
|
||||
<reg32 offset="3" name="3">
|
||||
<!-- localsize is value minus one: -->
|
||||
<bitfield name="LOCALSIZEX" low="2" high="11" type="uint"/>
|
||||
|
|
@ -2161,12 +2083,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
</doc>
|
||||
</value>
|
||||
</enum>
|
||||
<reg32 offset="0" name="0">
|
||||
<bitfield name="ADDR_LO" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg32 offset="1" name="1">
|
||||
<bitfield name="ADDR_HI" low="0" high="31"/>
|
||||
</reg32>
|
||||
<reg64 offset="0" name="ADDR" type="address"/>
|
||||
<reg32 offset="2" name="2">
|
||||
<bitfield name="DWORDS" low="0" high="19" type="uint"/>
|
||||
<bitfield name="TYPE" low="20" high="21" type="amble_type"/>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,16 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 offset="0x00018" name="GLBL_CTRL"/>
|
||||
<reg32 offset="0x0001c" name="RBUF_CTRL"/>
|
||||
<reg32 offset="0x00020" name="VREG_CTRL_0"/>
|
||||
<reg32 offset="0x00024" name="CTRL_0"/>
|
||||
<reg32 offset="0x00024" name="CTRL_0">
|
||||
<bitfield name="CLKSL_SHUTDOWNB" pos="7" type="boolean"/>
|
||||
<bitfield name="DIGTOP_PWRDN_B" pos="6" type="boolean"/>
|
||||
<bitfield name="PLL_SHUTDOWNB" pos="5" type="boolean"/>
|
||||
<bitfield name="DLN3_SHUTDOWNB" pos="4" type="boolean"/>
|
||||
<bitfield name="DLN2_SHUTDOWNB" pos="3" type="boolean"/>
|
||||
<bitfield name="CLK_SHUTDOWNB" pos="2" type="boolean"/>
|
||||
<bitfield name="DLN1_SHUTDOWNB" pos="1" type="boolean"/>
|
||||
<bitfield name="DLN0_SHUTDOWNB" pos="0" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="0x00028" name="CTRL_1"/>
|
||||
<reg32 offset="0x0002c" name="CTRL_2"/>
|
||||
<reg32 offset="0x00030" name="CTRL_3"/>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import collections
|
|||
import argparse
|
||||
import time
|
||||
import datetime
|
||||
import re
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message):
|
||||
|
|
@ -31,7 +30,7 @@ class Enum(object):
|
|||
def names(self):
|
||||
return [n for (n, value) in self.values]
|
||||
|
||||
def dump(self):
|
||||
def dump(self, is_deprecated):
|
||||
use_hex = False
|
||||
for (name, value) in self.values:
|
||||
if value > 0x1000:
|
||||
|
|
@ -45,7 +44,7 @@ class Enum(object):
|
|||
print("\t%s = %d," % (name, value))
|
||||
print("};\n")
|
||||
|
||||
def dump_pack_struct(self):
|
||||
def dump_pack_struct(self, is_deprecated):
|
||||
pass
|
||||
|
||||
class Field(object):
|
||||
|
|
@ -70,11 +69,11 @@ class Field(object):
|
|||
raise parser.error("booleans should be 1 bit fields")
|
||||
elif self.type == "float" and not (high - low == 31 or high - low == 15):
|
||||
raise parser.error("floats should be 16 or 32 bit fields")
|
||||
elif not self.type in builtin_types and not self.type in parser.enums:
|
||||
elif self.type not in builtin_types and self.type not in parser.enums:
|
||||
raise parser.error("unknown type '%s'" % self.type)
|
||||
|
||||
def ctype(self, var_name):
|
||||
if self.type == None:
|
||||
if self.type is None:
|
||||
type = "uint32_t"
|
||||
val = var_name
|
||||
elif self.type == "boolean":
|
||||
|
|
@ -124,7 +123,7 @@ def field_name(reg, f):
|
|||
name = f.name.lower()
|
||||
else:
|
||||
# We hit this path when a reg is defined with no bitset fields, ie.
|
||||
# <reg32 offset="0x88db" name="RB_BLIT_DST_ARRAY_PITCH" low="0" high="28" shr="6" type="uint"/>
|
||||
# <reg32 offset="0x88db" name="RB_RESOLVE_SYSTEM_BUFFER_ARRAY_PITCH" low="0" high="28" shr="6" type="uint"/>
|
||||
name = reg.name.lower()
|
||||
|
||||
if (name in [ "double", "float", "int" ]) or not (name[0].isalpha()):
|
||||
|
|
@ -146,10 +145,23 @@ def indices_strides(indices):
|
|||
"%s(i%d)" % (offset, idx)
|
||||
for (idx, (ctype, stride, offset)) in enumerate(indices)])
|
||||
|
||||
def is_number(str):
|
||||
try:
|
||||
int(str)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def sanitize_variant(variant):
|
||||
if variant and "-" in variant:
|
||||
return variant[:variant.index("-")]
|
||||
return variant
|
||||
|
||||
class Bitset(object):
|
||||
def __init__(self, name, template):
|
||||
self.name = name
|
||||
self.inline = False
|
||||
self.reg = None
|
||||
if template:
|
||||
self.fields = template.fields[:]
|
||||
else:
|
||||
|
|
@ -175,11 +187,7 @@ class Bitset(object):
|
|||
print("#endif\n")
|
||||
|
||||
print(" return (struct fd_reg_pair) {")
|
||||
if reg.array:
|
||||
print(" .reg = REG_%s(__i)," % reg.full_name)
|
||||
else:
|
||||
print(" .reg = REG_%s," % reg.full_name)
|
||||
|
||||
print(" .reg = (uint32_t)%s," % reg.reg_offset())
|
||||
print(" .value =")
|
||||
for f in self.fields:
|
||||
if f.type in [ "address", "waddress" ]:
|
||||
|
|
@ -204,7 +212,7 @@ class Bitset(object):
|
|||
|
||||
print(" };")
|
||||
|
||||
def dump_pack_struct(self, reg=None):
|
||||
def dump_pack_struct(self, is_deprecated, reg=None):
|
||||
if not reg:
|
||||
return
|
||||
|
||||
|
|
@ -229,12 +237,15 @@ class Bitset(object):
|
|||
tab_to(" uint32_t", "dword;")
|
||||
print("};\n")
|
||||
|
||||
depcrstr = ""
|
||||
if is_deprecated:
|
||||
depcrstr = " FD_DEPRECATED"
|
||||
if reg.array:
|
||||
print("static inline struct fd_reg_pair\npack_%s(uint32_t __i, struct %s fields)\n{" %
|
||||
(prefix, prefix))
|
||||
print("static inline%s struct fd_reg_pair\npack_%s(uint32_t __i, struct %s fields)\n{" %
|
||||
(depcrstr, prefix, prefix))
|
||||
else:
|
||||
print("static inline struct fd_reg_pair\npack_%s(struct %s fields)\n{" %
|
||||
(prefix, prefix))
|
||||
print("static inline%s struct fd_reg_pair\npack_%s(struct %s fields)\n{" %
|
||||
(depcrstr, prefix, prefix))
|
||||
|
||||
self.dump_regpair_builder(reg)
|
||||
|
||||
|
|
@ -253,18 +264,23 @@ class Bitset(object):
|
|||
(prefix, prefix, prefix, skip))
|
||||
|
||||
|
||||
def dump(self, prefix=None):
|
||||
if prefix == None:
|
||||
def dump(self, is_deprecated, prefix=None):
|
||||
if prefix is None:
|
||||
prefix = self.name
|
||||
if self.reg and self.reg.bit_size == 64:
|
||||
print("static inline uint32_t %s_LO(uint32_t val)\n{" % prefix)
|
||||
print("\treturn val;\n}")
|
||||
print("static inline uint32_t %s_HI(uint32_t val)\n{" % prefix)
|
||||
print("\treturn val;\n}")
|
||||
for f in self.fields:
|
||||
if f.name:
|
||||
name = prefix + "_" + f.name
|
||||
else:
|
||||
name = prefix
|
||||
|
||||
if not f.name and f.low == 0 and f.shr == 0 and not f.type in ["float", "fixed", "ufixed"]:
|
||||
if not f.name and f.low == 0 and f.shr == 0 and f.type not in ["float", "fixed", "ufixed"]:
|
||||
pass
|
||||
elif f.type == "boolean" or (f.type == None and f.low == f.high):
|
||||
elif f.type == "boolean" or (f.type is None and f.low == f.high):
|
||||
tab_to("#define %s" % name, "0x%08x" % (1 << f.low))
|
||||
else:
|
||||
tab_to("#define %s__MASK" % name, "0x%08x" % mask(f.low, f.high))
|
||||
|
|
@ -286,6 +302,7 @@ class Array(object):
|
|||
self.domain = domain
|
||||
self.variant = variant
|
||||
self.parent = parent
|
||||
self.children = []
|
||||
if self.parent:
|
||||
self.name = self.parent.name + "_" + self.local_name
|
||||
else:
|
||||
|
|
@ -337,12 +354,15 @@ class Array(object):
|
|||
offset += self.parent.total_offset()
|
||||
return offset
|
||||
|
||||
def dump(self):
|
||||
def dump(self, is_deprecated):
|
||||
depcrstr = ""
|
||||
if is_deprecated:
|
||||
depcrstr = " FD_DEPRECATED"
|
||||
proto = indices_varlist(self.indices())
|
||||
strides = indices_strides(self.indices())
|
||||
array_offset = self.total_offset()
|
||||
if self.fixed_offsets:
|
||||
print("static inline uint32_t __offset_%s(%s idx)" % (self.local_name, self.index_ctype()))
|
||||
print("static inline%s uint32_t __offset_%s(%s idx)" % (depcrstr, self.local_name, self.index_ctype()))
|
||||
print("{\n\tswitch (idx) {")
|
||||
if self.index_type:
|
||||
for val, offset in zip(self.index_type.names(), self.offsets):
|
||||
|
|
@ -357,7 +377,7 @@ class Array(object):
|
|||
else:
|
||||
tab_to("#define REG_%s_%s(%s)" % (self.domain, self.name, proto), "(0x%08x + %s )\n" % (array_offset, strides))
|
||||
|
||||
def dump_pack_struct(self):
|
||||
def dump_pack_struct(self, is_deprecated):
|
||||
pass
|
||||
|
||||
def dump_regpair_builder(self):
|
||||
|
|
@ -373,6 +393,7 @@ class Reg(object):
|
|||
self.bit_size = bit_size
|
||||
if array:
|
||||
self.name = array.name + "_" + self.name
|
||||
array.children.append(self)
|
||||
self.full_name = self.domain + "_" + self.name
|
||||
if "stride" in attrs:
|
||||
self.stride = int(attrs["stride"], 0)
|
||||
|
|
@ -397,25 +418,34 @@ class Reg(object):
|
|||
else:
|
||||
return self.offset
|
||||
|
||||
def dump(self):
|
||||
def reg_offset(self):
|
||||
if self.array:
|
||||
offset = self.array.offset + self.offset
|
||||
return "(0x%08x + 0x%x*__i)" % (offset, self.array.stride)
|
||||
return "0x%08x" % self.offset
|
||||
|
||||
def dump(self, is_deprecated):
|
||||
depcrstr = ""
|
||||
if is_deprecated:
|
||||
depcrstr = " FD_DEPRECATED "
|
||||
proto = indices_prototype(self.indices())
|
||||
strides = indices_strides(self.indices())
|
||||
offset = self.total_offset()
|
||||
if proto == '':
|
||||
tab_to("#define REG_%s" % self.full_name, "0x%08x" % offset)
|
||||
else:
|
||||
print("static inline uint32_t REG_%s(%s) { return 0x%08x + %s; }" % (self.full_name, proto, offset, strides))
|
||||
print("static inline%s uint32_t REG_%s(%s) { return 0x%08x + %s; }" % (depcrstr, self.full_name, proto, offset, strides))
|
||||
|
||||
if self.bitset.inline:
|
||||
self.bitset.dump(self.full_name)
|
||||
self.bitset.dump(is_deprecated, self.full_name)
|
||||
print("")
|
||||
|
||||
def dump_pack_struct(self):
|
||||
def dump_pack_struct(self, is_deprecated):
|
||||
if self.bitset.inline:
|
||||
self.bitset.dump_pack_struct(self)
|
||||
self.bitset.dump_pack_struct(is_deprecated, self)
|
||||
|
||||
def dump_regpair_builder(self):
|
||||
if self.bitset.inline:
|
||||
self.bitset.dump_regpair_builder(self)
|
||||
self.bitset.dump_regpair_builder(self)
|
||||
|
||||
def dump_py(self):
|
||||
print("\tREG_%s = 0x%08x" % (self.full_name, self.offset))
|
||||
|
|
@ -444,9 +474,6 @@ class Parser(object):
|
|||
self.variants = set()
|
||||
self.file = []
|
||||
self.xml_files = []
|
||||
self.copyright_year = None
|
||||
self.authors = []
|
||||
self.license = None
|
||||
|
||||
def error(self, message):
|
||||
parser, filename = self.stack[-1]
|
||||
|
|
@ -454,7 +481,7 @@ class Parser(object):
|
|||
|
||||
def prefix(self, variant=None):
|
||||
if self.current_prefix_type == "variant" and variant:
|
||||
return variant
|
||||
return sanitize_variant(variant)
|
||||
elif self.current_stripe:
|
||||
return self.current_stripe + "_" + self.current_domain
|
||||
elif self.current_prefix:
|
||||
|
|
@ -500,15 +527,22 @@ class Parser(object):
|
|||
return varset
|
||||
|
||||
def parse_variants(self, attrs):
|
||||
if not "variants" in attrs:
|
||||
if "variants" not in attrs:
|
||||
return None
|
||||
variant = attrs["variants"].split(",")[0]
|
||||
if "-" in variant:
|
||||
variant = variant[:variant.index("-")]
|
||||
|
||||
variant = attrs["variants"].split(",")[0]
|
||||
varset = self.parse_varset(attrs)
|
||||
|
||||
assert varset.has_name(variant)
|
||||
if "-" in variant:
|
||||
# if we have a range, validate that both the start and end
|
||||
# of the range are valid enums:
|
||||
start = variant[:variant.index("-")]
|
||||
end = variant[variant.index("-") + 1:]
|
||||
assert varset.has_name(start)
|
||||
if end != "":
|
||||
assert varset.has_name(end)
|
||||
else:
|
||||
assert varset.has_name(variant)
|
||||
|
||||
return variant
|
||||
|
||||
|
|
@ -572,9 +606,6 @@ class Parser(object):
|
|||
error_str = str(xmlschema.error_log.filter_from_errors()[0])
|
||||
raise self.error("Schema validation failed for: " + filename + "\n" + error_str)
|
||||
except ImportError as e:
|
||||
if self.validate:
|
||||
raise e
|
||||
|
||||
print("lxml not found, skipping validation", file=sys.stderr)
|
||||
|
||||
def do_parse(self, filename):
|
||||
|
|
@ -620,6 +651,7 @@ class Parser(object):
|
|||
|
||||
self.current_reg = Reg(attrs, self.prefix(variant), self.current_array, bit_size)
|
||||
self.current_reg.bitset = self.current_bitset
|
||||
self.current_bitset.reg = self.current_reg
|
||||
|
||||
if len(self.stack) == 1:
|
||||
self.file.append(self.current_reg)
|
||||
|
|
@ -643,7 +675,7 @@ class Parser(object):
|
|||
elif name == "domain":
|
||||
self.current_domain = attrs["name"]
|
||||
if "prefix" in attrs:
|
||||
self.current_prefix = self.parse_variants(attrs)
|
||||
self.current_prefix = sanitize_variant(self.parse_variants(attrs))
|
||||
self.current_prefix_type = attrs["prefix"]
|
||||
else:
|
||||
self.current_prefix = None
|
||||
|
|
@ -651,7 +683,7 @@ class Parser(object):
|
|||
if "varset" in attrs:
|
||||
self.current_varset = self.enums[attrs["varset"]]
|
||||
elif name == "stripe":
|
||||
self.current_stripe = self.parse_variants(attrs)
|
||||
self.current_stripe = sanitize_variant(self.parse_variants(attrs))
|
||||
elif name == "enum":
|
||||
self.current_enum_value = 0
|
||||
self.current_enum = Enum(attrs["name"])
|
||||
|
|
@ -686,10 +718,6 @@ class Parser(object):
|
|||
self.parse_field(attrs["name"], attrs)
|
||||
elif name == "database":
|
||||
self.do_validate(attrs["xsi:schemaLocation"])
|
||||
elif name == "copyright":
|
||||
self.copyright_year = attrs["year"]
|
||||
elif name == "author":
|
||||
self.authors.append(attrs["name"] + " <" + attrs["email"] + "> " + attrs["name"])
|
||||
|
||||
def end_element(self, name):
|
||||
if name == "domain":
|
||||
|
|
@ -703,11 +731,16 @@ class Parser(object):
|
|||
elif name == "reg32":
|
||||
self.current_reg = None
|
||||
elif name == "array":
|
||||
# if the array has no Reg children, push an implicit reg32:
|
||||
if len(self.current_array.children) == 0:
|
||||
attrs = {
|
||||
"name": "REG",
|
||||
"offset": "0",
|
||||
}
|
||||
self.parse_reg(attrs, 32)
|
||||
self.current_array = self.current_array.parent
|
||||
elif name == "enum":
|
||||
self.current_enum = None
|
||||
elif name == "license":
|
||||
self.license = self.cdata
|
||||
|
||||
def character_data(self, data):
|
||||
self.cdata += data
|
||||
|
|
@ -720,10 +753,10 @@ class Parser(object):
|
|||
if variants:
|
||||
for variant, vreg in variants.items():
|
||||
if reg == vreg:
|
||||
d[(usage, variant)].append(reg)
|
||||
d[(usage, sanitize_variant(variant))].append(reg)
|
||||
else:
|
||||
for variant in self.variants:
|
||||
d[(usage, variant)].append(reg)
|
||||
d[(usage, sanitize_variant(variant))].append(reg)
|
||||
|
||||
print("#ifdef __cplusplus")
|
||||
|
||||
|
|
@ -753,6 +786,9 @@ class Parser(object):
|
|||
|
||||
print("#endif")
|
||||
|
||||
def has_variants(self, reg):
|
||||
return reg.name in self.variant_regs and not is_number(reg.name) and not is_number(reg.name[1:])
|
||||
|
||||
def dump(self):
|
||||
enums = []
|
||||
bitsets = []
|
||||
|
|
@ -766,7 +802,7 @@ class Parser(object):
|
|||
regs.append(e)
|
||||
|
||||
for e in enums + bitsets + regs:
|
||||
e.dump()
|
||||
e.dump(self.has_variants(e))
|
||||
|
||||
self.dump_reg_usages()
|
||||
|
||||
|
|
@ -782,8 +818,7 @@ class Parser(object):
|
|||
|
||||
|
||||
def dump_reg_variants(self, regname, variants):
|
||||
# Don't bother for things that only have a single variant:
|
||||
if len(variants) == 1:
|
||||
if is_number(regname) or is_number(regname[1:]):
|
||||
return
|
||||
print("#ifdef __cplusplus")
|
||||
print("struct __%s {" % regname)
|
||||
|
|
@ -834,11 +869,20 @@ class Parser(object):
|
|||
xtravar = "__i, "
|
||||
print("__%s(%sstruct __%s fields) {" % (regname, xtra, regname))
|
||||
for variant in variants.keys():
|
||||
print(" if (%s == %s) {" % (varenum.upper(), variant))
|
||||
if "-" in variant:
|
||||
start = variant[:variant.index("-")]
|
||||
end = variant[variant.index("-") + 1:]
|
||||
if end != "":
|
||||
print(" if ((%s >= %s) && (%s <= %s)) {" % (varenum.upper(), start, varenum.upper(), end))
|
||||
else:
|
||||
print(" if (%s >= %s) {" % (varenum.upper(), start))
|
||||
else:
|
||||
print(" if (%s == %s) {" % (varenum.upper(), variant))
|
||||
reg = variants[variant]
|
||||
reg.dump_regpair_builder()
|
||||
print(" } else")
|
||||
print(" assert(!\"invalid variant\");")
|
||||
print(" return (struct fd_reg_pair){};")
|
||||
print("}")
|
||||
|
||||
if bit_size == 64:
|
||||
|
|
@ -851,7 +895,7 @@ class Parser(object):
|
|||
|
||||
def dump_structs(self):
|
||||
for e in self.file:
|
||||
e.dump_pack_struct()
|
||||
e.dump_pack_struct(self.has_variants(e))
|
||||
|
||||
for regname in self.variant_regs:
|
||||
self.dump_reg_variants(regname, self.variant_regs[regname])
|
||||
|
|
@ -868,33 +912,7 @@ def dump_c(args, guard, func):
|
|||
|
||||
print("#ifndef %s\n#define %s\n" % (guard, guard))
|
||||
|
||||
print("""/* Autogenerated file, DO NOT EDIT manually!
|
||||
|
||||
This file was generated by the rules-ng-ng gen_header.py tool in this git repository:
|
||||
http://gitlab.freedesktop.org/mesa/mesa/
|
||||
git clone https://gitlab.freedesktop.org/mesa/mesa.git
|
||||
|
||||
The rules-ng-ng source files this header was generated from are:
|
||||
""")
|
||||
maxlen = 0
|
||||
for filepath in p.xml_files:
|
||||
new_filepath = re.sub("^.+drivers","drivers",filepath)
|
||||
maxlen = max(maxlen, len(new_filepath))
|
||||
for filepath in p.xml_files:
|
||||
pad = " " * (maxlen - len(new_filepath))
|
||||
filesize = str(os.path.getsize(filepath))
|
||||
filesize = " " * (7 - len(filesize)) + filesize
|
||||
filetime = time.ctime(os.path.getmtime(filepath))
|
||||
print("- " + new_filepath + pad + " (" + filesize + " bytes, from <stripped>)")
|
||||
if p.copyright_year:
|
||||
current_year = str(datetime.date.today().year)
|
||||
print()
|
||||
print("Copyright (C) %s-%s by the following authors:" % (p.copyright_year, current_year))
|
||||
for author in p.authors:
|
||||
print("- " + author)
|
||||
if p.license:
|
||||
print(p.license)
|
||||
print("*/")
|
||||
print("/* Autogenerated file, DO NOT EDIT manually! */")
|
||||
|
||||
print()
|
||||
print("#ifdef __KERNEL__")
|
||||
|
|
@ -912,9 +930,20 @@ The rules-ng-ng source files this header was generated from are:
|
|||
print("#endif")
|
||||
print()
|
||||
|
||||
print("#ifndef FD_NO_DEPRECATED_PACK")
|
||||
print("#define FD_DEPRECATED __attribute__((deprecated))")
|
||||
print("#else")
|
||||
print("#define FD_DEPRECATED")
|
||||
print("#endif")
|
||||
print()
|
||||
|
||||
func(p)
|
||||
|
||||
print("\n#endif /* %s */" % guard)
|
||||
print()
|
||||
print("#undef FD_DEPRECATED")
|
||||
print()
|
||||
|
||||
print("#endif /* %s */" % guard)
|
||||
|
||||
|
||||
def dump_c_defines(args):
|
||||
|
|
@ -931,7 +960,7 @@ def dump_py_defines(args):
|
|||
p = Parser()
|
||||
|
||||
try:
|
||||
p.parse(args.rnn, args.xml)
|
||||
p.parse(args.rnn, args.xml, args.validate)
|
||||
except Error as e:
|
||||
print(e, file=sys.stderr)
|
||||
exit(1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue