Compare commits
212 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9c309610d | ||
|
|
aa0dfa5d16 | ||
|
|
d8db54ed3b | ||
|
|
85135b6dd5 | ||
|
|
39294c71d0 | ||
|
|
8948f5c05d | ||
|
|
ee15712244 | ||
|
|
68a902fe55 | ||
|
|
76e224dc98 | ||
|
|
6517d9007b | ||
|
|
1b236d1075 | ||
|
|
5de8b284f8 | ||
|
|
7646d0f7f1 | ||
|
|
a924a833d0 | ||
|
|
5d5c508d47 | ||
|
|
8a0a87c923 | ||
|
|
393cd16f3a | ||
|
|
e1033dcc0e | ||
|
|
b6ee419de4 | ||
|
|
f548d786a8 | ||
|
|
332ec26e7b | ||
|
|
9f4ffb9a9c | ||
|
|
ed101b0949 | ||
|
|
fa8171e920 | ||
|
|
122ab67613 | ||
|
|
945e0f5efc | ||
|
|
6fca65ccb0 | ||
|
|
859a1ae388 | ||
|
|
41179d35fb | ||
|
|
57c7528f8c | ||
|
|
23a6de947e | ||
|
|
ac057abd31 | ||
|
|
694be6adcd | ||
|
|
ea6b8af19e | ||
|
|
42b3371dfa | ||
|
|
986190113f | ||
|
|
d2e6912f20 | ||
|
|
054ad80080 | ||
|
|
c70f833efa | ||
|
|
b608dfd547 | ||
|
|
dffa02cc2a | ||
|
|
a33fd4351b | ||
|
|
0953d76319 | ||
|
|
804dea4ce6 | ||
|
|
68229c25b8 | ||
|
|
bed14a3bb9 | ||
|
|
41531113f2 | ||
|
|
ea5b58fcdf | ||
|
|
ae78fc1d7e | ||
|
|
b48f513acf | ||
|
|
b6492e810e | ||
|
|
25f251ea49 | ||
|
|
600576bd13 | ||
|
|
9040d9932a | ||
|
|
80280ab41e | ||
|
|
ca7ae55c48 | ||
|
|
0d15a5ef69 | ||
|
|
5200e0ea04 | ||
|
|
103686b10c | ||
|
|
cba6ccd255 | ||
|
|
5f9d2ce95d | ||
|
|
09588133d4 | ||
|
|
10df41f3a6 | ||
|
|
04285e416b | ||
|
|
5b142a5515 | ||
|
|
8ed17fc2f4 | ||
|
|
af4b70fff2 | ||
|
|
aaa397f95a | ||
|
|
ac4ea80c8c | ||
|
|
a6d0e33c3f | ||
|
|
74eacc6b50 | ||
|
|
055b21d3cf | ||
|
|
8388111622 | ||
|
|
989cb3490b | ||
|
|
eb54959b93 | ||
|
|
99098ac658 | ||
|
|
7b4567cebc | ||
|
|
672fd7d815 | ||
|
|
6453ef9313 | ||
|
|
63f8961563 | ||
|
|
c106837527 | ||
|
|
925130181f | ||
|
|
776cec534a | ||
|
|
d906a0bdc2 | ||
|
|
b6059252cb | ||
|
|
bd5d3e1fb4 | ||
|
|
9caf508f3a | ||
|
|
29aeb2c98f | ||
|
|
61412ac5b5 | ||
|
|
5dc7c1e48d | ||
|
|
b67ca04aa0 | ||
|
|
7de41ec0b9 | ||
|
|
7dc94830d3 | ||
|
|
c5c1c3eb35 | ||
|
|
4d7e1ead3b | ||
|
|
839d50f0a1 | ||
|
|
4f0d4b7061 | ||
|
|
dc02fca014 | ||
|
|
df2301f33e | ||
|
|
2eb5e6adb5 | ||
|
|
f2689a3ccc | ||
|
|
49185f9466 | ||
|
|
e82d3a0bb1 | ||
|
|
6f697fc063 | ||
|
|
ecfb13285d | ||
|
|
4ad208b26f | ||
|
|
b74746724f | ||
|
|
c0287eb905 | ||
|
|
77aec8f806 | ||
|
|
2c1bb0a77e | ||
|
|
153366a6f5 | ||
|
|
75eb1f0a6b | ||
|
|
50f5ca35f9 | ||
|
|
f7eba7b59e | ||
|
|
dc3e650ce1 | ||
|
|
632174d48a | ||
|
|
3b3668af63 | ||
|
|
22227d74fd | ||
|
|
3fbf48ec45 | ||
|
|
8580c66f3c | ||
|
|
0e156db800 | ||
|
|
fe7b8b61c6 | ||
|
|
ed5d4496d7 | ||
|
|
eec3b9f699 | ||
|
|
02524dfa62 | ||
|
|
76fb26265f | ||
|
|
5abec5d77e | ||
|
|
3851b91c8f | ||
|
|
bf8ab5ac8d | ||
|
|
309939ed8a | ||
|
|
40e0553a6d | ||
|
|
497945318d | ||
|
|
b92c738248 | ||
|
|
673461e76a | ||
|
|
85a24731ff | ||
|
|
636e73b34e | ||
|
|
0670a85109 | ||
|
|
acf7cceaf4 | ||
|
|
b845614d93 | ||
|
|
e9fe4aa5da | ||
|
|
54cffae709 | ||
|
|
3cf0279920 | ||
|
|
f67d486afc | ||
|
|
5691e1fe7d | ||
|
|
01a24161e1 | ||
|
|
804f95c769 | ||
|
|
1199c5a501 | ||
|
|
2bc4ab0787 | ||
|
|
f5514fdd59 | ||
|
|
0b5e268a0d | ||
|
|
567ae59295 | ||
|
|
848a1bbf75 | ||
|
|
f7add98021 | ||
|
|
441ab88ea6 | ||
|
|
f4d9f13eb7 | ||
|
|
8d6b6e3078 | ||
|
|
e113e17634 | ||
|
|
534226dd92 | ||
|
|
1b3bf3b1ce | ||
|
|
59598b642c | ||
|
|
44fde9148e | ||
|
|
b766d992cd | ||
|
|
76330e01e0 | ||
|
|
b3bad314cd | ||
|
|
28337278f5 | ||
|
|
86f859fc4b | ||
|
|
9a151a1e8d | ||
|
|
4419531c3d | ||
|
|
4ddfcc0a10 | ||
|
|
2b7bfae14a | ||
|
|
1bdbb50dd5 | ||
|
|
3a24655b15 | ||
|
|
25281c8b70 | ||
|
|
0b099e0d7e | ||
|
|
e6dc461e83 | ||
|
|
b2a234e861 | ||
|
|
4121e0bc1c | ||
|
|
645c2d229c | ||
|
|
3b2ed60056 | ||
|
|
3f134d4eab | ||
|
|
ad3c1d83ab | ||
|
|
80d6ecc10a | ||
|
|
345e2402f9 | ||
|
|
9deca0ad10 | ||
|
|
7ed205734a | ||
|
|
e5b76990e8 | ||
|
|
84f338c4d3 | ||
|
|
c6fea63d41 | ||
|
|
4835b657d6 | ||
|
|
d492687bfa | ||
|
|
0b8a882b92 | ||
|
|
be3b2acd0d | ||
|
|
93af1dbe3e | ||
|
|
f5bd27247f | ||
|
|
8f263ba951 | ||
|
|
328f064e3a | ||
|
|
f71ea3441b | ||
|
|
1e696c47d1 | ||
|
|
0fde91e372 | ||
|
|
e7523b153d | ||
|
|
b4e0021277 | ||
|
|
914ee6b355 | ||
|
|
8796032540 | ||
|
|
f286ad3039 | ||
|
|
c783b6740a | ||
|
|
ffdad2e91a | ||
|
|
95faea9235 | ||
|
|
95d7ebbcf1 | ||
|
|
ee785e6e99 | ||
|
|
3e6dad1592 | ||
|
|
6ee5bcdadf | ||
|
|
ab59ed04c6 |
161 changed files with 49167 additions and 2236 deletions
|
|
@ -297,6 +297,12 @@ properties:
|
|||
|
||||
* arm/msm/qcom,kpss-acc.txt
|
||||
|
||||
qcom,freq-domain:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle-array'
|
||||
description: |
|
||||
CPUs supporting freq-domain must set their "qcom,freq-domain" property
|
||||
with phandle to a cpufreq_hw node followed by the Domain ID(0/1).
|
||||
|
||||
rockchip,pmu:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle'
|
||||
description: |
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ description: |
|
|||
sa8155p
|
||||
sc7180
|
||||
sc7280
|
||||
msm8998
|
||||
sdm630
|
||||
sdm660
|
||||
sdm845
|
||||
|
|
@ -194,6 +195,16 @@ properties:
|
|||
- google,senor
|
||||
- const: qcom,sc7280
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- asus,novago-tp370ql
|
||||
- hp,envy-x2
|
||||
- lenovo,miix-630
|
||||
- oneplus,cheeseburger
|
||||
- oneplus,dumpling
|
||||
- qcom,msm8998-mtp
|
||||
- const: qcom,msm8998
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- xiaomi,lavender
|
||||
|
|
|
|||
|
|
@ -1,172 +0,0 @@
|
|||
Qualcomm Technologies, Inc. CPUFREQ Bindings
|
||||
|
||||
CPUFREQ HW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
|
||||
SoCs to manage frequency in hardware. It is capable of controlling frequency
|
||||
for multiple clusters.
|
||||
|
||||
Properties:
|
||||
- compatible
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be "qcom,cpufreq-hw" or "qcom,cpufreq-epss".
|
||||
|
||||
- clocks
|
||||
Usage: required
|
||||
Value type: <phandle> From common clock binding.
|
||||
Definition: clock handle for XO clock and GPLL0 clock.
|
||||
|
||||
- clock-names
|
||||
Usage: required
|
||||
Value type: <string> From common clock binding.
|
||||
Definition: must be "xo", "alternate".
|
||||
|
||||
- reg
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: Addresses and sizes for the memory of the HW bases in
|
||||
each frequency domain.
|
||||
- reg-names
|
||||
Usage: Optional
|
||||
Value type: <string>
|
||||
Definition: Frequency domain name i.e.
|
||||
"freq-domain0", "freq-domain1".
|
||||
|
||||
- #freq-domain-cells:
|
||||
Usage: required.
|
||||
Definition: Number of cells in a freqency domain specifier.
|
||||
|
||||
* Property qcom,freq-domain
|
||||
Devices supporting freq-domain must set their "qcom,freq-domain" property with
|
||||
phandle to a cpufreq_hw followed by the Domain ID(0/1) in the CPU DT node.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
Example 1: Dual-cluster, Quad-core per cluster. CPUs within a cluster switch
|
||||
DCVS state together.
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
CPU0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x0>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_0>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_0: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
L3_0: l3-cache {
|
||||
compatible = "cache";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
CPU1: cpu@100 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x100>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_100>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_100: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU2: cpu@200 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x200>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_200>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_200: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU3: cpu@300 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x300>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_300>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_300: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU4: cpu@400 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x400>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_400>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_400: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU5: cpu@500 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x500>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_500>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_500: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU6: cpu@600 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x600>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_600>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_600: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU7: cpu@700 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x700>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_700>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_700: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
cpufreq_hw: cpufreq@17d43000 {
|
||||
compatible = "qcom,cpufreq-hw";
|
||||
reg = <0x17d43000 0x1400>, <0x17d45800 0x1400>;
|
||||
reg-names = "freq-domain0", "freq-domain1";
|
||||
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
|
||||
clock-names = "xo", "alternate";
|
||||
|
||||
#freq-domain-cells = <1>;
|
||||
};
|
||||
}
|
||||
242
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
Normal file
242
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/cpufreq/cpufreq-qcom-hw.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. CPUFREQ
|
||||
|
||||
maintainers:
|
||||
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
|
||||
description: |
|
||||
|
||||
CPUFREQ HW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
|
||||
SoCs to manage frequency in hardware. It is capable of controlling frequency
|
||||
for multiple clusters.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: Non-secure v1 of CPUFREQ HW
|
||||
items:
|
||||
- const: qcom,cpufreq-hw-8998
|
||||
|
||||
- description: v1 of CPUFREQ HW
|
||||
items:
|
||||
- const: qcom,cpufreq-hw
|
||||
|
||||
- description: v2 of CPUFREQ HW (EPSS)
|
||||
items:
|
||||
- enum:
|
||||
- qcom,sm8250-cpufreq-epss
|
||||
- const: qcom,cpufreq-epss
|
||||
|
||||
reg: {}
|
||||
|
||||
reg-names: {}
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XO Clock
|
||||
- description: GPLL0 Clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xo
|
||||
- const: alternate
|
||||
|
||||
'#freq-domain-cells':
|
||||
const: 1
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,cpufreq-hw-8998
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 6
|
||||
items:
|
||||
- description: Frequency domain 0 register region
|
||||
- description: Operating State Manager domain 0 register region
|
||||
- description: Frequency domain 1 register region
|
||||
- description: Operating State Manager domain 1 register region
|
||||
- description: PLL ACD domain 0 register region (if ACD programming required)
|
||||
- description: PLL ACD domain 1 register region (if ACD programming required)
|
||||
|
||||
reg-names:
|
||||
minItems: 2
|
||||
maxItems: 6
|
||||
items:
|
||||
- const: "osm-domain0"
|
||||
- const: "freq-domain0"
|
||||
- const: "osm-domain1"
|
||||
- const: "freq-domain1"
|
||||
- const: "osm-acd0"
|
||||
- const: "osm-acd1"
|
||||
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- description: Frequency domain 0 register region
|
||||
- description: Frequency domain 1 register region
|
||||
- description: Frequency domain 2 register region
|
||||
reg-names:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- const: "freq-domain0"
|
||||
- const: "freq-domain1"
|
||||
- const: "freq-domain2"
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#freq-domain-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
|
||||
// Example 1: Dual-cluster, Quad-core per cluster. CPUs within a cluster
|
||||
// switch DCVS state together.
|
||||
cpus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
CPU0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x0>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_0>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_0: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
L3_0: l3-cache {
|
||||
compatible = "cache";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
CPU1: cpu@100 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x100>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_100>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_100: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU2: cpu@200 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x200>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_200>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_200: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU3: cpu@300 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x300>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_300>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
L2_300: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU4: cpu@400 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x400>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_400>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_400: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU5: cpu@500 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x500>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_500>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_500: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU6: cpu@600 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x600>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_600>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_600: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
|
||||
CPU7: cpu@700 {
|
||||
device_type = "cpu";
|
||||
compatible = "qcom,kryo385";
|
||||
reg = <0x0 0x700>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_700>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
L2_700: l2-cache {
|
||||
compatible = "cache";
|
||||
next-level-cache = <&L3_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpufreq@17d43000 {
|
||||
compatible = "qcom,cpufreq-hw";
|
||||
reg = <0x17d43000 0x1400>, <0x17d45800 0x1400>;
|
||||
reg-names = "freq-domain0", "freq-domain1";
|
||||
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
|
||||
clock-names = "xo", "alternate";
|
||||
|
||||
#freq-domain-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/boe,bf060y8m-aj0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: BOE BF060Y8M-AJ0 5.99" 1080x2160 AMOLED Panel
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
This is a 5.99" 1080x2160 16.7M Color active matrix AMOLED
|
||||
video mode panel module on MIPI-DSI 4-Lane interface, GGRB
|
||||
pixel arrangement, 63 micrometers pitch, with an active
|
||||
area of 68.04 x 136.08 millimeters.
|
||||
Each pixel is divided into red and green dots, or blue and
|
||||
green dots, and two pixels share red or blue dots which are
|
||||
arranged in vertical stripe.
|
||||
The DriverIC for this panel module is SW43404.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: boe,bf060y8m-aj0
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
vcc-supply:
|
||||
description: Core (TSP) voltage supply (2.70-3.60V)
|
||||
vddio-supply:
|
||||
description: I/O voltage supply (1.62-1.98V)
|
||||
vci-supply:
|
||||
description: DriverIC Operation supply (2.60-3.60V)
|
||||
elvdd-supply:
|
||||
description: EL Driving positive (VDD) supply (4.40-4.80V)
|
||||
elvss-supply:
|
||||
description: EL Driving negative (VSS) supply (-5.00V to -1.40V)
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "boe,bf060y8m,aj0";
|
||||
reg = <0>;
|
||||
|
||||
vcc-supply = <&disp_vcc_vreg>;
|
||||
vddio-supply = <&disp_vddio_vreg>;
|
||||
vci-supply = <&disp_vci_vreg>;
|
||||
elvdd-supply = <&disp_elvdd_vreg>;
|
||||
elvss-supply = <&disp_elvss_vreg>;
|
||||
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/novatek,nt35950.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Novatek NT35950-based display panels
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
The nt35950 IC from Novatek is a Driver IC used to drive MIPI-DSI panels,
|
||||
with Static RAM for content retention in command mode and also supports
|
||||
video mode with VESA Frame Buffer Compression or Display Stream Compression
|
||||
on single, or dual dsi port(s).
|
||||
This DDIC is also capable of upscaling an input image to the panel's native
|
||||
resolution, for example it can upscale a 1920x1080 input to 3840x2160 with
|
||||
either bilinear interpolation or pixel duplication.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- sharp,ls055d1sx04
|
||||
- const: novatek,nt35950
|
||||
description: This indicates the panel manufacturer of the panel
|
||||
that is in turn using the NT35950 panel driver. The compatible
|
||||
string determines how the NT35950 panel driver shall be configured
|
||||
to work with the indicated panel. The novatek,nt35950 compatible shall
|
||||
always be provided as a fallback.
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: phandle of gpio for reset line - This should be 8mA, gpio
|
||||
can be configured using mux, pinctrl, pinctrl-names (active high)
|
||||
|
||||
avdd-supply:
|
||||
description: positive boost supply regulator
|
||||
avee-supply:
|
||||
description: negative boost supply regulator
|
||||
dvdd-supply:
|
||||
description: regulator that supplies the digital voltage
|
||||
vddio-supply:
|
||||
description: regulator that supplies the I/O voltage
|
||||
|
||||
backlight: true
|
||||
ports: true
|
||||
reg: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
- avdd-supply
|
||||
- avee-supply
|
||||
- dvdd-supply
|
||||
- vddio-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "sharp,ls055d1sx04", "novatek,nt35950";
|
||||
reg = <0>;
|
||||
|
||||
backlight = <&pmi8998_wled>;
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
avdd-supply = <&lab>;
|
||||
avee-supply = <&ibb>;
|
||||
dvdd-supply = <&disp_dvdd_vreg>;
|
||||
vddio-supply = <&vreg_l14a_1p85>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
panel_in0: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
panel_in1: endpoint {
|
||||
remote-endpoint = <&dsi1_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -55,6 +55,10 @@ properties:
|
|||
- samsung,sofef00
|
||||
# Shangai Top Display Optoelectronics 7" TL070WSH30 1024x600 TFT LCD panel
|
||||
- tdo,tl070wsh30
|
||||
# Sony Kirin nt36672a Truly FHD+ IPS LCD panel
|
||||
- sony,kirin-nt36672a-truly
|
||||
# Sony mermaid nt36672a Tianma FHD+ IPS LCD panel
|
||||
- sony,mermaid-nt36672a-tianma
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/sony,discovery-td4322-innolux.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SONY Discovery TD4322 Innolux 6.0" 1080×1920 LCD Panel
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
|
||||
description: |+
|
||||
This panel seems to only be found in the Sony Xperia XA2 Ultra
|
||||
smartphone and we have no straightforward way of
|
||||
actually getting the correct model number,
|
||||
as no schematics are released publicly.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,discovery-td4322-innolux
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
vdd-supply:
|
||||
description: core voltage supply
|
||||
vddio-supply:
|
||||
description: vddio supply
|
||||
vsp-supply:
|
||||
description: positive voltage supply
|
||||
vsn-supply:
|
||||
description: negative voltage supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vddio-supply
|
||||
- vsp-supply
|
||||
- vsn-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
reg = <0>;
|
||||
compatible = "sony,discovery-td4322-innolux";
|
||||
|
||||
vdd-supply = <&pm8916_l8>;
|
||||
vddio-supply = <&pm8916_l6>;
|
||||
vsp-supply = <&lab>;
|
||||
vsn-supply = <&ibb>;
|
||||
reset-gpios = <&tlmm 53 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/sony,pioneer-td4322-truly.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SONY Pioneer TD4322 Truly 5.2" 1080×1920 LCD Panel
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
|
||||
description: |+
|
||||
This panel seems to only be found in the Sony Xperia XA2
|
||||
smartphone and we have no straightforward way of
|
||||
actually getting the correct model number,
|
||||
as no schematics are released publicly.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,pioneer-td4322-truly
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
vdd-supply:
|
||||
description: core voltage supply
|
||||
vddio-supply:
|
||||
description: vddio supply
|
||||
vsp-supply:
|
||||
description: positive voltage supply
|
||||
vsn-supply:
|
||||
description: negative voltage supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vddio-supply
|
||||
- vsp-supply
|
||||
- vsn-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
reg = <0>;
|
||||
compatible = "sony,pioneer-td4322-truly";
|
||||
|
||||
vdd-supply = <&pm8916_l8>;
|
||||
vddio-supply = <&pm8916_l6>;
|
||||
vsp-supply = <&lab>;
|
||||
vsn-supply = <&ibb>;
|
||||
reset-gpios = <&tlmm 53 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/sony,voyager-td4328-tianma.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SONY Voyager TD4328 Tianma 6.0" 1080×2160 LCD Panel
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
|
||||
description: |+
|
||||
This panel seems to only be found in the Sony Xperia XA2 Plus
|
||||
smartphone and we have no straightforward way of
|
||||
actually getting the correct model number,
|
||||
as no schematics are released publicly.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,voyager-td4328-tianma
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
vdd-supply:
|
||||
description: core voltage supply
|
||||
vddio-supply:
|
||||
description: vddio supply
|
||||
vsp-supply:
|
||||
description: positive voltage supply
|
||||
vsn-supply:
|
||||
description: negative voltage supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vddio-supply
|
||||
- vsp-supply
|
||||
- vsn-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
reg = <0>;
|
||||
compatible = "sony,voyager-td4328-tianma";
|
||||
|
||||
vdd-supply = <&pm8916_l8>;
|
||||
vddio-supply = <&pm8916_l6>;
|
||||
vsp-supply = <&lab>;
|
||||
vsn-supply = <&ibb>;
|
||||
reset-gpios = <&tlmm 53 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
Qualcomm Universal Peripheral (QUP) I2C controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be:
|
||||
* "qcom,i2c-qup-v1.1.1" for 8660, 8960 and 8064.
|
||||
* "qcom,i2c-qup-v2.1.1" for 8974 v1.
|
||||
* "qcom,i2c-qup-v2.2.1" for 8974 v2 and later.
|
||||
- reg: Should contain QUP register address and length.
|
||||
- interrupts: Should contain I2C interrupt.
|
||||
|
||||
- clocks: A list of phandles + clock-specifiers, one for each entry in
|
||||
clock-names.
|
||||
- clock-names: Should contain:
|
||||
* "core" for the core clock
|
||||
* "iface" for the AHB clock
|
||||
|
||||
- #address-cells: Should be <1> Address cells for i2c device address
|
||||
- #size-cells: Should be <0> as i2c addresses have no size component
|
||||
|
||||
Optional properties:
|
||||
- clock-frequency: Should specify the desired i2c bus clock frequency in Hz,
|
||||
defaults to 100kHz if omitted.
|
||||
|
||||
Child nodes should conform to i2c bus binding.
|
||||
|
||||
Example:
|
||||
|
||||
i2c@f9924000 {
|
||||
compatible = "qcom,i2c-qup-v2.2.1";
|
||||
reg = <0xf9924000 0x1000>;
|
||||
interrupts = <0 96 0>;
|
||||
|
||||
clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
|
||||
clock-frequency = <355000>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
101
Documentation/devicetree/bindings/i2c/qcom,i2c-qup.yaml
Normal file
101
Documentation/devicetree/bindings/i2c/qcom,i2c-qup.yaml
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/i2c/qcom,i2c-qup.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Universal Peripheral (QUP) I2C controller
|
||||
|
||||
maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: Binding for Qualcomm "QUP" I2C controllers
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,i2c-qup-v1.1.1
|
||||
- qcom,i2c-qup-v2.1.1
|
||||
- qcom,i2c-qup-v2.2.1
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: QUP I2C register iospace
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Core QUP I2C clock
|
||||
- description: AHB clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: iface
|
||||
|
||||
clock-frequency:
|
||||
minimum: 100000
|
||||
maximum: 1000000
|
||||
default: 100000
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: RX DMA Channel phandle
|
||||
- description: TX DMA Channel phandle
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
qcom,noise-reject-sda:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Noise rejection level for the SDA line.
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
default: 0
|
||||
|
||||
qcom,noise-reject-scl:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Noise rejection level for the SCL line.
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
default: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- clock-names
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8998.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
i2c@c175000 {
|
||||
compatible = "qcom,i2c-qup-v2.2.1";
|
||||
reg = <0x0c175000 0x600>;
|
||||
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>,
|
||||
<&gcc GCC_BLSP1_AHB_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
clock-frequency = <400000>;
|
||||
dmas = <&blsp_dma 4>, <&blsp_dma 5>;
|
||||
dma-names = "rx", "tx";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/gpio-fastmatrix-keyboard.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Fast modern GPIO-driven keyboard/keypad matrix driver binding
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
A simple common binding for matrix-connected keyboards/keypads, targeted at
|
||||
defining the keys in the scope of linux key codes since that is a stable and
|
||||
standardized interface at this time.
|
||||
This driver uses the GPIOD API in order to support setting (and reading) an
|
||||
entire array of GPIOs which is very fast (if the controller supports it) and
|
||||
a requirement to support full keyboard matrices on slow external GPIO I2C
|
||||
expanders, but also a great latency enhancement for faster GPIO controllers.
|
||||
|
||||
allOf:
|
||||
- $ref: input.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: gpio-fastmatrix-keyboard
|
||||
|
||||
label:
|
||||
description: Descriptive name of the key.
|
||||
|
||||
linux,keymap:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: |
|
||||
An array of packed 1-cell entries containing the equivalent of row,
|
||||
column and linux key-code as specified in dt-bindings/input/input.h
|
||||
|
||||
autorescan-ms:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
Activates auto-rescanning of the matrix after receiving and processing
|
||||
an event for quirky hardware that won't re-send interrupts on fast-press,
|
||||
fast-depress, or multiple keys pressed events.
|
||||
This time is expressed in milliseconds; if not specified, the feature is
|
||||
disabled.
|
||||
|
||||
col-scan-delay-us:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
Time to wait in microseconds for scan after activating a column.
|
||||
If not specified, the default is 0 (no wait).
|
||||
|
||||
debounce-delay-ms:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
Matrix button debouncing interval time in milliseconds.
|
||||
If not specified, debouncing is disabled.
|
||||
|
||||
drive-inactive-cols:
|
||||
type: boolean
|
||||
description: Keep direction of inactive columns as output
|
||||
|
||||
col-gpios:
|
||||
minItems: 2
|
||||
maxItems: 20
|
||||
|
||||
keypad,num-rows:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Number of row lines connected to the keypad controller.
|
||||
|
||||
keypad,num-columns:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Number of column lines connected to the keypad controller.
|
||||
|
||||
pinctrl-0:
|
||||
maxItems: 1
|
||||
|
||||
pinctrl-names:
|
||||
maxItems: 1
|
||||
|
||||
row-gpios:
|
||||
minItems: 2
|
||||
maxItems: 20
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- row-gpios
|
||||
- col-gpios
|
||||
- linux,keymap
|
||||
- keypad,num-rows
|
||||
- keypad,num-columns
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
gpio-keyboard {
|
||||
compatible = "gpio-fastmatrix-keyboard";
|
||||
label = "Keyboard over I2C Expander";
|
||||
row-gpios =
|
||||
<&gpioext0 0 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 1 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 2 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 3 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 4 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 5 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 6 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
|
||||
col-gpios =
|
||||
<&gpioext0 8 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 9 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 10 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 11 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 12 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 13 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 14 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 15 GPIO_ACTIVE_LOW>;
|
||||
|
||||
linux,keymap = <
|
||||
MATRIX_KEY(0, 0, KEY_F1) MATRIX_KEY(1, 0, KEY_H)
|
||||
MATRIX_KEY(2, 0, KEY_B) MATRIX_KEY(3, 0, KEY_7)
|
||||
/* ... */
|
||||
>;
|
||||
|
||||
keypad,num-rows = <8>;
|
||||
keypad,num-columns = <8>;
|
||||
};
|
||||
128
Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
Normal file
128
Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright 2020 Unisoc Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/qcom,spmi-haptics.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies Inc PMI8998 spmi haptics
|
||||
|
||||
maintainers:
|
||||
- Caleb Connolly <caleb@connolly.tech>
|
||||
|
||||
description: |
|
||||
Qualcomm SPMI haptics is a peripheral on some QTI PMICs. It supports linear resonant
|
||||
actuators and eccentric rotating mass type haptics commonly found in mobile devices.
|
||||
It supports multiple sources of wave data such as an internal buffer, direct play
|
||||
(from kernel or userspace) as well as an audio mode.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,pmi8998-haptics
|
||||
- qcom,pmi8996-haptics
|
||||
- qcom,pmi8941-haptics
|
||||
- const: qcom,spmi-haptics
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: short circuit interrupt
|
||||
- description: play interrupt
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: short
|
||||
- const: play
|
||||
|
||||
qcom,actuator-type:
|
||||
description: |
|
||||
The type of actuator attached to the hardware.
|
||||
Allowed values are,
|
||||
0 - HAP_TYPE_LRA
|
||||
1 - HAP_TYPE_ERM
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
default: 0
|
||||
|
||||
qcom,wave-shape:
|
||||
description: |
|
||||
Selects the wave shape to use.
|
||||
Allowed values are,
|
||||
0 - HAP_WAVE_SINE
|
||||
1 - HAP_WAVE_SQUARE
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
default: 0
|
||||
|
||||
qcom,play-mode:
|
||||
description: |
|
||||
Selects the play mode to use.
|
||||
Allowed values are,
|
||||
0 - HAP_PLAY_DIRECT
|
||||
1 - HAP_PLAY_BUFFER
|
||||
2 - HAP_PLAY_AUDIO
|
||||
3 - HAP_PLAY_PWM
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1, 2, 3 ]
|
||||
default: 2
|
||||
|
||||
qcom,wave-play-rate-us:
|
||||
description: |
|
||||
Wave play rate in microseconds, 1/f where f
|
||||
is the resonant frequency of the actuator.
|
||||
minimum: 0
|
||||
maximum: 20475
|
||||
|
||||
qcom,brake-pattern:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
description: |
|
||||
The brake pattern is an array of amplitudes
|
||||
used to brake the haptics. Allowed values are,
|
||||
0 - 0V
|
||||
1 - Vmax/4
|
||||
2 - Vmax/2
|
||||
3 - Vmax
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
default: [0x3, 0x3, 0x2, 0x1]
|
||||
items:
|
||||
enum: [ 0, 1, 2, 3 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- qcom,wave-play-rate-us
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/input/qcom,spmi-haptics.h>
|
||||
|
||||
pmic@3 {
|
||||
compatible = "qcom,pmi8998", "qcom,spmi-pmic";
|
||||
reg = <0x3 SPMI_USID>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmi8998_haptics: haptics@c000 {
|
||||
compatible = "qcom,pmi8998-haptics", "qcom,spmi-haptics";
|
||||
reg = <0xc000>;
|
||||
|
||||
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "short", "play";
|
||||
|
||||
qcom,wave-shape = <HAP_WAVE_SINE>;
|
||||
qcom,wave-play-rate-us = <4255>;
|
||||
qcom,play-mode = <HAP_PLAY_BUFFER>;
|
||||
qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/nt36xxx.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Novatek NT36xxx series touchscreen controller Bindings
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <kholk11@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: novatek,nt36525
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Power supply regulator for VDD pin
|
||||
|
||||
vio-supply:
|
||||
description: Power supply regulator on VDD-IO pin
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
touchscreen@62 {
|
||||
compatible = "novatek,nt36525";
|
||||
reg = <0x62>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <45 IRQ_TYPE_EDGE_RISING>;
|
||||
reset-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
158
Documentation/devicetree/bindings/interconnect/qcom,msm8998.yaml
Normal file
158
Documentation/devicetree/bindings/interconnect/qcom,msm8998.yaml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/interconnect/qcom,msm8998.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm MSM8998 Network-On-Chip interconnect
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
- Konrad Dybcio <konrad.dybcio@somainline.org>
|
||||
|
||||
description: |
|
||||
The Qualcomm MSM8998 interconnect providers support adjusting the
|
||||
bandwidth requirements between the various NoC fabrics.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,msm8998-a1noc
|
||||
- qcom,msm8998-a2noc
|
||||
- qcom,msm8998-bimc
|
||||
- qcom,msm8998-cnoc
|
||||
- qcom,msm8998-gnoc
|
||||
- qcom,msm8998-mnoc
|
||||
- qcom,msm8998-snoc
|
||||
|
||||
'#interconnect-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#interconnect-cells'
|
||||
- clock-names
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-mnoc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus Clock.
|
||||
- description: Bus A Clock.
|
||||
- description: CPU-NoC High-performance Bus Clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: bus_a
|
||||
- const: iface
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-a2noc
|
||||
- qcom,msm8998-bimc
|
||||
- qcom,msm8998-cnoc
|
||||
- qcom,msm8998-gnoc
|
||||
- qcom,msm8998-snoc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus Clock.
|
||||
- description: Bus A Clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: bus_a
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/clock/qcom,mmcc-msm8998.h>
|
||||
|
||||
bimc: interconnect@1008000 {
|
||||
compatible = "qcom,msm8998-bimc";
|
||||
reg = <0x01008000 0x78000>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
|
||||
<&rpmcc RPM_SMD_BIMC_A_CLK>;
|
||||
};
|
||||
|
||||
cnoc: interconnect@1500000 {
|
||||
compatible = "qcom,msm8998-cnoc";
|
||||
reg = <0x01500000 0x10000>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_CNOC_CLK>,
|
||||
<&rpmcc RPM_SMD_CNOC_A_CLK>;
|
||||
};
|
||||
|
||||
snoc: interconnect@1625000 {
|
||||
compatible = "qcom,msm8998-snoc";
|
||||
reg = <0x01625000 0x6100>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
|
||||
<&rpmcc RPM_SMD_SNOC_A_CLK>;
|
||||
};
|
||||
|
||||
a1noc: interconnect@1669000 {
|
||||
compatible = "qcom,msm8998-a1noc";
|
||||
reg = <0x01669000 0x5020>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_AGGR1_NOC_CLK>,
|
||||
<&rpmcc RPM_SMD_AGGR1_NOC_A_CLK>;
|
||||
};
|
||||
|
||||
a2noc: interconnect@1705000 {
|
||||
compatible = "qcom,msm8998-a2noc";
|
||||
reg = <0x01705000 0xa090>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>,
|
||||
<&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>;
|
||||
};
|
||||
|
||||
mnoc: interconnect@1744000 {
|
||||
compatible = "qcom,msm8998-mnoc";
|
||||
reg = <0x01744000 0xb010>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a", "iface";
|
||||
clocks = <&rpmcc RPM_SMD_MMAXI_CLK>,
|
||||
<&rpmcc RPM_SMD_MMAXI_A_CLK>,
|
||||
<&mmcc AHB_CLK_SRC>;
|
||||
};
|
||||
|
||||
gnoc: interconnect@17900000 {
|
||||
compatible = "qcom,msm8998-gnoc";
|
||||
reg = <0x17900000 0xe000>;
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&xo_board>, <&xo_board>;
|
||||
};
|
||||
158
Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
Normal file
158
Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/leds-qcom-lpg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Light Pulse Generator
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: >
|
||||
The Qualcomm Light Pulse Generator consists of three different hardware blocks;
|
||||
a ramp generator with lookup table, the light pulse generator and a three
|
||||
channel current sink. These blocks are found in a wide range of Qualcomm PMICs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pm8150b-lpg
|
||||
- qcom,pm8150l-lpg
|
||||
- qcom,pm8916-pwm
|
||||
- qcom,pm8941-lpg
|
||||
- qcom,pm8994-lpg
|
||||
- qcom,pmi8994-lpg
|
||||
- qcom,pmi8998-lpg
|
||||
|
||||
"#pwm-cells":
|
||||
const: 2
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
qcom,power-source:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
power-source used to drive the output, as defined in the datasheet.
|
||||
Should be specified if the TRILED block is present
|
||||
|
||||
qcom,dtest:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: >
|
||||
A list of integer pairs, where each pair represent the dtest line the
|
||||
particular channel should be connected to and the flags denoting how the
|
||||
value should be outputed, as defined in the datasheet. The number of
|
||||
pairs should be the same as the number of channels.
|
||||
|
||||
multi-led:
|
||||
type: object
|
||||
$ref: leds-class-multicolor.yaml#
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
"^led@[0-9a-f]$":
|
||||
type: object
|
||||
$ref: common.yaml#
|
||||
|
||||
patternProperties:
|
||||
"^led@[0-9a-f]$":
|
||||
type: object
|
||||
$ref: common.yaml#
|
||||
|
||||
properties:
|
||||
reg: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
lpg {
|
||||
compatible = "qcom,pmi8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
qcom,power-source = <1>;
|
||||
|
||||
qcom,dtest = <0 0
|
||||
0 0
|
||||
0 0
|
||||
4 1>;
|
||||
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
label = "green:user1";
|
||||
};
|
||||
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
label = "green:user0";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
label = "green:user2";
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
label = "green:user3";
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
lpg {
|
||||
compatible = "qcom,pmi8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
qcom,power-source = <1>;
|
||||
|
||||
multi-led {
|
||||
color = <LED_COLOR_ID_MULTI>;
|
||||
label = "rgb:notification";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
lpg {
|
||||
compatible = "qcom,pm8916-pwm";
|
||||
#pwm-cells = <2>;
|
||||
};
|
||||
...
|
||||
112
Documentation/devicetree/bindings/media/i2c/sony,imx300.yaml
Normal file
112
Documentation/devicetree/bindings/media/i2c/sony,imx300.yaml
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/sony,imx300.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sony 1/2.3-Inch 25Mpixel Stacked CMOS Digital Image Sensor
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |-
|
||||
The Sony IMX300 is a 1/2.3-inch Stacked CMOS (Exmor-RS) digital image
|
||||
sensor with a pixel size of 1.08um and an active array size of
|
||||
5948H x 4140V. It is programmable through I2C interface at address 0x10.
|
||||
Image data is sent through MIPI CSI-2, which is configured as either 2 or
|
||||
4 data lanes.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,imx300
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
vdig-supply:
|
||||
description:
|
||||
Digital I/O voltage supply, 1.15-1.20 volts
|
||||
|
||||
vana-supply:
|
||||
description:
|
||||
Analog voltage supply, 2.2 volts
|
||||
|
||||
vddl-supply:
|
||||
description:
|
||||
Digital core voltage supply, 1.8 volts
|
||||
|
||||
reset-gpios:
|
||||
description: |-
|
||||
Reference to the GPIO connected to the xclr pin, if any.
|
||||
Must be released (set high) after all supplies are applied.
|
||||
|
||||
# See ../video-interfaces.txt for more details
|
||||
port:
|
||||
type: object
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
description: |-
|
||||
The driver only supports four-lane operation.
|
||||
items:
|
||||
- const: 0
|
||||
- const: 1
|
||||
- const: 2
|
||||
- const: 3
|
||||
|
||||
clock-noncontinuous: true
|
||||
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description:
|
||||
Allowed data bus frequencies. The driver currently needs
|
||||
to switch between 780000000 and 480000000 Hz in order to
|
||||
guarantee functionality of all modes.
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- vana-supply
|
||||
- vdig-supply
|
||||
- vddl-supply
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
imx300: sensor@10 {
|
||||
compatible = "sony,imx300";
|
||||
reg = <0x10>;
|
||||
clocks = <&imx300_xclk>;
|
||||
vana-supply = <&imx300_vana>; /* 2.2v */
|
||||
vdig-supply = <&imx300_vdig>; /* 1.2v */
|
||||
vddl-supply = <&imx300_vddl>; /* 1.8v */
|
||||
|
||||
port {
|
||||
imx300_0: endpoint {
|
||||
remote-endpoint = <&csi1_ep>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
clock-noncontinuous;
|
||||
link-frequencies = /bits/ 64 <780000000 480000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
164
Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml
Normal file
164
Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Venus video encode and decode accelerators
|
||||
|
||||
maintainers:
|
||||
- Stanimir Varbanov <stanimir.varbanov@linaro.org>
|
||||
|
||||
description: |
|
||||
The Venus IP is a video encode and decode accelerator present
|
||||
on Qualcomm platforms
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sdm660-venus
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 5
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: iface
|
||||
- const: bus
|
||||
- const: bus_throttle
|
||||
- const: vcodec0_core
|
||||
|
||||
interconnects:
|
||||
maxItems: 2
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: video-mem
|
||||
- const: cpu-cfg
|
||||
|
||||
iommus:
|
||||
maxItems: 20
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
minItems: 3
|
||||
|
||||
power-domain-names:
|
||||
items:
|
||||
- const: cx
|
||||
- const: vcodec0
|
||||
- const: venus
|
||||
|
||||
video-decoder:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: venus-decoder
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
video-encoder:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: venus-encoder
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
video-firmware:
|
||||
type: object
|
||||
|
||||
description: |
|
||||
Firmware subnode is needed when the platform does not
|
||||
have TrustZone.
|
||||
|
||||
properties:
|
||||
iommus:
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- iommus
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- power-domains
|
||||
- power-domain-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- iommus
|
||||
- memory-region
|
||||
- video-decoder
|
||||
- video-encoder
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/qcom,mmcc-sdm660.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
video-codec@cc00000 {
|
||||
compatible = "qcom,sdm660-venus";
|
||||
reg = <0x0cc00000 0xff000>;
|
||||
interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
|
||||
power-domains = <&rpmpd SDM660_VDDCX>,
|
||||
<&mmcc VENUS_CORE0_GDSC>,
|
||||
<&mmcc VENUS_GDSC>;
|
||||
power-domain-names = "cx", "vcodec0", "venus";
|
||||
clocks = <&mmcc VIDEO_CORE_CLK>,
|
||||
<&mmcc VIDEO_AHB_CLK>,
|
||||
<&mmcc VIDEO_AXI_CLK>,
|
||||
<&mmcc THROTTLE_VIDEO_AXI_CLK>,
|
||||
<&mmcc VIDEO_SUBCORE0_CLK>;
|
||||
clock-names = "core", "iface", "bus", "bus_throttle",
|
||||
"vcodec0_core";
|
||||
iommus = <&mmss_smmu 0x400>,
|
||||
<&mmss_smmu 0x401>,
|
||||
<&mmss_smmu 0x40a>,
|
||||
<&mmss_smmu 0x407>,
|
||||
<&mmss_smmu 0x40e>,
|
||||
<&mmss_smmu 0x40f>,
|
||||
<&mmss_smmu 0x408>,
|
||||
<&mmss_smmu 0x409>,
|
||||
<&mmss_smmu 0x40b>,
|
||||
<&mmss_smmu 0x40c>,
|
||||
<&mmss_smmu 0x40d>,
|
||||
<&mmss_smmu 0x410>,
|
||||
<&mmss_smmu 0x421>,
|
||||
<&mmss_smmu 0x428>,
|
||||
<&mmss_smmu 0x429>,
|
||||
<&mmss_smmu 0x42b>,
|
||||
<&mmss_smmu 0x42c>,
|
||||
<&mmss_smmu 0x42d>,
|
||||
<&mmss_smmu 0x411>,
|
||||
<&mmss_smmu 0x431>;
|
||||
memory-region = <&venus_region>;
|
||||
|
||||
video-decoder {
|
||||
compatible = "venus-decoder";
|
||||
};
|
||||
|
||||
video-encoder {
|
||||
compatible = "venus-encoder";
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/awinic,aw9523-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Awinic AW9523/AW9523B I2C GPIO Expander
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
The Awinic AW9523/AW9523B I2C GPIO Expander featuring 16 multi-function
|
||||
I/O, 256 steps PWM mode and interrupt support.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: awinic,aw9523-pinctrl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#gpio-cells':
|
||||
description: |
|
||||
Specifying the pin number and flags, as defined in
|
||||
include/dt-bindings/gpio/gpio.h
|
||||
const: 2
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description: Specifies the INTN pin IRQ.
|
||||
|
||||
'#interrupt-cells':
|
||||
description:
|
||||
Specifies the PIN numbers and Flags, as defined in defined in
|
||||
include/dt-bindings/interrupt-controller/irq.h
|
||||
const: 2
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
#PIN CONFIGURATION NODES
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
type: object
|
||||
description:
|
||||
Pinctrl node's client devices use subnodes for desired pin configuration.
|
||||
Client device subnodes use below standard properties.
|
||||
$ref: "/schemas/pinctrl/pincfg-node.yaml"
|
||||
|
||||
properties:
|
||||
pins:
|
||||
description:
|
||||
List of gpio pins affected by the properties specified in
|
||||
this subnode.
|
||||
items:
|
||||
pattern: "^gpio([0-9]|1[0-5])$"
|
||||
minItems: 1
|
||||
maxItems: 16
|
||||
|
||||
function:
|
||||
description:
|
||||
Specify the alternative function to be configured for the
|
||||
specified pins.
|
||||
|
||||
enum: [ gpio, pwm ]
|
||||
|
||||
bias-disable: true
|
||||
bias-pull-down: true
|
||||
bias-pull-up: true
|
||||
drive-open-drain: true
|
||||
drive-push-pull: true
|
||||
input-enable: true
|
||||
input-disable: true
|
||||
output-high: true
|
||||
output-low: true
|
||||
|
||||
required:
|
||||
- pins
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- gpio-controller
|
||||
- '#gpio-cells'
|
||||
- gpio-ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Example configuration to drive pins for a keyboard matrix
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
aw9523: gpio-expander@58 {
|
||||
compatible = "awinic,aw9523-pinctrl";
|
||||
reg = <0x58>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <50 IRQ_TYPE_EDGE_FALLING>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&tlmm 0 0 16>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reset-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
keyboard-matrix-col-pins {
|
||||
pins = "gpio8", "gpio9", "gpio10", "gpio11",
|
||||
"gpio12", "gpio13", "gpio14", "gpio15";
|
||||
function = "gpio";
|
||||
input-disable;
|
||||
output-low;
|
||||
};
|
||||
|
||||
keyboard-matrix-row-pins {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
||||
"gpio4", "gpio5", "gpio6", "gpio7";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
drive-open-drain;
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -1,130 +1 @@
|
|||
QCOM CPR (Core Power Reduction)
|
||||
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests adjustments to the voltage to save power
|
||||
and meet silicon characteristic requirements.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: should be "qcom,qcs404-cpr", "qcom,cpr" for qcs404
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: base address and size of the rbcpr register region
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: should specify the CPR interrupt
|
||||
|
||||
- clocks:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: phandle to the reference clock
|
||||
|
||||
- clock-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: must be "ref"
|
||||
|
||||
- vdd-apc-supply:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to the vdd-apc-supply regulator
|
||||
|
||||
- #power-domain-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: should be 0
|
||||
|
||||
- operating-points-v2:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: A phandle to the OPP table containing the
|
||||
performance states supported by the CPR
|
||||
power domain
|
||||
|
||||
- acc-syscon:
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
Definition: phandle to syscon for writing ACC settings
|
||||
|
||||
- nvmem-cells:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to nvmem cells containing the data
|
||||
that makes up a fuse corner, for each fuse corner.
|
||||
As well as the CPR fuse revision.
|
||||
|
||||
- nvmem-cell-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: should be "cpr_quotient_offset1", "cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3", "cpr_init_voltage1",
|
||||
"cpr_init_voltage2", "cpr_init_voltage3", "cpr_quotient1",
|
||||
"cpr_quotient2", "cpr_quotient3", "cpr_ring_osc1",
|
||||
"cpr_ring_osc2", "cpr_ring_osc3", "cpr_fuse_revision"
|
||||
for qcs404.
|
||||
|
||||
Example:
|
||||
|
||||
cpr_opp_table: cpr-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cpr_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cpr_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cpr_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
power-controller@b018000 {
|
||||
compatible = "qcom,qcs404-cpr", "qcom,cpr";
|
||||
reg = <0x0b018000 0x1000>;
|
||||
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xo_board>;
|
||||
clock-names = "ref";
|
||||
vdd-apc-supply = <&pms405_s3>;
|
||||
#power-domain-cells = <0>;
|
||||
operating-points-v2 = <&cpr_opp_table>;
|
||||
acc-syscon = <&tcsr>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_quot_offset1>,
|
||||
<&cpr_efuse_quot_offset2>,
|
||||
<&cpr_efuse_quot_offset3>,
|
||||
<&cpr_efuse_init_voltage1>,
|
||||
<&cpr_efuse_init_voltage2>,
|
||||
<&cpr_efuse_init_voltage3>,
|
||||
<&cpr_efuse_quot1>,
|
||||
<&cpr_efuse_quot2>,
|
||||
<&cpr_efuse_quot3>,
|
||||
<&cpr_efuse_ring1>,
|
||||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr_quotient_offset1",
|
||||
"cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3",
|
||||
"cpr_init_voltage1",
|
||||
"cpr_init_voltage2",
|
||||
"cpr_init_voltage3",
|
||||
"cpr_quotient1",
|
||||
"cpr_quotient2",
|
||||
"cpr_quotient3",
|
||||
"cpr_ring_osc1",
|
||||
"cpr_ring_osc2",
|
||||
"cpr_ring_osc3",
|
||||
"cpr_fuse_revision";
|
||||
};
|
||||
This file has been moved to ../../soc/qcom/qcom,cpr.yaml
|
||||
|
|
|
|||
167
Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
Normal file
167
Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/soc/qcom/qcom,cpr.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Core Power Reduction (CPR)
|
||||
|
||||
description: |
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests adjustments to the voltage to save power
|
||||
and meet silicon characteristic requirements.
|
||||
|
||||
maintainers:
|
||||
- Niklas Cassel <nks@flawful.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,qcs404-cpr
|
||||
- const: qcom,cpr
|
||||
|
||||
reg:
|
||||
description: Base address and size of the RBCPR register region
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: CPR reference clock
|
||||
|
||||
vdd-apc-supply:
|
||||
description: Autonomous Phase Control (APC) power supply
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 0
|
||||
|
||||
acc-syscon:
|
||||
description: phandle to syscon for writing ACC settings
|
||||
|
||||
nvmem-cells:
|
||||
minItems: 9
|
||||
maxItems: 32
|
||||
description: Cells containing the fuse corners and revision data
|
||||
|
||||
nvmem-cell-names:
|
||||
minItems: 9
|
||||
maxItems: 32
|
||||
|
||||
operating-points-v2: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clock-names
|
||||
- clocks
|
||||
- vdd-apc-supply
|
||||
- "#power-domain-cells"
|
||||
- nvmem-cells
|
||||
- nvmem-cell-names
|
||||
- operating-points-v2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@100 {
|
||||
compatible = "arm,cortex-a53";
|
||||
device_type = "cpu";
|
||||
reg = <0x100>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
power-domains = <&cpr>;
|
||||
power-domain-names = "cpr";
|
||||
};
|
||||
};
|
||||
|
||||
cpu_opp_table: cpu-opp-table {
|
||||
compatible = "operating-points-v2-kryo-cpu";
|
||||
opp-shared;
|
||||
|
||||
opp-1094400000 {
|
||||
opp-hz = /bits/ 64 <1094400000>;
|
||||
required-opps = <&cpr_opp1>;
|
||||
};
|
||||
opp-1248000000 {
|
||||
opp-hz = /bits/ 64 <1248000000>;
|
||||
required-opps = <&cpr_opp2>;
|
||||
};
|
||||
opp-1401600000 {
|
||||
opp-hz = /bits/ 64 <1401600000>;
|
||||
required-opps = <&cpr_opp3>;
|
||||
};
|
||||
};
|
||||
|
||||
cpr_opp_table: cpr-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cpr_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cpr_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cpr_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
power-controller@b018000 {
|
||||
compatible = "qcom,qcs404-cpr", "qcom,cpr";
|
||||
reg = <0x0b018000 0x1000>;
|
||||
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xo_board>;
|
||||
clock-names = "ref";
|
||||
vdd-apc-supply = <&pms405_s3>;
|
||||
#power-domain-cells = <0>;
|
||||
operating-points-v2 = <&cpr_opp_table>;
|
||||
acc-syscon = <&tcsr>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_quot_offset1>,
|
||||
<&cpr_efuse_quot_offset2>,
|
||||
<&cpr_efuse_quot_offset3>,
|
||||
<&cpr_efuse_init_voltage1>,
|
||||
<&cpr_efuse_init_voltage2>,
|
||||
<&cpr_efuse_init_voltage3>,
|
||||
<&cpr_efuse_quot1>,
|
||||
<&cpr_efuse_quot2>,
|
||||
<&cpr_efuse_quot3>,
|
||||
<&cpr_efuse_ring1>,
|
||||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr0_quotient_offset1",
|
||||
"cpr0_quotient_offset2",
|
||||
"cpr0_quotient_offset3",
|
||||
"cpr0_init_voltage1",
|
||||
"cpr0_init_voltage2",
|
||||
"cpr0_init_voltage3",
|
||||
"cpr0_quotient1",
|
||||
"cpr0_quotient2",
|
||||
"cpr0_quotient3",
|
||||
"cpr0_ring_osc1",
|
||||
"cpr0_ring_osc2",
|
||||
"cpr0_ring_osc3",
|
||||
"cpr0_fuse_revision";
|
||||
};
|
||||
...
|
||||
241
Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
Normal file
241
Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/soc/qcom/qcom,cpr3.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Core Power Reduction v3/v4/Hardened (CPR3, CPR4, CPRh)
|
||||
|
||||
description: |
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests or, in the CPR-Hardened case performs,
|
||||
adjustments to the voltage to save power and meet silicon characteristic
|
||||
requirements.
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: CPRv3 controller
|
||||
items:
|
||||
- const: qcom,cpr3
|
||||
- description: CPRv4 controller
|
||||
items:
|
||||
- const: qcom,cpr4
|
||||
- description: CPRv4-Hardened controller
|
||||
items:
|
||||
- enum:
|
||||
- qcom,msm8998-cprh
|
||||
- qcom,sdm630-cprh
|
||||
- const: qcom,cprh
|
||||
|
||||
reg:
|
||||
description: Base address and size of the CPR controller(s)
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: "ref"
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: CPR reference clock
|
||||
|
||||
vdd-supply:
|
||||
description: Autonomous Phase Control (APC) or other power supply
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 1
|
||||
|
||||
acc-syscon:
|
||||
description: phandle to syscon for writing ACC settings
|
||||
|
||||
nvmem-cells:
|
||||
description: Cells containing the fuse corners and revision data
|
||||
minItems: 10
|
||||
maxItems: 32
|
||||
|
||||
nvmem-cell-names:
|
||||
minItems: 10
|
||||
maxItems: 32
|
||||
|
||||
operating-points-v2: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clock-names
|
||||
- clocks
|
||||
- "#power-domain-cells"
|
||||
- nvmem-cells
|
||||
- nvmem-cell-names
|
||||
- operating-points-v2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8998.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
cpus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "qcom,kryo280";
|
||||
device_type = "cpu";
|
||||
reg = <0x0 0x0>;
|
||||
operating-points-v2 = <&cpu_gold_opp_table>;
|
||||
power-domains = <&apc_cprh 0>;
|
||||
power-domain-names = "cprh";
|
||||
};
|
||||
|
||||
cpu@100 {
|
||||
compatible = "qcom,kryo280";
|
||||
device_type = "cpu";
|
||||
reg = <0x0 0x0>;
|
||||
operating-points-v2 = <&cpu_silver_opp_table>;
|
||||
power-domains = <&apc_cprh 1>;
|
||||
power-domain-names = "cprh";
|
||||
};
|
||||
};
|
||||
|
||||
cpu_silver_opp_table: cpu-silver-opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-1843200000 {
|
||||
opp-hz = /bits/ 64 <1843200000>;
|
||||
required-opps = <&cprh_opp3>;
|
||||
};
|
||||
opp-1094400000 {
|
||||
opp-hz = /bits/ 64 <1094400000>;
|
||||
required-opps = <&cprh_opp2>;
|
||||
};
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&cprh_opp1>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_gold_opp_table: cpu-gold-opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-2208000000 {
|
||||
opp-hz = /bits/ 64 <2208000000>;
|
||||
required-opps = <&cprh_opp3>;
|
||||
};
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
required-opps = <&cprh_opp2>;
|
||||
};
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&cprh_opp1>;
|
||||
};
|
||||
};
|
||||
|
||||
cprh_opp_table: cpr-hardened-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cprh_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cprh_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cprh_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <2 3>;
|
||||
};
|
||||
};
|
||||
|
||||
apc_cprh: power-controller@179c8000 {
|
||||
compatible = "qcom,msm8998-cprh", "qcom,cprh";
|
||||
reg = <0x0179c8000 0x4000>, <0x0179c4000 0x4000>;
|
||||
clocks = <&gcc GCC_HMSS_RBCPR_CLK>;
|
||||
clock-names = "ref";
|
||||
|
||||
#power-domain-cells = <1>;
|
||||
operating-points-v2 = <&cprh_opp_table>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_speedbin>,
|
||||
<&cpr_fuse_revision>,
|
||||
<&cpr_quot0_pwrcl>,
|
||||
<&cpr_quot1_pwrcl>,
|
||||
<&cpr_quot2_pwrcl>,
|
||||
<&cpr_quot3_pwrcl>,
|
||||
<&cpr_quot_offset1_pwrcl>,
|
||||
<&cpr_quot_offset2_pwrcl>,
|
||||
<&cpr_quot_offset3_pwrcl>,
|
||||
<&cpr_init_voltage0_pwrcl>,
|
||||
<&cpr_init_voltage1_pwrcl>,
|
||||
<&cpr_init_voltage2_pwrcl>,
|
||||
<&cpr_init_voltage3_pwrcl>,
|
||||
<&cpr_ro_sel0_pwrcl>,
|
||||
<&cpr_ro_sel1_pwrcl>,
|
||||
<&cpr_ro_sel2_pwrcl>,
|
||||
<&cpr_ro_sel3_pwrcl>,
|
||||
<&cpr_quot0_perfcl>,
|
||||
<&cpr_quot1_perfcl>,
|
||||
<&cpr_quot2_perfcl>,
|
||||
<&cpr_quot3_perfcl>,
|
||||
<&cpr_quot_offset1_perfcl>,
|
||||
<&cpr_quot_offset2_perfcl>,
|
||||
<&cpr_quot_offset3_perfcl>,
|
||||
<&cpr_init_voltage0_perfcl>,
|
||||
<&cpr_init_voltage1_perfcl>,
|
||||
<&cpr_init_voltage2_perfcl>,
|
||||
<&cpr_init_voltage3_perfcl>,
|
||||
<&cpr_ro_sel0_perfcl>,
|
||||
<&cpr_ro_sel1_perfcl>,
|
||||
<&cpr_ro_sel2_perfcl>,
|
||||
<&cpr_ro_sel3_perfcl>;
|
||||
|
||||
nvmem-cell-names = "cpr_speed_bin",
|
||||
"cpr_fuse_revision",
|
||||
"cpr0_quotient1",
|
||||
"cpr0_quotient2",
|
||||
"cpr0_quotient3",
|
||||
"cpr0_quotient4",
|
||||
"cpr0_quotient_offset2",
|
||||
"cpr0_quotient_offset3",
|
||||
"cpr0_quotient_offset4",
|
||||
"cpr0_init_voltage1",
|
||||
"cpr0_init_voltage2",
|
||||
"cpr0_init_voltage3",
|
||||
"cpr0_init_voltage4",
|
||||
"cpr0_ring_osc1",
|
||||
"cpr0_ring_osc2",
|
||||
"cpr0_ring_osc3",
|
||||
"cpr0_ring_osc4",
|
||||
"cpr1_quotient1",
|
||||
"cpr1_quotient2",
|
||||
"cpr1_quotient3",
|
||||
"cpr1_quotient4",
|
||||
"cpr1_quotient_offset2",
|
||||
"cpr1_quotient_offset3",
|
||||
"cpr1_quotient_offset4",
|
||||
"cpr1_init_voltage1",
|
||||
"cpr1_init_voltage2",
|
||||
"cpr1_init_voltage3",
|
||||
"cpr1_init_voltage4",
|
||||
"cpr1_ring_osc1",
|
||||
"cpr1_ring_osc2",
|
||||
"cpr1_ring_osc3",
|
||||
"cpr1_ring_osc4";
|
||||
};
|
||||
...
|
||||
80
Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml
Normal file
80
Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/soc/qcom/qcom,spm.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Subsystem Power Manager binding
|
||||
|
||||
maintainers:
|
||||
- Andy Gross <agross@kernel.org>
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: |
|
||||
This binding describes the Qualcomm Subsystem Power Manager, used to control
|
||||
the peripheral logic surrounding the application cores in Qualcomm platforms.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,sdm660-gold-saw2-v4.1-l2
|
||||
- qcom,sdm660-silver-saw2-v4.1-l2
|
||||
- qcom,msm8998-gold-saw2-v4.1-l2
|
||||
- qcom,msm8998-silver-saw2-v4.1-l2
|
||||
- qcom,msm8226-saw2-v2.1-cpu
|
||||
- qcom,msm8974-saw2-v2.1-cpu
|
||||
- qcom,apq8084-saw2-v2.1-cpu
|
||||
- qcom,apq8064-saw2-v1.1-cpu
|
||||
- const: qcom,saw2
|
||||
|
||||
reg:
|
||||
description: Base address and size of the SPM register region
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
/* Example 1: SoC using SAW2 and kpss-acc-v2 CPUIdle */
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "qcom,kryo";
|
||||
device_type = "cpu";
|
||||
enable-method = "qcom,kpss-acc-v2";
|
||||
qcom,saw = <&saw0>;
|
||||
reg = <0x0>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
saw0: power-manager@f9089000 {
|
||||
compatible = "qcom,msm8974-saw2-v2.1-cpu", "qcom,saw2";
|
||||
reg = <0xf9089000 0x1000>;
|
||||
};
|
||||
|
||||
- |
|
||||
|
||||
/*
|
||||
* Example 2: New-gen multi cluster SoC using SAW only for L2;
|
||||
* This does not require any cpuidle driver, nor any cpu phandle.
|
||||
*/
|
||||
power-manager@17812000 {
|
||||
compatible = "qcom,msm8998-gold-saw2-v4.1-l2", "qcom,saw2";
|
||||
reg = <0x17812000 0x1000>;
|
||||
};
|
||||
|
||||
power-manager@17912000 {
|
||||
compatible = "qcom,msm8998-silver-saw2-v4.1-l2", "qcom,saw2";
|
||||
reg = <0x17912000 0x1000>;
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -812,6 +812,8 @@ patternProperties:
|
|||
description: Nokia
|
||||
"^nordic,.*":
|
||||
description: Nordic Semiconductor
|
||||
"^novatek,.*":
|
||||
description: Novatek Microelectronics Corp.
|
||||
"^novtech,.*":
|
||||
description: NovTech, Inc.
|
||||
"^nutsboard,.*":
|
||||
|
|
@ -836,6 +838,8 @@ patternProperties:
|
|||
description: OLIMEX Ltd.
|
||||
"^olpc,.*":
|
||||
description: One Laptop Per Child
|
||||
"^oneplus,.*":
|
||||
description: OnePlus Technology (Shenzhen) Co., Ltd.
|
||||
"^onion,.*":
|
||||
description: Onion Corporation
|
||||
"^onnn,.*":
|
||||
|
|
|
|||
15
MAINTAINERS
15
MAINTAINERS
|
|
@ -15490,9 +15490,15 @@ M: Niklas Cassel <nks@flawful.org>
|
|||
L: linux-pm@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
|
||||
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
|
||||
F: drivers/soc/qcom/cpr.c
|
||||
|
||||
QUALCOMM CORE POWER REDUCTION v3/v4/Hardened AVS DRIVER
|
||||
M: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
|
||||
F: drivers/soc/qcom/cpr3.c
|
||||
|
||||
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
|
||||
M: Ilia Lin <ilia.lin@kernel.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
|
|
@ -17458,6 +17464,13 @@ T: git git://linuxtv.org/media_tree.git
|
|||
F: Documentation/devicetree/bindings/media/i2c/imx290.txt
|
||||
F: drivers/media/i2c/imx290.c
|
||||
|
||||
SONY IMX300 SENSOR DRIVER
|
||||
M: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/media/i2c/sony,imx300.yaml
|
||||
F: drivers/media/i2c/imx300.c
|
||||
|
||||
SONY IMX319 SENSOR DRIVER
|
||||
M: Bingbu Cao <bingbu.cao@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
|
|
|
|||
|
|
@ -34,11 +34,15 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-dora.dtb
|
|||
dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-kagura.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-keyaki.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-asus-novago-tp370ql.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-fxtec-pro1.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-hp-envy-x2.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-lenovo-miix-630.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-mtp.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-oneplus-cheeseburger.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-oneplus-dumpling.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-lilac.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-maple.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb
|
||||
|
|
@ -74,6 +78,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-pioneer.dtb
|
|||
dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-voyager.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += sdm636-sony-xperia-ganges-mermaid.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += sdm660-xiaomi-lavender.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += sdm660-xiaomi-platina.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r1.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r3.dtb
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "pmi8994.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
|
||||
#include <dt-bindings/sound/qcom,q6afe.h>
|
||||
#include <dt-bindings/sound/qcom,q6asm.h>
|
||||
|
|
@ -695,6 +696,54 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8994_lpg {
|
||||
qcom,power-source = <1>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pmi8994_mpp2_userled4>;
|
||||
|
||||
qcom,dtest = <0 0
|
||||
0 0
|
||||
0 0
|
||||
4 1>;
|
||||
|
||||
status = "okay";
|
||||
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
label = "green:user1";
|
||||
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
label = "green:user0";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
label = "green:user2";
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
label = "green:user3";
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8994_mpps {
|
||||
pmi8994_mpp2_userled4: mpp2-userled4-state {
|
||||
pins = "mpp2";
|
||||
function = "sink";
|
||||
|
||||
output-low;
|
||||
qcom,dtest = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8994_spmi_regulators {
|
||||
vdd_gfx: s2@1700 {
|
||||
reg = <0x1700 0x100>;
|
||||
|
|
|
|||
682
arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
Normal file
682
arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
Normal file
|
|
@ -0,0 +1,682 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Copyright (c) 2021, AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "msm8998-mtp.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
|
||||
|
||||
/ {
|
||||
model = "F(x)tec Pro1 (QX1000)";
|
||||
compatible = "fxtec,pro1", "qcom,msm8998";
|
||||
qcom,board-id = <0x02000b 0x10>;
|
||||
|
||||
/* This part enables graphical output via bootloader-enabled display */
|
||||
chosen {
|
||||
bootargs = "earlycon=tty0 console=tty0 clk_ignore_unused";
|
||||
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
cont_splash_mem: cont-splash-region@9d400000 {
|
||||
reg = <0x0 0x9d400000 0x0 0x2000000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
zap_shader_region: gpu@f6400000 {
|
||||
compatible = "shared-dma-pool";
|
||||
reg = <0x0 0xf6400000 0x0 0x2000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ramoops@ffc00000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0xffc00000 0x0 0x100000>;
|
||||
record-size = <0x10000>;
|
||||
console-size = <0x60000>;
|
||||
ftrace-size = <0x10000>;
|
||||
pmsg-size = <0x20000>;
|
||||
ecc-size = <16>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
keyboard-leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
backlight {
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
default-state = "off";
|
||||
function = LED_FUNCTION_KBD_BACKLIGHT;
|
||||
gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>;
|
||||
label = "white:kbd_backlight";
|
||||
retain-state-suspended;
|
||||
};
|
||||
|
||||
caps-lock {
|
||||
color = <LED_COLOR_ID_YELLOW>;
|
||||
default-state = "off";
|
||||
function = LED_FUNCTION_CAPSLOCK;
|
||||
gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>;
|
||||
label = "yellow:capslock";
|
||||
linux,default-trigger = "kbd-capslock";
|
||||
};
|
||||
};
|
||||
|
||||
gpio_keyboard: gpio-keyboard {
|
||||
compatible = "gpio-fastmatrix-keyboard";
|
||||
label = "F(x)Tec Pro1 Hardware Keyboard";
|
||||
row-gpios =
|
||||
<&gpioext0 0 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 1 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 2 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 3 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 4 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 5 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 6 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
|
||||
<&gpioext0 7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
|
||||
|
||||
col-gpios =
|
||||
<&gpioext0 8 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 9 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 10 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 11 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 12 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 13 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 14 GPIO_ACTIVE_LOW>,
|
||||
<&gpioext0 15 GPIO_ACTIVE_LOW>;
|
||||
keypad,num-rows = <8>;
|
||||
keypad,num-columns = <8>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&keyboard_pins_col>, <&keyboard_pins_row>;
|
||||
|
||||
autorescan-ms = <5>;
|
||||
debounce-delay-ms = <1>;
|
||||
col-scan-delay-us = <1500>;
|
||||
};
|
||||
|
||||
gpio_kb_extra_keys {
|
||||
compatible = "gpio-keys";
|
||||
input-name = "extra-kb-keys";
|
||||
label = "Keyboard extra keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio_kb_extra_active>;
|
||||
|
||||
home {
|
||||
label = "Home";
|
||||
gpios = <&tlmm 21 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <172>;
|
||||
debounce-interval = <15>;
|
||||
linux,can-disable;
|
||||
};
|
||||
|
||||
super_l {
|
||||
label = "Super Left";
|
||||
gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_FN>;
|
||||
debounce-interval = <15>;
|
||||
linux,can-disable;
|
||||
};
|
||||
|
||||
super_r {
|
||||
label = "Super Right";
|
||||
gpios = <&tlmm 33 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_FN>;
|
||||
debounce-interval = <15>;
|
||||
linux,can-disable;
|
||||
};
|
||||
|
||||
shift {
|
||||
label = "Shift";
|
||||
gpios = <&tlmm 114 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RIGHTSHIFT>;
|
||||
debounce-interval = <15>;
|
||||
linux,can-disable;
|
||||
};
|
||||
|
||||
ctrl {
|
||||
label = "Ctrl";
|
||||
gpios = <&tlmm 128 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_LEFTCTRL>;
|
||||
debounce-interval = <15>;
|
||||
linux,can-disable;
|
||||
};
|
||||
|
||||
alt {
|
||||
label = "Alt";
|
||||
gpios = <&tlmm 129 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <56>;
|
||||
debounce-interval = <15>;
|
||||
linux,can-disable;
|
||||
};
|
||||
};
|
||||
|
||||
gpio_hall_sensors {
|
||||
compatible = "gpio-keys";
|
||||
input-name = "hall-sensors";
|
||||
label = "Hall sensors";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hall_sensor0_default>, <&hall_sensor1_default>;
|
||||
/*
|
||||
hall_sensor0 {
|
||||
label = "Cover Hall Sensor";
|
||||
gpios = <&tlmm 82 GPIO_ACTIVE_HIGH>;
|
||||
linux,input-type = <EV_SW>;
|
||||
linux,code = <SW_LID>;
|
||||
gpio-key,wakeup;
|
||||
debounce-interval = <15>;
|
||||
};
|
||||
*/
|
||||
hall_sensor1 {
|
||||
label = "Keyboard Hall Sensor";
|
||||
gpios = <&tlmm 124 GPIO_ACTIVE_HIGH>;
|
||||
linux,input-type = <EV_SW>;
|
||||
linux,code = <SW_KEYPAD_SLIDE>;
|
||||
gpio-key,wakeup;
|
||||
debounce-interval = <15>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
input-name = "side-buttons";
|
||||
label = "Side buttons";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vol_up_pin_a>, <&cam_focus_pin_a>,
|
||||
<&cam_snapshot_pin_a>;
|
||||
vol_up {
|
||||
label = "Volume Up";
|
||||
gpios = <&pm8998_gpio 6 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
linux,code = <KEY_VOLUMEUP>;
|
||||
gpio-key,wakeup;
|
||||
debounce-interval = <15>;
|
||||
};
|
||||
|
||||
camera_snapshot {
|
||||
label = "Camera Snapshot";
|
||||
gpios = <&pm8998_gpio 7 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
linux,code = <KEY_CAMERA>;
|
||||
debounce-interval = <15>;
|
||||
};
|
||||
|
||||
camera_focus {
|
||||
label = "Camera Focus";
|
||||
gpios = <&pm8998_gpio 8 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
linux,code = <KEY_CAMERA_FOCUS>;
|
||||
debounce-interval = <15>;
|
||||
};
|
||||
};
|
||||
|
||||
disp_vcc_vreg: disp-vcc-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_vcc";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
disp_vddio_vreg: disp-vddio-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_vddio";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
disp_vci_vreg: disp-vci-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_vci";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
disp_elvdd_vreg: disp-elvdd-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_elvdd";
|
||||
regulator-min-microvolt = <4600000>;
|
||||
regulator-max-microvolt = <4600000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
disp_elvss_vreg: disp-elvss-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_elvss";
|
||||
regulator-min-microvolt = <2400000>;
|
||||
regulator-max-microvolt = <2400000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ts_vio_vreg: ts-vio-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "ts_vio_reg";
|
||||
startup-delay-us = <2>;
|
||||
enable-active-high;
|
||||
gpio = <&tlmm 81 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ts_vio_default>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
/*
|
||||
* Until we hook up type-c detection, we
|
||||
* have to stick with this. But it works.
|
||||
*/
|
||||
extcon_usb: extcon-usb {
|
||||
compatible = "linux,extcon-usb-gpio";
|
||||
id-gpio = <&tlmm 38 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&adreno_gpu {
|
||||
status = "ok";
|
||||
|
||||
zap-shader {
|
||||
memory-region = <&zap_shader_region>;
|
||||
firmware-name = "qcom/a540_zap.mbn";
|
||||
};
|
||||
};
|
||||
|
||||
&adreno_smmu {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&apc_cprh {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&blsp1_i2c6 {
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&i2c6_default>;
|
||||
pinctrl-1 = <&i2c6_sleep>;
|
||||
dmas = <&blsp1_dma 16>, <&blsp1_dma 17>;
|
||||
dma-names = "tx", "rx";
|
||||
status = "ok";
|
||||
|
||||
gpioext0: gpio-expander@58 {
|
||||
compatible = "awinic,aw9523-pinctrl";
|
||||
reg = <0x58>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <50 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&gpioext0 0 0 16>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
pinctrl-0 = <&gpio_expander_int_n>, <&gpio_expander_rst_n>;
|
||||
pinctrl-names = "default";
|
||||
reset-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
keyboard_pins_col: keyboard-matrix-col-pins {
|
||||
pins = "gpio8", "gpio9", "gpio10", "gpio11",
|
||||
"gpio12", "gpio13", "gpio14", "gpio15";
|
||||
function = "gpio";
|
||||
output-low;
|
||||
};
|
||||
keyboard_pins_row: keyboard-matrix-row-pins {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
||||
"gpio4", "gpio5", "gpio6", "gpio7";
|
||||
function = "gpio";
|
||||
drive-open-drain;
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&blsp2_i2c1 {
|
||||
status = "ok";
|
||||
qcom,noise-reject-scl = <3>;
|
||||
qcom,noise-reject-sda = <3>;
|
||||
|
||||
touchscreen@14 {
|
||||
compatible = "goodix,gt9286";
|
||||
reg = <0x14>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <125 IRQ_TYPE_LEVEL_LOW>;
|
||||
reset-gpios = <&tlmm 89 GPIO_ACTIVE_HIGH>;
|
||||
AVDD28-supply = <&vreg_l28_3p0>;
|
||||
VDDIO-supply = <&ts_vio_vreg>;
|
||||
pinctrl-names = "active", "sleep";
|
||||
pinctrl-0 = <&ts_active>;
|
||||
pinctrl-1 = <&ts_sleep>;
|
||||
};
|
||||
};
|
||||
|
||||
&cpufreq_hw {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "ok";
|
||||
|
||||
vdd-supply = <&vreg_l1a_0p875>;
|
||||
vdda-supply = <&vreg_l2a_1p2>;
|
||||
|
||||
panel: panel@0 {
|
||||
compatible = "boe,bf060y8m-aj0";
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
|
||||
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
|
||||
no-hpd;
|
||||
|
||||
vcc-supply = <&disp_vcc_vreg>;
|
||||
vddio-supply = <&disp_vddio_vreg>;
|
||||
vci-supply = <&disp_vci_vreg>;
|
||||
elvdd-supply = <&disp_elvdd_vreg>;
|
||||
elvss-supply = <&disp_elvss_vreg>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0_phy {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&dsi0_out {
|
||||
remote-endpoint = <&panel_in>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
&gcc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&gpucc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&gpio_keyboard {
|
||||
linux,keymap = <
|
||||
MATRIX_KEY(0, 0, KEY_F1) MATRIX_KEY(1, 0, KEY_H)
|
||||
MATRIX_KEY(2, 0, KEY_B) MATRIX_KEY(3, 0, KEY_7)
|
||||
MATRIX_KEY(4, 0, KEY_UP) MATRIX_KEY(5, 0, KEY_ENTER)
|
||||
MATRIX_KEY(6, 0, KEY_Y) MATRIX_KEY(7, 0, KEY_COMMA)
|
||||
MATRIX_KEY(0, 1, KEY_3) MATRIX_KEY(1, 1, KEY_S)
|
||||
MATRIX_KEY(2, 1, KEY_Z) MATRIX_KEY(3, 1, KEY_M)
|
||||
MATRIX_KEY(4, 1, KEY_I) MATRIX_KEY(5, 1, KEY_9)
|
||||
MATRIX_KEY(6, 1, KEY_W) MATRIX_KEY(7, 1, KEY_J)
|
||||
MATRIX_KEY(0, 2, KEY_LEFT) MATRIX_KEY(1, 2, KEY_G)
|
||||
MATRIX_KEY(2, 2, KEY_V) MATRIX_KEY(3, 2, KEY_6)
|
||||
MATRIX_KEY(4, 2, KEY_RIGHT) MATRIX_KEY(5, 2, KEY_DELETE)
|
||||
MATRIX_KEY(6, 2, KEY_T) MATRIX_KEY(7, 2, KEY_DOT)
|
||||
MATRIX_KEY(0, 3, KEY_SLASH) MATRIX_KEY(1, 3, KEY_A)
|
||||
MATRIX_KEY(2, 3, KEY_RIGHTBRACE) MATRIX_KEY(3, 3, KEY_HOMEPAGE)
|
||||
MATRIX_KEY(4, 3, KEY_P) MATRIX_KEY(5, 3, KEY_MINUS)
|
||||
MATRIX_KEY(6, 3, KEY_Q) MATRIX_KEY(7, 3, KEY_L)
|
||||
MATRIX_KEY(0, 4, KEY_BACKSPACE) MATRIX_KEY(1, 4, KEY_D)
|
||||
MATRIX_KEY(2, 4, KEY_X) MATRIX_KEY(3, 4, KEY_K)
|
||||
MATRIX_KEY(4, 4, KEY_SEMICOLON) MATRIX_KEY(5, 4, KEY_EQUAL)
|
||||
MATRIX_KEY(6, 4, KEY_E) MATRIX_KEY(7, 4, KEY_APOSTROPHE)
|
||||
MATRIX_KEY(0, 5, KEY_CAPSLOCK) MATRIX_KEY(1, 5, KEY_BACKSLASH)
|
||||
MATRIX_KEY(2, 5, KEY_LEFTBRACE) MATRIX_KEY(3, 5, KEY_DOWN)
|
||||
MATRIX_KEY(4, 5, KEY_O) MATRIX_KEY(5, 5, KEY_0)
|
||||
MATRIX_KEY(6, 5, KEY_GRAVE) MATRIX_KEY(7, 5, KEY_K)
|
||||
MATRIX_KEY(0, 6, KEY_SPACE) MATRIX_KEY(1, 6, KEY_F)
|
||||
MATRIX_KEY(2, 6, KEY_C) MATRIX_KEY(3, 6, KEY_N)
|
||||
MATRIX_KEY(4, 6, KEY_U) MATRIX_KEY(5, 6, KEY_8)
|
||||
MATRIX_KEY(6, 6, KEY_R) MATRIX_KEY(7, 6, KEY_5)
|
||||
MATRIX_KEY(0, 7, KEY_ESC) MATRIX_KEY(1, 7, KEY_1)
|
||||
MATRIX_KEY(2, 7, KEY_RESERVED) MATRIX_KEY(3, 7, KEY_RESERVED)
|
||||
MATRIX_KEY(4, 7, KEY_2) MATRIX_KEY(5, 7, KEY_4)
|
||||
MATRIX_KEY(6, 7, KEY_TAB) MATRIX_KEY(7, 7, KEY_RESERVED)
|
||||
>;
|
||||
};
|
||||
|
||||
&mdss {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&mdss_mdp {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&remoteproc_adsp {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/fxtec/adsp.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_mss {
|
||||
firmware-name = "qcom/msm8998/fxtec/mba.mbn", "qcom/msm8998/fxtec/modem.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_slpi {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/fxtec/slpi_v2.mbn";
|
||||
};
|
||||
|
||||
&mmcc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&mmss_smmu {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pmi8998_haptics {
|
||||
status = "okay";
|
||||
|
||||
qcom,wave-play-rate-us = <5000>;
|
||||
};
|
||||
|
||||
/* HACK! Push GPU voltage high until GPU CPR is hooked up */
|
||||
&pm8005_s1 {
|
||||
regulator-min-microvolt = <988000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
status = "okay";
|
||||
|
||||
qcom,max-voltage-uv = <4400000>;
|
||||
qcom,min-voltage-uv = <3700000>;
|
||||
qcom,battery-capacity-ua = <3150000>;
|
||||
};
|
||||
|
||||
&pm8998_gpio {
|
||||
unknown_pin_a: unk-active {
|
||||
pins = "gpio5";
|
||||
function = "normal";
|
||||
input-enable;
|
||||
bias-pull-up;
|
||||
qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
|
||||
};
|
||||
|
||||
vol_up_pin_a: vol-up-active {
|
||||
pins = "gpio6";
|
||||
function = "normal";
|
||||
input-enable;
|
||||
bias-pull-up;
|
||||
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
|
||||
};
|
||||
|
||||
cam_focus_pin_a: cam-focus-btn-active {
|
||||
pins = "gpio7";
|
||||
function = "normal";
|
||||
input-enable;
|
||||
bias-pull-up;
|
||||
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
|
||||
};
|
||||
|
||||
cam_snapshot_pin_a: cam-snapshot-btn-active {
|
||||
pins = "gpio8";
|
||||
function = "normal";
|
||||
input-enable;
|
||||
bias-pull-up;
|
||||
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
|
||||
};
|
||||
};
|
||||
|
||||
&pm8998_pon {
|
||||
resin {
|
||||
compatible = "qcom,pm8941-resin";
|
||||
interrupts = <GIC_SPI 0x8 1 IRQ_TYPE_EDGE_BOTH>;
|
||||
debounce = <15625>;
|
||||
bias-pull-up;
|
||||
linux,code = <KEY_VOLUMEDOWN>;
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
gpio-reserved-ranges = <0 4>;
|
||||
|
||||
mdp_vsync_n: mdp-vsync-n {
|
||||
pins = "gpio10";
|
||||
function = "mdp_vsync_a";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
i2c6_default: i2c6-default {
|
||||
pins = "gpio43", "gpio44";
|
||||
function = "blsp_i2c6";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
i2c6_sleep: i2c6-sleep {
|
||||
pins = "gpio43", "gpio44";
|
||||
function = "blsp_i2c6";
|
||||
drive-strength = <2>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
gpio_kb_extra_active: gpio-kb-extra-active {
|
||||
pins = "gpio21", "gpio32", "gpio33", "gpio114",
|
||||
"gpio128", "gpio129";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
gpio_expander_int_n: gpio-exp-intn-def {
|
||||
pins = "gpio50";
|
||||
drive-strength = <2>;
|
||||
input-enable;
|
||||
};
|
||||
|
||||
gpio_expander_rst_n: gpio-exp-rst-def {
|
||||
pins = "gpio51";
|
||||
drive-strength = <8>;
|
||||
};
|
||||
|
||||
disp_en_default: disp-en {
|
||||
pins = "gpio62";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
ts_vio_default: ts-vio-def {
|
||||
pins = "gpio81";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
hall_sensor0_default: hall-sensor0-def {
|
||||
pins = "gpio82";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
input-enable;
|
||||
};
|
||||
|
||||
hall_sensor1_default: hall-sensor1-def {
|
||||
pins = "gpio124";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
input-enable;
|
||||
};
|
||||
|
||||
panel_reset_n: panel-rst-n {
|
||||
pins = "gpio94";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
ts_active: ts-active {
|
||||
ts-rst-n {
|
||||
pins = "gpio89";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
ts-intr-n {
|
||||
pins = "gpio125";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
ts_sleep: ts-sleep {
|
||||
ts-rst-n {
|
||||
pins = "gpio89";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
ts-intr-n {
|
||||
pins = "gpio125";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ufshc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&ufsphy {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&usb3_dwc3 {
|
||||
dr_mode = "peripheral";
|
||||
extcon = <&extcon_usb>;
|
||||
};
|
||||
|
||||
/* GT9286 analog supply */
|
||||
&vreg_l28_3p0 {
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
};
|
||||
|
|
@ -40,3 +40,19 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* Capacitive keypad buttons */
|
||||
&rmi4_i2c {
|
||||
rmi4-f1a@1a {
|
||||
reg = <0x1a>;
|
||||
syna,codes = <KEY_BACK KEY_APPSELECT>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Display */
|
||||
&panel {
|
||||
compatible = "samsung,s6e3fa5";
|
||||
|
||||
/* The panel is mounted upside down on the OnePlus 5 */
|
||||
rotation = <180>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
|
||||
#include "msm8998.dtsi"
|
||||
#include "pm8998.dtsi"
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
height = <1920>;
|
||||
stride = <(1080 * 4)>;
|
||||
format = "a8r8g8b8";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -152,10 +154,18 @@
|
|||
reg = <0x0 0x95715000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
&apc_cprh {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&cpufreq_hw {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&blsp1_i2c5 {
|
||||
status = "okay";
|
||||
|
||||
touchscreen@20 {
|
||||
rmi4_i2c: touchscreen@20 {
|
||||
compatible = "syna,rmi4-i2c";
|
||||
reg = <0x20>;
|
||||
#address-cells = <1>;
|
||||
|
|
@ -188,6 +198,31 @@
|
|||
};
|
||||
};
|
||||
|
||||
&blsp1_i2c5_sleep {
|
||||
/delete-property/ bias-pull-up;
|
||||
/* Configure a no-pull on TP I2C sleep to match downstream. */
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
&blsp1_i2c6 {
|
||||
status = "okay";
|
||||
|
||||
nfc: pn544@28 {
|
||||
compatible = "nxp,nxp-nci-i2c";
|
||||
reg = <0x28>;
|
||||
clock-frequency = <400000>;
|
||||
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <92 IRQ_TYPE_NONE>;
|
||||
|
||||
enable-gpios = <&tlmm 116 0>;
|
||||
firmware-gpios = <&tlmm 93 0>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
|
||||
};
|
||||
};
|
||||
|
||||
&blsp1_uart3 {
|
||||
status = "okay";
|
||||
|
||||
|
|
@ -224,10 +259,35 @@
|
|||
};
|
||||
};
|
||||
|
||||
&blsp2_i2c3 {
|
||||
status = "disabled";
|
||||
|
||||
audio-codec@36 {
|
||||
compatible = "nxp,tfa9890";
|
||||
reg = <0x36>;
|
||||
|
||||
/*
|
||||
* vddd-supply = <&vreg_bob>;
|
||||
* vreg_l20a_2p95? 2950000->2960000 mV @ 200->800000 mA?
|
||||
*/
|
||||
|
||||
sound-name-prefix = "Mono Speaker";
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
&blsp2_uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ipa {
|
||||
status = "okay";
|
||||
|
||||
memory-region = <&ipa_fws_region>; // ipa_fw_mem? ipa_gsi_mem?
|
||||
firmware-name = "qcom/msm8998/oneplus/ipa_fws.mbn";
|
||||
};
|
||||
|
||||
&pm8005_lsid1 {
|
||||
pm8005-regulators {
|
||||
compatible = "qcom,pm8005-regulators";
|
||||
|
|
@ -257,6 +317,49 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
status = "okay";
|
||||
|
||||
qcom,max-voltage-uv = <4370000>;
|
||||
qcom,min-voltage-uv = <3700000>;
|
||||
qcom,battery-capacity-ua = <3300000>;
|
||||
};
|
||||
|
||||
&pmi8998_lpg {
|
||||
status = "okay";
|
||||
|
||||
//qcom,power-source = <0>;
|
||||
|
||||
notification-led {
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
|
||||
led@5 {
|
||||
reg = <5>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8998_haptics {
|
||||
status = "okay";
|
||||
|
||||
qcom,wave-play-rate-us = <4255>;
|
||||
};
|
||||
|
||||
&qusb2phy {
|
||||
status = "okay";
|
||||
|
||||
|
|
@ -437,9 +540,132 @@
|
|||
};
|
||||
};
|
||||
|
||||
&remoteproc_adsp {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/oneplus/adsp.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_mss {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/oneplus/mba.mbn", "qcom/msm8998/oneplus/modem.mbn";
|
||||
};
|
||||
|
||||
&remoteproc_slpi {
|
||||
status = "okay";
|
||||
|
||||
firmware-name = "qcom/msm8998/oneplus/slpi_v2.mbn";
|
||||
};
|
||||
|
||||
&mmcc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmss_smmu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdss {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdss_mdp {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
|
||||
vdd-supply = <&vreg_l1a_0p875>;
|
||||
vdda-supply = <&vreg_l2a_1p2>;
|
||||
|
||||
panel: panel@0 {
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
|
||||
disp-te-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>;
|
||||
|
||||
vddio-supply = <&vreg_l14a_1p88>; // TODO: Could this be moved under dsi0?
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0_phy {
|
||||
status = "okay";
|
||||
vdds-supply = <&vreg_l1a_0p875>;
|
||||
};
|
||||
|
||||
&dsi0_out {
|
||||
remote-endpoint = <&panel_in>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
/* Adreno 540 GPU */
|
||||
&gpucc {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&gpu_mem {
|
||||
compatible = "shared-dma-pool";
|
||||
};
|
||||
|
||||
&adreno_gpu {
|
||||
status = "ok";
|
||||
|
||||
zap-shader {
|
||||
memory-region = <&zap_shader_region>; // gpu_mem?
|
||||
firmware-name = "qcom/a540_zap.mbn";
|
||||
};
|
||||
};
|
||||
|
||||
&adreno_smmu {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
/*
|
||||
* HACK: Shoot GPU voltage high to stabilize Adreno 540 at high frequencies
|
||||
* until the GPU CPR is brought up.
|
||||
*/
|
||||
&pm8005_s1 {
|
||||
regulator-min-microvolt = <988000>; /* 0,524V -> 0,988V */
|
||||
//regulator-max-microvolt = <1100000>;
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
gpio-reserved-ranges = <0 4>, <81 4>;
|
||||
|
||||
disp_en_default: disp-en {
|
||||
pins = "gpio62";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
panel_reset_n: panel-rst-n {
|
||||
pins = "gpio94";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mdp_vsync_n: mdp-vsync-n {
|
||||
pins = "gpio11";
|
||||
function = "mdp_vsync_a";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
hall_sensor_default: hall-sensor-default {
|
||||
pins = "gpio124";
|
||||
function = "gpio";
|
||||
|
|
@ -461,6 +687,20 @@
|
|||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
nfc_int_active: nfc_int_active {
|
||||
pins = "gpio92";
|
||||
function = "gpio";
|
||||
drive-strength = <6>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
nfc_enable_active: nfc_enable_active {
|
||||
pins = "gpio12", "gpio116";
|
||||
function = "gpio";
|
||||
drive-strength = <6>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
&ufshc {
|
||||
|
|
@ -506,7 +746,7 @@
|
|||
};
|
||||
|
||||
&wifi {
|
||||
/* Leave disabled until MSS is functional */
|
||||
status = "okay";
|
||||
vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
|
||||
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
|
||||
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
|
||||
|
|
|
|||
|
|
@ -23,3 +23,8 @@
|
|||
&rmi4_f12 {
|
||||
touchscreen-y-mm = <137>;
|
||||
};
|
||||
|
||||
/* Display */
|
||||
&panel {
|
||||
compatible = "samsung,s6e3fc1";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Copyright (c) 2021, AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "msm8998-sony-xperia-yoshino.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Sony Xperia XZ1 Compact";
|
||||
compatible = "sony,xperia-lilac", "qcom,msm8998";
|
||||
};
|
||||
|
||||
&ibb {
|
||||
regulator-min-microvolt = <5500000>;
|
||||
regulator-max-microvolt = <5500000>;
|
||||
};
|
||||
|
||||
&lab {
|
||||
regulator-min-microvolt = <5500000>;
|
||||
regulator-max-microvolt = <5500000>;
|
||||
qcom,soft-start-us = <800>;
|
||||
};
|
||||
|
||||
&wcd9335 {
|
||||
pinctrl-0 = <&cdc_reset_n &wcd_int_n>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
&vreg_l22a_2p85 {
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
};
|
||||
116
arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino-maple.dts
Normal file
116
arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino-maple.dts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Copyright (c) 2021, AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "msm8998-sony-xperia-yoshino.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Sony Xperia XZ Premium";
|
||||
compatible = "sony,xperia-maple", "qcom,msm8998";
|
||||
|
||||
disp_dvdd_vreg: disp-dvdd-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "disp_dvdd_en";
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
startup-delay-us = <0>;
|
||||
enable-active-high;
|
||||
gpio = <&pmi8998_gpio 10 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&disp_dvdd_en>;
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
qcom,dual-dsi-mode;
|
||||
qcom,master-dsi;
|
||||
};
|
||||
|
||||
&dsi1 {
|
||||
vdd-supply = <&vreg_l1a_0p875>;
|
||||
vdda-supply = <&vreg_l2a_1p2>;
|
||||
qcom,dual-dsi-mode;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&dsi1_out {
|
||||
remote-endpoint = <&panel_in1>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
&dsi1_phy {
|
||||
vdds-supply = <&vreg_l1a_0p875>;
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&ibb {
|
||||
regulator-min-microvolt = <5600000>;
|
||||
regulator-max-microvolt = <5600000>;
|
||||
};
|
||||
|
||||
&lab {
|
||||
regulator-min-microvolt = <5800000>;
|
||||
regulator-max-microvolt = <5800000>;
|
||||
qcom,soft-start-us = <200>;
|
||||
};
|
||||
|
||||
&panel {
|
||||
compatible = "sharp,ls055d1sx04";
|
||||
|
||||
dvdd-supply = <&disp_dvdd_vreg>;
|
||||
ports {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
panel_in1: endpoint {
|
||||
remote-endpoint = <&dsi1_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pm8005_gpio {
|
||||
ear_en_default: ear-en-active {
|
||||
pins = "gpio1";
|
||||
function = "normal";
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
output-high;
|
||||
power-source = <1>; /* 1.8V */
|
||||
qcom,drive-strength = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&pmi8998_gpio {
|
||||
disp_dvdd_en: disp-dvdd-en-active {
|
||||
pins = "gpio10";
|
||||
function = PMIC_GPIO_FUNC_NORMAL;
|
||||
drive-push-pull;
|
||||
bias-disable;
|
||||
qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
|
||||
power-source = <0>;
|
||||
output-high;
|
||||
};
|
||||
};
|
||||
|
||||
&vreg_l22a_2p85 {
|
||||
regulator-min-microvolt = <2704000>;
|
||||
regulator-max-microvolt = <2704000>;
|
||||
};
|
||||
|
||||
|
||||
&pmi8998_wled {
|
||||
status = "okay";
|
||||
|
||||
//qcom,auto-string-detection;
|
||||
qcom,num-strings = <3>;
|
||||
qcom,enabled-strings = <0 1 2>;
|
||||
};
|
||||
|
||||
&wcd9335 {
|
||||
pinctrl-0 = <&cdc_reset_n &wcd_int_n &ear_en_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Copyright (c) 2021, AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "msm8998-sony-xperia-yoshino.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Sony Xperia XZ1";
|
||||
compatible = "sony,xperia-poplar", "qcom,msm8998";
|
||||
};
|
||||
|
||||
&ibb {
|
||||
regulator-min-microvolt = <5600000>;
|
||||
regulator-max-microvolt = <5600000>;
|
||||
};
|
||||
|
||||
&lab {
|
||||
regulator-min-microvolt = <5600000>;
|
||||
regulator-max-microvolt = <5600000>;
|
||||
qcom,soft-start-us = <800>;
|
||||
};
|
||||
|
||||
&wcd9335 {
|
||||
pinctrl-0 = <&cdc_reset_n &wcd_int_n>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
&vreg_l18a_2p85 {
|
||||
regulator-min-microvolt = <2850000>;
|
||||
regulator-max-microvolt = <2850000>;
|
||||
};
|
||||
|
||||
&vreg_l22a_2p85 {
|
||||
regulator-min-microvolt = <2700000>;
|
||||
regulator-max-microvolt = <2700000>;
|
||||
};
|
||||
1282
arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi
Normal file
1282
arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -65,6 +65,15 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pm660l_lpg: lpg@b100 {
|
||||
compatible = "qcom,pm660l-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pm660l_wled: leds@d800 {
|
||||
compatible = "qcom,pm660l-wled";
|
||||
reg = <0xd800 0xd900>;
|
||||
|
|
|
|||
|
|
@ -119,6 +119,14 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pm8916_pwm: pwm {
|
||||
compatible = "qcom,pm8916-pwm";
|
||||
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pm8916_vib: vibrator@c000 {
|
||||
compatible = "qcom,pm8916-vib";
|
||||
reg = <0xc000>;
|
||||
|
|
|
|||
|
|
@ -140,6 +140,16 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pm8994_lpg: lpg {
|
||||
compatible = "qcom,pm8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pm8994_spmi_regulators: regulators {
|
||||
compatible = "qcom,pm8994-regulators";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,6 +78,16 @@
|
|||
#size-cells = <0>;
|
||||
#io-channel-cells = <1>;
|
||||
|
||||
adc-chan@0 {
|
||||
reg = <ADC5_REF_GND>;
|
||||
label = "ref_gnd";
|
||||
};
|
||||
|
||||
adc-chan@1 {
|
||||
reg = <ADC5_REF_GND>;
|
||||
label = "vref_1p25";
|
||||
};
|
||||
|
||||
adc-chan@6 {
|
||||
reg = <ADC5_DIE_TEMP>;
|
||||
label = "die_temp";
|
||||
|
|
|
|||
|
|
@ -19,6 +19,29 @@
|
|||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
pmi8994_fg: fuel_gauge@4000 {
|
||||
compatible = "qcom,pmi8994-fg";
|
||||
status = "disabled";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
//FG //Charger
|
||||
reg = <0x4000 0x1000>;
|
||||
interrupts = <0x2 0x44 0x0 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "mem-avail";
|
||||
};
|
||||
|
||||
pmi8994_mpps: mpps@a000 {
|
||||
compatible = "qcom,pmi8994-mpp";
|
||||
reg = <0xa000>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pmi8994_mpps 0 0 4>;
|
||||
#gpio-cells = <2>;
|
||||
interrupts = <0 0xa0 0 IRQ_TYPE_NONE>,
|
||||
<0 0xa1 0 IRQ_TYPE_NONE>,
|
||||
<0 0xa2 0 IRQ_TYPE_NONE>,
|
||||
<0 0xa3 0 IRQ_TYPE_NONE>;
|
||||
};
|
||||
};
|
||||
|
||||
pmic@3 {
|
||||
|
|
@ -27,6 +50,16 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmi8994_lpg: lpg {
|
||||
compatible = "qcom,pmi8994-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pmi8994_spmi_regulators: regulators {
|
||||
compatible = "qcom,pmi8994-regulators";
|
||||
#address-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <dt-bindings/input/qcom,spmi-haptics.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
|
|
@ -18,6 +19,17 @@
|
|||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
pmi8998_fg: fuel_guage {
|
||||
compatible = "qcom,pmi8998-fg";
|
||||
status = "disabled";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
//FG //Charger
|
||||
reg = <0x4000 0x1000>;
|
||||
interrupts = <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "usb-plugin";
|
||||
};
|
||||
};
|
||||
|
||||
pmi8998_lsid1: pmic@3 {
|
||||
|
|
@ -41,5 +53,41 @@
|
|||
interrupt-names = "sc-err", "ocp";
|
||||
};
|
||||
};
|
||||
|
||||
pmi8998_lpg: lpg {
|
||||
compatible = "qcom,pmi8998-lpg";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#pwm-cells = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pmi8998_haptics: haptics@c000 {
|
||||
compatible = "qcom,pmi8998-haptics", "qcom,spmi-haptics";
|
||||
reg = <0xc000>;
|
||||
|
||||
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "short", "play";
|
||||
|
||||
qcom,wave-shape = <HAP_WAVE_SINE>;
|
||||
qcom,play-mode = <HAP_PLAY_BUFFER>;
|
||||
qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pmi8998_wled: leds@d800 {
|
||||
compatible = "qcom,pm660l-wled";
|
||||
reg = <0xd800 0xd900>;
|
||||
interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>,
|
||||
<0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "ovp", "short";
|
||||
label = "backlight";
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1168,19 +1168,19 @@
|
|||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr_quotient_offset1",
|
||||
"cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3",
|
||||
"cpr_init_voltage1",
|
||||
"cpr_init_voltage2",
|
||||
"cpr_init_voltage3",
|
||||
"cpr_quotient1",
|
||||
"cpr_quotient2",
|
||||
"cpr_quotient3",
|
||||
"cpr_ring_osc1",
|
||||
"cpr_ring_osc2",
|
||||
"cpr_ring_osc3",
|
||||
"cpr_fuse_revision";
|
||||
nvmem-cell-names = "cpr0_quotient_offset1",
|
||||
"cpr0_quotient_offset2",
|
||||
"cpr0_quotient_offset3",
|
||||
"cpr0_init_voltage1",
|
||||
"cpr0_init_voltage2",
|
||||
"cpr0_init_voltage3",
|
||||
"cpr0_quotient1",
|
||||
"cpr0_quotient2",
|
||||
"cpr0_quotient3",
|
||||
"cpr0_ring_osc1",
|
||||
"cpr0_ring_osc2",
|
||||
"cpr0_ring_osc3",
|
||||
"cpr0_fuse_revision";
|
||||
};
|
||||
|
||||
timer@b120000 {
|
||||
|
|
|
|||
|
|
@ -22,4 +22,9 @@
|
|||
|
||||
/* Ganges devices feature a Novatek touchscreen instead. */
|
||||
/delete-node/ &touchscreen;
|
||||
|
||||
&panel {
|
||||
compatible = "sony,kirin-nt36672a-truly";
|
||||
};
|
||||
|
||||
/delete-node/ &vreg_l18a_1v8;
|
||||
|
|
|
|||
|
|
@ -12,3 +12,7 @@
|
|||
model = "Sony Xperia XA2 Ultra";
|
||||
compatible = "sony,discovery-row", "qcom,sdm630";
|
||||
};
|
||||
|
||||
&panel {
|
||||
compatible = "sony,discovery-td4322-innolux";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,3 +12,7 @@
|
|||
model = "Sony Xperia XA2";
|
||||
compatible = "sony,pioneer-row", "qcom,sdm630";
|
||||
};
|
||||
|
||||
&panel {
|
||||
compatible = "sony,pioneer-td4322-truly";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,3 +19,7 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
&panel {
|
||||
compatible = "sony,voyager-td4328-tianma";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/input/gpio-keys.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
/* required for bootloader to select correct board */
|
||||
|
|
@ -19,23 +20,23 @@
|
|||
|
||||
/* This part enables graphical output via bootloader-enabled display */
|
||||
chosen {
|
||||
bootargs = "earlycon=tty0 console=tty0";
|
||||
// bootargs = "earlycon=tty0 console=tty0";
|
||||
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
stdout-path = "framebuffer0";
|
||||
// stdout-path = "framebuffer0";
|
||||
|
||||
framebuffer0: framebuffer@9d400000 {
|
||||
compatible = "simple-framebuffer";
|
||||
reg = <0 0x9d400000 0 (1920 * 1080 * 4)>;
|
||||
width = <1080>;
|
||||
height = <1920>;
|
||||
stride = <(1080 * 4)>;
|
||||
format = "a8r8g8b8";
|
||||
status= "okay";
|
||||
};
|
||||
// framebuffer0: framebuffer@9d400000 {
|
||||
// compatible = "simple-framebuffer";
|
||||
// reg = <0 0x9d400000 0 (1920 * 1080 * 4)>;
|
||||
// width = <1080>;
|
||||
// height = <1920>;
|
||||
// stride = <(1080 * 4)>;
|
||||
// format = "a8r8g8b8";
|
||||
// status= "okay";
|
||||
// };
|
||||
};
|
||||
|
||||
board_vbat: vbat-regulator {
|
||||
|
|
@ -212,7 +213,92 @@
|
|||
&blsp2_uart1 {
|
||||
status = "okay";
|
||||
|
||||
/* HCI Bluetooth */
|
||||
bluetooth: wcn3990-bt {
|
||||
compatible = "qcom,wcn3998-bt";
|
||||
|
||||
vddio-supply = <&vreg_l13a_1p8>;
|
||||
vddxo-suppky = <&vreg_l9a_1p8>;
|
||||
vddrf-supply = <&vreg_l6a_1p3>;
|
||||
vddch0-supply = <&vreg_l19a_3p3>;
|
||||
|
||||
max-speed = <3200000>;
|
||||
|
||||
clocks = <&rpmcc RPM_SMD_RF_CLK1_PIN>;
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vdda-supply = <&vreg_l1a_1p225>;
|
||||
|
||||
panel: panel@0 {
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&tlmm 53 GPIO_ACTIVE_HIGH>;
|
||||
disp-te-gpios = <&tlmm 59 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
backlight = <&pm660l_wled>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&panel_reset_n &mdp_vsync_n>;
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dsi0_out {
|
||||
remote-endpoint = <&panel_in>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
|
||||
&mdss {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pm660l_lpg {
|
||||
// No idea, and optional...
|
||||
// qcom,power-source = <1>;
|
||||
|
||||
status = "okay";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
multi-led {
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pm660l_wled {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpucc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pon {
|
||||
|
|
@ -564,7 +650,7 @@
|
|||
};
|
||||
|
||||
&sdhc_2 {
|
||||
status = "okay";
|
||||
status = "disabled";
|
||||
|
||||
vmmc-supply = <&vreg_l5b_29p5>;
|
||||
vqmmc-supply = <&vreg_l2b_2p95>;
|
||||
|
|
@ -605,6 +691,20 @@
|
|||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
panel_reset_n: panel-rst-n {
|
||||
pins = "gpio53";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mdp_vsync_n: mdp-vsync-n {
|
||||
pins = "gpio59";
|
||||
function = "mdp_vsync";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
|
|
@ -615,3 +715,345 @@
|
|||
dr_mode = "peripheral";
|
||||
extcon = <&extcon_usb>;
|
||||
};
|
||||
|
||||
&rpm_requests {
|
||||
pm660l-regulators {
|
||||
compatible = "qcom,rpm-pm660l-regulators";
|
||||
|
||||
vdd_s1-supply = <&vph_pwr>;
|
||||
vdd_s2-supply = <&vph_pwr>;
|
||||
vdd_s3_s4-supply = <&vph_pwr>;
|
||||
vdd_s5-supply = <&vph_pwr>;
|
||||
vdd_s6-supply = <&vph_pwr>;
|
||||
|
||||
vdd_l1_l9_l10-supply = <&vreg_s2b_1p05>;
|
||||
vdd_l2-supply = <&vreg_bob>;
|
||||
vdd_l3_l5_l7_l8-supply = <&vreg_bob>;
|
||||
vdd_l4_l6-supply = <&vreg_bob>;
|
||||
vdd_bob-supply = <&vph_pwr>;
|
||||
|
||||
vreg_s1b_1p125: s1 {
|
||||
regulator-min-microvolt = <1125000>;
|
||||
regulator-max-microvolt = <1125000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_s2b_1p05: s2 {
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1050000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/*
|
||||
* At least on Nile's configuration, S3B/S4B (VDD_CX) and
|
||||
* S5B (VDD_MX) are managed only through RPM Power Domains.
|
||||
* Trying to set a voltage on the main supply will create
|
||||
* havoc and freeze the SoC.
|
||||
* In any case, reference voltages for these regulators are:
|
||||
* S3B/S4B: 0.870V
|
||||
* S5B: 0.915V
|
||||
*/
|
||||
|
||||
/* LDOs */
|
||||
vreg_l1b_0p925: l1 {
|
||||
regulator-min-microvolt = <920000>;
|
||||
regulator-max-microvolt = <928000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l2b_2p95: l2 {
|
||||
/*
|
||||
* This regulator supports 1.648 - 3.104V on this board
|
||||
* but we set a max voltage of anything less than 2.7V
|
||||
* to satisfy a condition in sdhci.c that will disable
|
||||
* 3.3V SDHCI signaling, which happens to be not really
|
||||
* supported on the Xperia Nile/Ganges platform.
|
||||
*/
|
||||
regulator-min-microvolt = <1648000>;
|
||||
regulator-max-microvolt = <2696000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l3b_3p0: l3 {
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-min-microamp = <200>;
|
||||
regulator-max-microamp = <600000>;
|
||||
regulator-system-load = <100000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l4b_29p5: l4 {
|
||||
regulator-min-microvolt = <2944000>;
|
||||
regulator-max-microvolt = <2952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
|
||||
regulator-min-microamp = <200>;
|
||||
regulator-max-microamp = <600000>;
|
||||
regulator-system-load = <570000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
/*
|
||||
* Downstream specifies a range of 1721-3600mV,
|
||||
* but the only assigned consumers are SDHCI2 VMMC
|
||||
* and Coresight QPDI that both request pinned 2.95V.
|
||||
* Tighten the range to 1.8-3.328 (closest to 3.3) to
|
||||
* make the mmc driver happy.
|
||||
*/
|
||||
vreg_l5b_29p5: l5 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3328000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l6b_3p3: l6 {
|
||||
regulator-min-microvolt = <1704000>;
|
||||
regulator-max-microvolt = <3312000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l7b_3p125: l7 {
|
||||
regulator-min-microvolt = <2704000>;
|
||||
regulator-max-microvolt = <3128000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l8b_3p3: l8 {
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <3400000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* L9B (870mV) is currently unused */
|
||||
/* L10B (915mV) is currently unused */
|
||||
|
||||
vreg_bob: bob {
|
||||
regulator-min-microvolt = <3304000>;
|
||||
regulator-max-microvolt = <3624000>;
|
||||
regulator-enable-ramp-delay = <500>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
pm660-regulators {
|
||||
compatible = "qcom,rpm-pm660-regulators";
|
||||
|
||||
vdd_s1-supply = <&vph_pwr>;
|
||||
vdd_s2-supply = <&vph_pwr>;
|
||||
vdd_s3-supply = <&vph_pwr>;
|
||||
vdd_s4-supply = <&vph_pwr>;
|
||||
vdd_s5-supply = <&vph_pwr>;
|
||||
vdd_s6-supply = <&vph_pwr>;
|
||||
|
||||
vdd_l1_l6_l7-supply = <&vreg_s5a_1p35>;
|
||||
vdd_l2_l3-supply = <&vreg_s2b_1p05>;
|
||||
vdd_l5-supply = <&vreg_s2b_1p05>;
|
||||
vdd_l8_l9_l10_l11_l12_l13_l14-supply = <&vreg_s4a_2p04>;
|
||||
vdd_l15_l16_l17_l18_l19-supply = <&vreg_bob>;
|
||||
|
||||
/*
|
||||
* S1A (FTAPC0), S2A (FTAPC1), S3A (HFAPC1) are managed
|
||||
* by the Core Power Reduction hardened (CPRh) and the
|
||||
* Operating State Manager (OSM) HW automatically.
|
||||
*/
|
||||
|
||||
vreg_s4a_2p04: s4 {
|
||||
regulator-min-microvolt = <2040000>;
|
||||
regulator-max-microvolt = <2040000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vreg_s5a_1p35: s5 {
|
||||
regulator-min-microvolt = <1224000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_s6a_0p87: s6 {
|
||||
regulator-min-microvolt = <504000>;
|
||||
regulator-max-microvolt = <992000>;
|
||||
regulator-enable-ramp-delay = <150>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* LDOs */
|
||||
vreg_l1a_1p225: l1 {
|
||||
regulator-min-microvolt = <1226000>;
|
||||
regulator-max-microvolt = <1250000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l2a_1p0: l2 {
|
||||
regulator-min-microvolt = <944000>;
|
||||
regulator-max-microvolt = <1008000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l3a_1p0: l3 {
|
||||
regulator-min-microvolt = <944000>;
|
||||
regulator-max-microvolt = <1008000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l5a_0p848: l5 {
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l6a_1p3: l6 {
|
||||
regulator-min-microvolt = <1304000>;
|
||||
regulator-max-microvolt = <1368000>;
|
||||
regulator-allow-set-load;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l7a_1p2: l7 {
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l8a_1p8: l8 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-system-load = <325000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
|
||||
vreg_l9a_1p8: l9 {
|
||||
regulator-min-microvolt = <1804000>;
|
||||
regulator-max-microvolt = <1896000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l10a_1p8: l10 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l11a_1p8: l11 {
|
||||
regulator-min-microvolt = <1784000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l12a_1p8: l12 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* This gives power to the LPDDR4: never turn it off! */
|
||||
vreg_l13a_1p8: l13 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vreg_l14a_1p8: l14 {
|
||||
regulator-min-microvolt = <1710000>;
|
||||
regulator-max-microvolt = <1904000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l15a_1p8: l15 {
|
||||
regulator-min-microvolt = <1648000>;
|
||||
regulator-max-microvolt = <2952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* L16A (2.70V) is unused */
|
||||
|
||||
vreg_l17a_1p8: l17 {
|
||||
regulator-min-microvolt = <1648000>;
|
||||
regulator-max-microvolt = <2952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l18a_1v8: l18 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <10>;
|
||||
regulator-min-microamp = <200>;
|
||||
regulator-max-microamp = <50000>;
|
||||
regulator-system-load = <10000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l19a_3p3: l19 {
|
||||
regulator-min-microvolt = <3312000>;
|
||||
regulator-max-microvolt = <3400000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
gpio-reserved-ranges = <8 4>;
|
||||
|
||||
imx300_vana_default: imx300-vana-default {
|
||||
pins = "gpio50";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
imx219_vana_default: imx219-vana-default {
|
||||
pins = "gpio51";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
cam_vdig_default: cam-vdig-default {
|
||||
pins = "gpio52";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@
|
|||
&PERF_CLUSTER_SLEEP_1
|
||||
&PERF_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1126>;
|
||||
dynamic-power-coefficient = <118>;
|
||||
operating-points-v2 = <&cpu_gold_opp_table>;
|
||||
power-domains = <&apc_cprh 0>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_1>;
|
||||
L2_1: l2-cache {
|
||||
|
|
@ -71,6 +77,12 @@
|
|||
&PERF_CLUSTER_SLEEP_1
|
||||
&PERF_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1126>;
|
||||
dynamic-power-coefficient = <118>;
|
||||
operating-points-v2 = <&cpu_gold_opp_table>;
|
||||
power-domains = <&apc_cprh 0>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_1>;
|
||||
};
|
||||
|
|
@ -86,6 +98,12 @@
|
|||
&PERF_CLUSTER_SLEEP_1
|
||||
&PERF_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1126>;
|
||||
dynamic-power-coefficient = <118>;
|
||||
operating-points-v2 = <&cpu_gold_opp_table>;
|
||||
power-domains = <&apc_cprh 0>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_1>;
|
||||
};
|
||||
|
|
@ -101,6 +119,12 @@
|
|||
&PERF_CLUSTER_SLEEP_1
|
||||
&PERF_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1126>;
|
||||
dynamic-power-coefficient = <118>;
|
||||
operating-points-v2 = <&cpu_gold_opp_table>;
|
||||
power-domains = <&apc_cprh 0>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_1>;
|
||||
};
|
||||
|
|
@ -116,6 +140,12 @@
|
|||
&PWR_CLUSTER_SLEEP_1
|
||||
&PWR_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1024>;
|
||||
dynamic-power-coefficient = <100>;
|
||||
operating-points-v2 = <&cpu_silver_opp_table>;
|
||||
power-domains = <&apc_cprh 1>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_0>;
|
||||
L2_0: l2-cache {
|
||||
|
|
@ -135,6 +165,12 @@
|
|||
&PWR_CLUSTER_SLEEP_1
|
||||
&PWR_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1024>;
|
||||
dynamic-power-coefficient = <100>;
|
||||
operating-points-v2 = <&cpu_silver_opp_table>;
|
||||
power-domains = <&apc_cprh 1>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_0>;
|
||||
};
|
||||
|
|
@ -150,6 +186,12 @@
|
|||
&PWR_CLUSTER_SLEEP_1
|
||||
&PWR_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1024>;
|
||||
dynamic-power-coefficient = <100>;
|
||||
operating-points-v2 = <&cpu_silver_opp_table>;
|
||||
power-domains = <&apc_cprh 1>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_0>;
|
||||
};
|
||||
|
|
@ -165,6 +207,12 @@
|
|||
&PWR_CLUSTER_SLEEP_1
|
||||
&PWR_CLUSTER_SLEEP_2>;
|
||||
capacity-dmips-mhz = <1024>;
|
||||
dynamic-power-coefficient = <100>;
|
||||
operating-points-v2 = <&cpu_silver_opp_table>;
|
||||
power-domains = <&apc_cprh 1>;
|
||||
power-domain-names = "cprh";
|
||||
clocks = <&xo_board>;
|
||||
qcom,freq-domain = <&cpufreq_hw 0>;
|
||||
#cooling-cells = <2>;
|
||||
next-level-cache = <&L2_0>;
|
||||
};
|
||||
|
|
@ -204,6 +252,7 @@
|
|||
core3 {
|
||||
cpu = <&CPU3>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -314,6 +363,28 @@
|
|||
scm {
|
||||
compatible = "qcom,scm-msm8998", "qcom,scm";
|
||||
};
|
||||
android {
|
||||
compatible = "android,firmware";
|
||||
fstab {
|
||||
compatible = "android,fstab";
|
||||
vendor {
|
||||
compatible = "android,vendor";
|
||||
dev = "/dev/block/platform/soc/c0c4000.sdhci/by-name/vendor_a";
|
||||
type = "ext4";
|
||||
mnt_flags = "ro,barrier=1,discard";
|
||||
fsmgr_flags = "wait";
|
||||
status = "ok";
|
||||
};
|
||||
system {
|
||||
compatible = "android,system";
|
||||
dev = "/dev/block/platform/soc/c0c4000.sdhci/by-name/system_a";
|
||||
type = "ext4";
|
||||
mnt_flags = "ro,barrier=1,discard";
|
||||
fsmgr_flags = "wait";
|
||||
status = "ok";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
|
|
@ -332,6 +403,175 @@
|
|||
method = "smc";
|
||||
};
|
||||
|
||||
cpu_silver_opp_table: cpu-silver-opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-1843200000 {
|
||||
opp-hz = /bits/ 64 <1843200000>;
|
||||
required-opps = <&cprh_opp8>;
|
||||
qcom,pll-override = <0x094c004c>;
|
||||
qcom,spare-data = <3>;
|
||||
};
|
||||
opp-1728000000 {
|
||||
opp-hz = /bits/ 64 <1728000000>;
|
||||
required-opps = <&cprh_opp7>;
|
||||
qcom,pll-override = <0x09480048>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-1536000000 {
|
||||
opp-hz = /bits/ 64 <1536000000>;
|
||||
required-opps = <&cprh_opp6>;
|
||||
qcom,pll-override = <0x08400040>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-1382400000 {
|
||||
opp-hz = /bits/ 64 <1382400000>;
|
||||
required-opps = <&cprh_opp5>;
|
||||
qcom,pll-override = <0x07390039>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-1094400000 {
|
||||
opp-hz = /bits/ 64 <1094400000>;
|
||||
required-opps = <&cprh_opp4>;
|
||||
qcom,pll-override = <0x052e002e>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-883200000 {
|
||||
opp-hz = /bits/ 64 <883200000>;
|
||||
required-opps = <&cprh_opp3>;
|
||||
qcom,pll-override = <0x04250025>;
|
||||
qcom,spare-data = <1>;
|
||||
};
|
||||
opp-614400000 {
|
||||
opp-hz = /bits/ 64 <614400000>;
|
||||
required-opps = <&cprh_opp2>;
|
||||
qcom,pll-override = <0x3200020>;
|
||||
qcom,pll-div = <1>;
|
||||
qcom,spare-data = <1>;
|
||||
};
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&cprh_opp1>;
|
||||
qcom,pll-override = <0x1200020>;
|
||||
qcom,spare-data = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_gold_opp_table: cpu-gold-opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-2208000000 {
|
||||
opp-hz = /bits/ 64 <2208000000>;
|
||||
required-opps = <&cprh_opp10>;
|
||||
qcom,pll-override = <0x0b5c005c>;
|
||||
qcom,spare-data = <3>;
|
||||
};
|
||||
opp-2150400000 {
|
||||
opp-hz = /bits/ 64 <2150400000>;
|
||||
required-opps = <&cprh_opp9>;
|
||||
qcom,pll-override = <0x0b590059>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-2016000000 {
|
||||
opp-hz = /bits/ 64 <2016000000>;
|
||||
required-opps = <&cprh_opp8>;
|
||||
qcom,pll-override = <0x0a540054>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-1881600000 {
|
||||
opp-hz = /bits/ 64 <1881600000>;
|
||||
required-opps = <&cprh_opp7>;
|
||||
qcom,pll-override = <0x094e004e>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-1670400000 {
|
||||
opp-hz = /bits/ 64 <1670400000>;
|
||||
required-opps = <&cprh_opp6>;
|
||||
qcom,pll-override = <0x08450045>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-1516800000 {
|
||||
opp-hz = /bits/ 64 <1516800000>;
|
||||
required-opps = <&cprh_opp5>;
|
||||
qcom,pll-override = <0x073f003f>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-1344000000 {
|
||||
opp-hz = /bits/ 64 <1344000000>;
|
||||
required-opps = <&cprh_opp4>;
|
||||
qcom,pll-override = <0x07380038>;
|
||||
qcom,spare-data = <2>;
|
||||
|
||||
};
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
required-opps = <&cprh_opp3>;
|
||||
qcom,pll-override = <0x052e002e>;
|
||||
qcom,spare-data = <2>;
|
||||
};
|
||||
opp-787200000 {
|
||||
opp-hz = /bits/ 64 <787200000>;
|
||||
required-opps = <&cprh_opp2>;
|
||||
qcom,pll-override = <0x4200020>;
|
||||
qcom,pll-div = <1>;
|
||||
qcom,spare-data = <1>;
|
||||
};
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&cprh_opp1>;
|
||||
qcom,pll-override = <0x1200020>;
|
||||
qcom,spare-data = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
cprh_opp_table: cpr-gold-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cprh_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cprh_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cprh_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cprh_opp4: opp4 {
|
||||
opp-level = <4>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cprh_opp5: opp5 {
|
||||
opp-level = <5>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
cprh_opp6: opp6 {
|
||||
opp-level = <6>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
cprh_opp7: opp7 {
|
||||
opp-level = <7>;
|
||||
qcom,opp-fuse-level = <4 3>;
|
||||
};
|
||||
cprh_opp8: opp8 {
|
||||
opp-level = <8>;
|
||||
qcom,opp-fuse-level = <4 3>;
|
||||
};
|
||||
cprh_opp9: opp9 {
|
||||
opp-level = <9>;
|
||||
qcom,opp-fuse-level = <4>;
|
||||
};
|
||||
cprh_opp10: opp10 {
|
||||
opp-level = <10>;
|
||||
qcom,opp-fuse-level = <5>;
|
||||
};
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
|
@ -552,14 +792,190 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
qusb2_hstx_trim: hstx-trim@240 {
|
||||
reg = <0x240 0x1>;
|
||||
bits = <25 3>;
|
||||
cpr_efuse_speedbin: speedbin@133 {
|
||||
reg = <0x133 0x8>;
|
||||
bits = <5 3>;
|
||||
};
|
||||
|
||||
gpu_speed_bin: gpu-speed-bin@41a0 {
|
||||
reg = <0x41a0 0x1>;
|
||||
bits = <21 7>;
|
||||
/* CPR Quotients: Power Cluster */
|
||||
cpr_quot00_pwrcl: quot00_pwrcl@221 {
|
||||
reg = <0x221 0x4>;
|
||||
bits = <4 12>;
|
||||
};
|
||||
|
||||
cpr_quot01_pwrcl: quot01_pwrcl@239 {
|
||||
reg = <0x239 0x4>;
|
||||
bits = <1 12>;
|
||||
};
|
||||
|
||||
cpr_quot02_pwrcl: quot02_pwrcl@21d {
|
||||
reg = <0x21d 0x4>;
|
||||
bits = <0 12>;
|
||||
};
|
||||
|
||||
cpr_quot_offset01_pwrcl: qoff01_pwrcl@23a {
|
||||
reg = <0x23a 0x4>;
|
||||
bits = <5 7>;
|
||||
};
|
||||
|
||||
cpr_quot_offset02_pwrcl: qoff02_pwrcl@223 {
|
||||
reg = <0x223 0x4>;
|
||||
bits = <0 7>;
|
||||
};
|
||||
|
||||
/* CPR Quotients: Performance Cluster */
|
||||
cpr_quot00_perfcl: quot00_perfcl@22e {
|
||||
reg = <0x22e 0x4>;
|
||||
bits = <5 11>;
|
||||
};
|
||||
|
||||
cpr_quot10_perfcl: quot10_perfcl@230 {
|
||||
reg = <0x230 0x4>;
|
||||
bits = <0 1>;
|
||||
};
|
||||
|
||||
cpr_quot01_perfcl: quot01_perfcl@230 {
|
||||
reg = <0x230 0x4>;
|
||||
bits = <1 12>;
|
||||
};
|
||||
|
||||
cpr_quot02_perfcl: quot02_perfcl@22d {
|
||||
reg = <0x22d 0x4>;
|
||||
bits = <1 12>;
|
||||
};
|
||||
|
||||
cpr_quot03_perfcl: quot03_perfcl@22b {
|
||||
reg = <0x22b 0x8>;
|
||||
bits = <5 12>;
|
||||
};
|
||||
|
||||
cpr_quot04_perfcl: quot04_perfcl@23e {
|
||||
reg = <0x236 0x4>;
|
||||
bits = <0 12>;
|
||||
};
|
||||
|
||||
cpr_quot_offset01_perfcl: qoff01_perfcl@233 {
|
||||
reg = <0x233 0x4>;
|
||||
bits = <3 7>;
|
||||
};
|
||||
|
||||
cpr_quot_offset02_perfcl: qoff02_perfcl@232 {
|
||||
reg = <0x232 0x4>;
|
||||
bits = <4 7>;
|
||||
};
|
||||
|
||||
cpr_quot_offset03_perfcl: qoff03_perfcl@231 {
|
||||
reg = <0x231 0x4>;
|
||||
bits = <5 7>;
|
||||
};
|
||||
|
||||
cpr_quot_offset04_perfcl: qoff04_perfcl@237 {
|
||||
reg = <0x237 0x4>;
|
||||
bits = <4 4>;
|
||||
};
|
||||
|
||||
cpr_quot_offset14_perfcl: qoff14_perfcl@230 {
|
||||
reg = <0x230 0x4>;
|
||||
bits = <0 3>;
|
||||
};
|
||||
|
||||
/* CPR Init Voltage: Power Cluster */
|
||||
cpr_init_voltage00_pwrcl: ivolt00_pwrcl@21c {
|
||||
reg = <0x21c 0x4>;
|
||||
bits = <2 6>;
|
||||
};
|
||||
|
||||
cpr_init_voltage01_pwrcl: ivolt01_pwrcl@238 {
|
||||
reg = <0x238 0x4>;
|
||||
bits = <3 6>;
|
||||
};
|
||||
|
||||
cpr_init_voltage02_pwrcl: ivolt02_pwrcl@219 {
|
||||
reg = <0x219 0x4>;
|
||||
bits = <8 6>;
|
||||
};
|
||||
|
||||
/* CPR Init Voltage: Performance Cluster */
|
||||
cpr_init_voltage00_perfcl: ivolt00_perfcl@22a {
|
||||
reg = <0x22a 0x4>;
|
||||
bits = <1 6>;
|
||||
};
|
||||
|
||||
cpr_init_voltage01_perfcl: ivolt01_perfcl@22a {
|
||||
reg = <0x22a 0x4>;
|
||||
bits = <7 6>;
|
||||
};
|
||||
|
||||
cpr_init_voltage02_perfcl: ivolt02_perfcl@229 {
|
||||
reg = <0x229 0x4>;
|
||||
bits = <3 6>;
|
||||
};
|
||||
|
||||
cpr_init_voltage03_perfcl: ivolt03_perfcl@228 {
|
||||
reg = <0x228 0x4>;
|
||||
bits = <5 6>;
|
||||
};
|
||||
|
||||
cpr_init_voltage04_perfcl: ivolt04_perfcl@235 {
|
||||
reg = <0x235 0x4>;
|
||||
bits = <2 6>;
|
||||
};
|
||||
|
||||
/* CPR Ring Oscillator: Power Cluster */
|
||||
cpr_ro_sel00_pwrcl: rosel00_pwrcl@219 {
|
||||
reg = <0x219 0x4>;
|
||||
bits = <4 4>;
|
||||
};
|
||||
|
||||
cpr_ro_sel01_pwrcl: rosel01_pwrcl@20f {
|
||||
reg = <0x20f 0x4>;
|
||||
bits = <0 4>;
|
||||
};
|
||||
|
||||
cpr_ro_sel02_pwrcl: rosel02_pwrcl@218 {
|
||||
reg = <0x218 0x4>;
|
||||
bits = <0 4>;
|
||||
};
|
||||
|
||||
/* CPR Ring Oscillator: Performance Cluster */
|
||||
cpr_ro_sel00_perfcl: rosel00_perfcl@227 {
|
||||
reg = <0x227 0x4>;
|
||||
bits = <5 4>;
|
||||
};
|
||||
|
||||
cpr_ro_sel01_perfcl: rosel01_perfcl@228 {
|
||||
reg = <0x228 0x4>;
|
||||
bits = <1 4>;
|
||||
};
|
||||
|
||||
cpr_ro_sel02_perfcl: rosel02_perfcl@227 {
|
||||
reg = <0x227 0x4>;
|
||||
bits = <1 4>;
|
||||
};
|
||||
|
||||
cpr_ro_sel03_perfcl: rosel03_perfcl@226 {
|
||||
reg = <0x226 0x4>;
|
||||
bits = <5 4>;
|
||||
};
|
||||
|
||||
cpr_ro_sel04_perfcl: rosel04_perfcl@211 {
|
||||
reg = <0x211 0x4>;
|
||||
bits = <6 4>;
|
||||
};
|
||||
|
||||
cpr_fuse_revision: cpr_fusing_rev@23b {
|
||||
reg = <0x23b 0x1>;
|
||||
bits = <4 3>;
|
||||
};
|
||||
|
||||
qusb2_hstx_trim: hstx-trim@243 {
|
||||
reg = <0x243 0x1>;
|
||||
bits = <1 3>;
|
||||
};
|
||||
|
||||
gpu_speed_bin: gpu_speed_bin@1a2 {
|
||||
reg = <0x1a2 0x1>;
|
||||
bits = <5 7>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -612,6 +1028,9 @@
|
|||
clock-names = "bus";
|
||||
#global-interrupts = <2>;
|
||||
#iommu-cells = <1>;
|
||||
qcom,bypass-cbndx = /bits/ 8 <6>;
|
||||
qcom,reset-nodisable-cbs = /bits/ 8 <7 8 9 10 11 12 13 14
|
||||
15 16 17 18 19 20>;
|
||||
|
||||
interrupts =
|
||||
<GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
|
@ -646,8 +1065,6 @@
|
|||
<GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
a2noc: interconnect@1704000 {
|
||||
|
|
@ -680,6 +1097,114 @@
|
|||
<&mmcc AHB_CLK_SRC>;
|
||||
};
|
||||
|
||||
saw1: power-controller@17812000 {
|
||||
compatible = "qcom,sdm660-gold-saw2-v4.1-l2", "qcom,saw2";
|
||||
reg = <0x017812000 0x1000>;
|
||||
};
|
||||
|
||||
saw0: power-controller@17912000 {
|
||||
compatible = "qcom,sdm660-gold-saw2-v4.1-l2", "qcom,saw2";
|
||||
reg = <0x017912000 0x1000>;
|
||||
};
|
||||
|
||||
cpufreq_hw: cpufreq_hw@17816000 {
|
||||
compatible = "qcom,cpufreq-hw-8998";
|
||||
|
||||
reg = <0x0179c0000 0x1000>, <0x0179c1000 0x1000>,
|
||||
<0x0179c2000 0x1000>, <0x0179c3000 0x1000>;
|
||||
reg-names = "osm-domain0", "freq-domain0",
|
||||
"osm-domain1", "freq-domain1";
|
||||
|
||||
assigned-clocks = <&gcc HMSS_GPLL0_CLK_SRC>;
|
||||
assigned-clock-rates = <300000000>;
|
||||
|
||||
clocks = <&rpmcc RPM_SMD_XO_A_CLK_SRC>,
|
||||
<&gcc HMSS_GPLL0_CLK_SRC>;
|
||||
clock-names = "xo", "alternate";
|
||||
|
||||
#freq-domain-cells = <1>;
|
||||
};
|
||||
|
||||
/* Gold and Silver cluster */
|
||||
apc_cprh: power-controller@179c4000 {
|
||||
compatible = "qcom,sdm630-cprh";
|
||||
reg = <0x0179c4000 0x4000>, <0x0179c8000 0x4000>;
|
||||
|
||||
clocks = <&gcc GCC_HMSS_RBCPR_CLK>;
|
||||
clock-names = "ref";
|
||||
assigned-clocks = <&gcc GCC_HMSS_RBCPR_CLK>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
#power-domain-cells = <1>;
|
||||
operating-points-v2 = <&cprh_opp_table>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_speedbin>,
|
||||
<&cpr_fuse_revision>,
|
||||
<&cpr_quot00_perfcl>,
|
||||
<&cpr_quot01_perfcl>,
|
||||
<&cpr_quot02_perfcl>,
|
||||
<&cpr_quot03_perfcl>,
|
||||
<&cpr_quot04_perfcl>,
|
||||
<&cpr_quot_offset01_perfcl>,
|
||||
<&cpr_quot_offset02_perfcl>,
|
||||
<&cpr_quot_offset03_perfcl>,
|
||||
<&cpr_quot_offset04_perfcl>,
|
||||
<&cpr_init_voltage00_perfcl>,
|
||||
<&cpr_init_voltage01_perfcl>,
|
||||
<&cpr_init_voltage02_perfcl>,
|
||||
<&cpr_init_voltage03_perfcl>,
|
||||
<&cpr_init_voltage04_perfcl>,
|
||||
<&cpr_ro_sel00_perfcl>,
|
||||
<&cpr_ro_sel01_perfcl>,
|
||||
<&cpr_ro_sel02_perfcl>,
|
||||
<&cpr_ro_sel03_perfcl>,
|
||||
<&cpr_ro_sel04_perfcl>,
|
||||
<&cpr_quot00_pwrcl>,
|
||||
<&cpr_quot01_pwrcl>,
|
||||
<&cpr_quot02_pwrcl>,
|
||||
<&cpr_quot_offset01_pwrcl>,
|
||||
<&cpr_quot_offset02_pwrcl>,
|
||||
<&cpr_init_voltage00_pwrcl>,
|
||||
<&cpr_init_voltage01_pwrcl>,
|
||||
<&cpr_init_voltage02_pwrcl>,
|
||||
<&cpr_ro_sel00_pwrcl>,
|
||||
<&cpr_ro_sel01_pwrcl>,
|
||||
<&cpr_ro_sel02_pwrcl>;
|
||||
|
||||
nvmem-cell-names = "cpr_speed_bin",
|
||||
"cpr_fuse_revision",
|
||||
"cpr0_quotient1",
|
||||
"cpr0_quotient2",
|
||||
"cpr0_quotient3",
|
||||
"cpr0_quotient4",
|
||||
"cpr0_quotient5",
|
||||
"cpr0_quotient_offset2",
|
||||
"cpr0_quotient_offset3",
|
||||
"cpr0_quotient_offset4",
|
||||
"cpr0_quotient_offset5",
|
||||
"cpr0_init_voltage1",
|
||||
"cpr0_init_voltage2",
|
||||
"cpr0_init_voltage3",
|
||||
"cpr0_init_voltage4",
|
||||
"cpr0_init_voltage5",
|
||||
"cpr0_ring_osc1",
|
||||
"cpr0_ring_osc2",
|
||||
"cpr0_ring_osc3",
|
||||
"cpr0_ring_osc4",
|
||||
"cpr0_ring_osc5",
|
||||
"cpr1_quotient1",
|
||||
"cpr1_quotient2",
|
||||
"cpr1_quotient3",
|
||||
"cpr1_quotient_offset2",
|
||||
"cpr1_quotient_offset3",
|
||||
"cpr1_init_voltage1",
|
||||
"cpr1_init_voltage2",
|
||||
"cpr1_init_voltage3",
|
||||
"cpr1_ring_osc1",
|
||||
"cpr1_ring_osc2",
|
||||
"cpr1_ring_osc3";
|
||||
};
|
||||
|
||||
tsens: thermal-sensor@10ae000 {
|
||||
compatible = "qcom,sdm630-tsens", "qcom,tsens-v2";
|
||||
reg = <0x010ae000 0x1000>, /* TM */
|
||||
|
|
@ -1048,6 +1573,20 @@
|
|||
|
||||
gpu_sdm630_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-700000000 {
|
||||
opp-hz = /bits/ 64 <700000000>;
|
||||
opp-level = <RPM_SMD_LEVEL_TURBO>;
|
||||
opp-peak-kBps = <5184000>;
|
||||
opp-supported-hw = <0xFF>;
|
||||
};
|
||||
|
||||
/*
|
||||
* 775MHz is only available on default speed bin
|
||||
* or 0xA2 (speed bin 1). Though it cannot be used
|
||||
* for now due to interconnect framework not supporting
|
||||
* multiple frequencies at the same opp-level
|
||||
|
||||
opp-775000000 {
|
||||
opp-hz = /bits/ 64 <775000000>;
|
||||
opp-level = <RPM_SMD_LEVEL_TURBO>;
|
||||
|
|
@ -1090,6 +1629,11 @@
|
|||
opp-peak-kBps = <1200000>;
|
||||
opp-supported-hw = <0xFF>;
|
||||
};
|
||||
*/
|
||||
};
|
||||
|
||||
zap-shader {
|
||||
memory-region = <&zap_shader_region>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -1112,6 +1656,7 @@
|
|||
clock-names = "iface", "mem", "mem_iface";
|
||||
#global-interrupts = <2>;
|
||||
#iommu-cells = <1>;
|
||||
qcom,reset-nodisable-cbs = /bits/ 8 <2 3 4>;
|
||||
|
||||
interrupts =
|
||||
<GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
|
@ -1125,8 +1670,6 @@
|
|||
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpucc: clock-controller@5065000 {
|
||||
|
|
@ -1149,6 +1692,8 @@
|
|||
compatible = "qcom,sdm630-smmu-v2", "qcom,smmu-v2";
|
||||
reg = <0x05100000 0x40000>;
|
||||
#iommu-cells = <1>;
|
||||
qcom,bypass-cbndx = /bits/ 8 <12>;
|
||||
qcom,reset-nodisable-cbs = /bits/ 8 <13>;
|
||||
|
||||
#global-interrupts = <2>;
|
||||
interrupts =
|
||||
|
|
@ -1172,8 +1717,6 @@
|
|||
<GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spmi_bus: spmi@800f000 {
|
||||
|
|
@ -2061,8 +2604,6 @@
|
|||
<GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
adsp_pil: remoteproc@15700000 {
|
||||
|
|
@ -2224,8 +2765,8 @@
|
|||
|
||||
intc: interrupt-controller@17a00000 {
|
||||
compatible = "arm,gic-v3";
|
||||
reg = <0x17a00000 0x10000>, /* GICD */
|
||||
<0x17b00000 0x100000>; /* GICR * 8 */
|
||||
reg = <0x17a00000 0x10000>, /* GICD */
|
||||
<0x17b00000 0x100000>; /* GICR * 8 */
|
||||
#interrupt-cells = <3>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@
|
|||
qcom,pmic-id = <0x1001b 0x101011a 0x00 0x00 0x1001b 0x201011a 0x00 0x00 0x1001b 0x102001a 0x00 0x00>;
|
||||
};
|
||||
|
||||
&panel {
|
||||
compatible = "sony,mermaid-nt36672a-tianma";
|
||||
};
|
||||
|
||||
&sdc2_state_on {
|
||||
pinconf-clk {
|
||||
drive-strength = <14>;
|
||||
|
|
|
|||
717
arch/arm64/boot/dts/qcom/sdm660-xiaomi-platina.dts
Normal file
717
arch/arm64/boot/dts/qcom/sdm660-xiaomi-platina.dts
Normal file
|
|
@ -0,0 +1,717 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "sdm660.dtsi"
|
||||
#include "pm660.dtsi"
|
||||
#include "pm660l.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/input/gpio-keys.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
|
||||
|
||||
/ {
|
||||
model = "Xiaomi Mi 8 Lite";
|
||||
compatible = "xiaomi,platina", "qcom,sdm660";
|
||||
|
||||
aliases {
|
||||
serial0 = &blsp1_uart2;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
ramoops@ffc00000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0xffc00000 0x0 0x100000>;
|
||||
record-size = <0x10000>;
|
||||
console-size = <0x60000>;
|
||||
ftrace-size = <0x10000>;
|
||||
pmsg-size = <0x20000>;
|
||||
ecc-size = <16>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
debug_region@ffb00000 {
|
||||
reg = <0x00 0xffb00000 0x00 0x100000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
cdsp-region@94e00000 {
|
||||
reg = <0x00 0x94e00000 0x00 0x600000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
removed_region@85800000 {
|
||||
reg = <0x00 0x85800000 0x00 0x3700000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
|
||||
board_vbat: vbat-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VBAT";
|
||||
|
||||
regulator-min-microvolt = <4000000>;
|
||||
regulator-max-microvolt = <4000000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
cam_avdd_front_vreg: cam-avdd-front-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "cam-avdd-front-vreg";
|
||||
|
||||
regulator-min-microvolt = <3600000>;
|
||||
regulator-max-microvolt = <3600000>;
|
||||
startup-delay-us = <0>;
|
||||
enable-active-high;
|
||||
gpio = <&tlmm 49 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cam_avdd_front_default>;
|
||||
vin-supply = <&vreg_bob>;
|
||||
};
|
||||
|
||||
cam_actuator_rear_vreg: cam-actuator-rear-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "cam-actuator-rear-vreg";
|
||||
|
||||
regulator-min-microvolt = <3600000>;
|
||||
regulator-max-microvolt = <3600000>;
|
||||
startup-delay-us = <0>;
|
||||
enable-active-high;
|
||||
gpio = <&tlmm 50 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cam_actuator_rear_default>;
|
||||
vin-supply = <&vreg_bob>;
|
||||
};
|
||||
|
||||
cam_avdd_rear_vreg: cam-avdd-rear-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "cam-avdd-rear-vreg";
|
||||
|
||||
regulator-min-microvolt = <3600000>;
|
||||
regulator-max-microvolt = <3600000>;
|
||||
startup-delay-us = <0>;
|
||||
enable-active-high;
|
||||
gpio = <&tlmm 51 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cam_avdd_rear_default>;
|
||||
vin-supply = <&vreg_bob>;
|
||||
};
|
||||
|
||||
cam_dvdd_front_vreg: cam-dvdd-front-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "cam-dvdd-front-vreg";
|
||||
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
startup-delay-us = <0>;
|
||||
enable-active-high;
|
||||
gpio = <&pm660l_gpios 3 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cam_dvdd_front_default>;
|
||||
vin-supply = <&vreg_s5a_1p35>;
|
||||
};
|
||||
|
||||
cam_dvdd_rear_vreg: cam-dvdd-rear-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "cam-dvdd-rear-vreg";
|
||||
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
startup-delay-us = <0>;
|
||||
enable-active-high;
|
||||
gpio = <&pm660l_gpios 4 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cam_dvdd_rear_default>;
|
||||
vin-supply = <&vreg_s5a_1p35>;
|
||||
};
|
||||
|
||||
disp_vdd_vreg: disp-vdd-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "display-vdd";
|
||||
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
ts_vdd_vreg: ts-vdd-vreg {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "ts-vdd";
|
||||
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
startup-delay-us = <4000>;
|
||||
enable-active-high;
|
||||
regulator-boot-on;
|
||||
gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ts_vdd_default>;
|
||||
};
|
||||
|
||||
vph_pwr: vph-pwr-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vph_pwr";
|
||||
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
status = "okay";
|
||||
compatible = "gpio-keys";
|
||||
input-name = "gpio-keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vol_up {
|
||||
label = "Volume Up";
|
||||
gpios = <&pm660l_gpios 7 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
linux,code = <KEY_VOLUMEUP>;
|
||||
wakeup-source;
|
||||
debounce-interval = <15>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio-hall-sensor {
|
||||
compatible = "gpio-keys";
|
||||
label = "Hall effect sensor";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hall_sensor_default>;
|
||||
|
||||
hall-sensor {
|
||||
label = "Hall Effect Sensor";
|
||||
gpios = <&tlmm 75 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <EV_SW>;
|
||||
linux,code = <SW_LID>;
|
||||
linux,can-disable;
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Until we hook up type-c detection, we
|
||||
* have to stick with this. But it works.
|
||||
*/
|
||||
extcon_usb: extcon-usb {
|
||||
compatible = "linux,extcon-usb-gpio";
|
||||
id-gpio = <&tlmm 58 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&blsp_i2c2 {
|
||||
status = "okay";
|
||||
|
||||
/*
|
||||
* Two instances of SMB1355 charger: 0x8, 0xc but only
|
||||
* one SMB1355 chip is present on board. What's the
|
||||
* right address?
|
||||
*/
|
||||
};
|
||||
|
||||
&blsp1_uart2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rpm_requests {
|
||||
pm660l-regulators {
|
||||
compatible = "qcom,rpm-pm660l-regulators";
|
||||
|
||||
vdd_s1-supply = <&vph_pwr>;
|
||||
vdd_s2-supply = <&vph_pwr>;
|
||||
vdd_s3_s4-supply = <&vph_pwr>;
|
||||
vdd_s5-supply = <&vph_pwr>;
|
||||
vdd_s6-supply = <&vph_pwr>;
|
||||
|
||||
vdd_l1_l9_l10-supply = <&vreg_s2b_1p05>;
|
||||
vdd_l2-supply = <&vreg_bob>;
|
||||
vdd_l3_l5_l7_l8-supply = <&vreg_bob>;
|
||||
vdd_l4_l6-supply = <&vreg_bob>;
|
||||
vdd_bob-supply = <&vph_pwr>;
|
||||
|
||||
vreg_s1b_1p125: s1 {
|
||||
regulator-min-microvolt = <1125000>;
|
||||
regulator-max-microvolt = <1125000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_s2b_1p05: s2 {
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1050000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/*
|
||||
* At least on Nile's configuration, S3B/S4B (VDD_CX) and
|
||||
* S5B (VDD_MX) are managed only through RPM Power Domains.
|
||||
* Trying to set a voltage on the main supply will create
|
||||
* havoc and freeze the SoC.
|
||||
* In any case, reference voltages for these regulators are:
|
||||
* S3B/S4B: 0.870V
|
||||
* S5B: 0.915V
|
||||
*/
|
||||
|
||||
/* LDOs */
|
||||
vreg_l1b_0p925: l1 {
|
||||
regulator-min-microvolt = <920000>;
|
||||
regulator-max-microvolt = <928000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l2b_2p95: l2 {
|
||||
/*
|
||||
* This regulator supports 1.648 - 3.104V on this board
|
||||
* but we set a max voltage of anything less than 2.7V
|
||||
* to satisfy a condition in sdhci.c that will disable
|
||||
* 3.3V SDHCI signaling, which happens to be not really
|
||||
* supported on the Xperia Nile/Ganges platform.
|
||||
*/
|
||||
regulator-min-microvolt = <1648000>;
|
||||
regulator-max-microvolt = <2696000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l3b_3p3: l3 {
|
||||
regulator-min-microvolt = <3296000>;
|
||||
regulator-max-microvolt = <3312000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-min-microamp = <200>;
|
||||
regulator-max-microamp = <600000>;
|
||||
regulator-system-load = <100000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l4b_2p95: l4 {
|
||||
regulator-min-microvolt = <2944000>;
|
||||
regulator-max-microvolt = <2952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
|
||||
regulator-min-microamp = <200>;
|
||||
regulator-max-microamp = <600000>;
|
||||
regulator-system-load = <570000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
/*
|
||||
* Downstream specifies a range of 1721-3600mV,
|
||||
* but the only assigned consumers are SDHCI2 VMMC
|
||||
* and Coresight QPDI that both request pinned 2.95V.
|
||||
* Tighten the range to 1.8-3.328 (closest to 3.3) to
|
||||
* make the mmc driver happy.
|
||||
*/
|
||||
vreg_l5b_29p5: l5 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3328000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
regulator-system-load = <800000>;
|
||||
};
|
||||
|
||||
vreg_l7b_3p125: l7 {
|
||||
regulator-min-microvolt = <2704000>;
|
||||
regulator-max-microvolt = <3128000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l8b_3p3: l8 {
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <3400000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* L9B (870mV) is currently unused */
|
||||
/* L10B (915mV) is currently unused */
|
||||
|
||||
vreg_bob: bob {
|
||||
regulator-min-microvolt = <3304000>;
|
||||
regulator-max-microvolt = <3624000>;
|
||||
regulator-enable-ramp-delay = <500>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
pm660-regulators {
|
||||
compatible = "qcom,rpm-pm660-regulators";
|
||||
|
||||
vdd_s1-supply = <&vph_pwr>;
|
||||
vdd_s2-supply = <&vph_pwr>;
|
||||
vdd_s3-supply = <&vph_pwr>;
|
||||
vdd_s4-supply = <&vph_pwr>;
|
||||
vdd_s5-supply = <&vph_pwr>;
|
||||
vdd_s6-supply = <&vph_pwr>;
|
||||
|
||||
vdd_l1_l6_l7-supply = <&vreg_s5a_1p35>;
|
||||
vdd_l2_l3-supply = <&vreg_s2b_1p05>;
|
||||
vdd_l5-supply = <&vreg_s2b_1p05>;
|
||||
vdd_l8_l9_l10_l11_l12_l13_l14-supply = <&vreg_s4a_2p04>;
|
||||
vdd_l15_l16_l17_l18_l19-supply = <&vreg_bob>;
|
||||
|
||||
/*
|
||||
* S1A (FTAPC0), S2A (FTAPC1), S3A (HFAPC1) are managed
|
||||
* by the Core Power Reduction hardened (CPRh) and the
|
||||
* Operating State Manager (OSM) HW automatically.
|
||||
*/
|
||||
|
||||
vreg_s4a_2p04: s4 {
|
||||
regulator-min-microvolt = <2040000>;
|
||||
regulator-max-microvolt = <2040000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vreg_s5a_1p35: s5 {
|
||||
regulator-min-microvolt = <1224000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_s6a_0p87: s6 {
|
||||
regulator-min-microvolt = <504000>;
|
||||
regulator-max-microvolt = <992000>;
|
||||
regulator-enable-ramp-delay = <150>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* LDOs */
|
||||
vreg_l1a_1p225: l1 {
|
||||
regulator-min-microvolt = <1226000>;
|
||||
regulator-max-microvolt = <1250000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l2a_1p0: l2 {
|
||||
regulator-min-microvolt = <944000>;
|
||||
regulator-max-microvolt = <1008000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l3a_1p0: l3 {
|
||||
regulator-min-microvolt = <944000>;
|
||||
regulator-max-microvolt = <1008000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l5a_0p848: l5 {
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l6a_1p3: l6 {
|
||||
regulator-min-microvolt = <1304000>;
|
||||
regulator-max-microvolt = <1368000>;
|
||||
regulator-allow-set-load;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l7a_1p2: l7 {
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l8a_1p8: l8 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-system-load = <325000>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
|
||||
vreg_l9a_1p8: l9 {
|
||||
regulator-min-microvolt = <1804000>;
|
||||
regulator-max-microvolt = <1896000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l10a_1p8: l10 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
|
||||
vreg_l11a_1p8: l11 {
|
||||
regulator-min-microvolt = <1784000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l12a_1p8: l12 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l13a_1p8: l13 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1944000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vreg_l14a_1p8: l14 {
|
||||
regulator-min-microvolt = <1710000>;
|
||||
regulator-max-microvolt = <1952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l15a_1p8: l15 {
|
||||
regulator-min-microvolt = <1648000>;
|
||||
regulator-max-microvolt = <2952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* DRX: QM13111 */
|
||||
vreg_l16a_2p7: l16 {
|
||||
regulator-min-microvolt = <2704000>;
|
||||
regulator-max-microvolt = <2712000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
vreg_l17a_1p8: l17 {
|
||||
regulator-min-microvolt = <1648000>;
|
||||
regulator-max-microvolt = <2952000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
};
|
||||
|
||||
/* L18A (2.7V) is unused */
|
||||
|
||||
vreg_l19a_3p3: l19 {
|
||||
regulator-min-microvolt = <3312000>;
|
||||
regulator-max-microvolt = <3328000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-allow-set-load;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&sdhc_1 {
|
||||
status = "okay";
|
||||
supports-cqe;
|
||||
|
||||
mmc-ddr-1_8v;
|
||||
mmc-hs400-1_8v;
|
||||
mmc-hs400-enhanced-strobe;
|
||||
|
||||
vmmc-supply = <&vreg_l4b_2p95>;
|
||||
vqmmc-supply = <&vreg_l8a_1p8>;
|
||||
};
|
||||
|
||||
&sdhc_2 {
|
||||
status = "disabled";
|
||||
|
||||
vmmc-supply = <&vreg_l5b_29p5>;
|
||||
vqmmc-supply = <&vreg_l2b_2p95>;
|
||||
};
|
||||
|
||||
&pm660_gpios {
|
||||
nfc_clk_req_n: nfc-clkreq-n {
|
||||
pins = "gpio4";
|
||||
function = PMIC_GPIO_FUNC_NORMAL;
|
||||
bias-disable;
|
||||
input-enable;
|
||||
power-source = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&pm660l_gpios {
|
||||
cam_dvdd_front_default: cam-dvdd-front-default {
|
||||
pins = "gpio3";
|
||||
function = "normal";
|
||||
output-low;
|
||||
power-source = <0>;
|
||||
};
|
||||
|
||||
cam_dvdd_rear_default: cam-dvdd-rear-default {
|
||||
pins = "gpio4";
|
||||
function = "normal";
|
||||
output-low;
|
||||
power-source = <0>;
|
||||
};
|
||||
|
||||
vol_key_gpio_default: vol-key-gpio-default {
|
||||
pins = "gpio7";
|
||||
function = "normal";
|
||||
bias-pull-up;
|
||||
input-enable;
|
||||
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
gpio-reserved-ranges = <8 4>;
|
||||
|
||||
camera_rear_default: camera-rear-default {
|
||||
mclk0 {
|
||||
pins = "gpio32";
|
||||
function = "cam_mclk";
|
||||
drive-strength = <4>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
rst {
|
||||
pins = "gpio46";
|
||||
function = "gpio";
|
||||
drive-strength = <16>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
camera_front_default: camera-front-default {
|
||||
mclk1 {
|
||||
pins = "gpio33";
|
||||
function = "cam_mclk";
|
||||
drive-strength = <4>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
rst {
|
||||
pins = "gpio47";
|
||||
function = "gpio";
|
||||
drive-strength = <16>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
camera_front_iris_default: camera-front-iris-default {
|
||||
mclk1 {
|
||||
pins = "gpio35";
|
||||
function = "cam_mclk";
|
||||
drive-strength = <4>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
rst {
|
||||
pins = "gpio52";
|
||||
function = "gpio";
|
||||
drive-strength = <16>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
cam_avdd_front_default: cam-avdd-front-default {
|
||||
pins = "gpio49";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
cam_actuator_rear_default: cam-actuator-rear-default {
|
||||
pins = "gpio50";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
cam_avdd_rear_default: cam-avdd-rear-default {
|
||||
pins = "gpio51";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <2>;
|
||||
};
|
||||
|
||||
panel_reset_n: panel-rst-n {
|
||||
pins = "gpio53";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mdp_vsync_n: mdp-vsync-n {
|
||||
pins = "gpio59";
|
||||
function = "mdp_vsync";
|
||||
drive-strength = <2>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
ts_rst_n: ts-rst-n {
|
||||
pins = "gpio66";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <8>;
|
||||
};
|
||||
|
||||
ts_int_active: ts-int-active {
|
||||
pins = "gpio67";
|
||||
drive-strength = <16>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
ts_vdd_default: ts-vdd-default {
|
||||
pins = "gpio73";
|
||||
function = "gpio";
|
||||
bias-disable;
|
||||
drive-strength = <8>;
|
||||
};
|
||||
|
||||
hall_sensor_default: hall-sensor-default {
|
||||
pins = "gpio75";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
input-enable;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb3_dwc3 {
|
||||
dr_mode = "peripheral";
|
||||
extcon = <&extcon_usb>;
|
||||
};
|
||||
|
|
@ -593,6 +593,30 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_lpg {
|
||||
status = "okay";
|
||||
|
||||
qcom,power-source = <1>;
|
||||
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
label = "green:user3";
|
||||
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
led@4 {
|
||||
reg = <4>;
|
||||
label = "green:user2";
|
||||
};
|
||||
|
||||
led@5 {
|
||||
reg = <5>;
|
||||
label = "green:user1";
|
||||
};
|
||||
};
|
||||
|
||||
/* QUAT I2S Uses 4 I2S SD Lines for audio on LT9611 HDMI Bridge */
|
||||
&q6afedai {
|
||||
qi2s@22 {
|
||||
|
|
|
|||
|
|
@ -447,6 +447,19 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
status = "okay";
|
||||
|
||||
qcom,max-voltage-uv = <4400000>;
|
||||
qcom,min-voltage-uv = <3700000>;
|
||||
};
|
||||
|
||||
&pmi8998_haptics {
|
||||
status = "okay";
|
||||
|
||||
qcom,wave-play-rate-us = <4255>;
|
||||
};
|
||||
|
||||
&qupv3_id_1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
@ -616,7 +629,7 @@
|
|||
pins = "gpio6", "gpio25", "gpio26";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-disable = <0>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@
|
|||
compatible = "oneplus,enchilada", "qcom,sdm845";
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
qcom,battery-capacity-ua = <3300000>;
|
||||
};
|
||||
|
||||
&display_panel {
|
||||
status = "okay";
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
compatible = "samsung,s6e3fc2x01";
|
||||
};
|
||||
|
||||
&pmi8998_fg {
|
||||
qcom,battery-capacity-ua = <3700000>;
|
||||
};
|
||||
|
||||
&rmi4_f12 {
|
||||
touchscreen-y-mm = <148>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -335,6 +335,11 @@
|
|||
};
|
||||
};
|
||||
|
||||
&pmi8998_haptics {
|
||||
status = "okay";
|
||||
qcom,wave-play-rate-us = <4878>;
|
||||
};
|
||||
|
||||
&qupv3_id_0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
5851
arch/arm64/configs/msm8998_defconfig
Normal file
5851
arch/arm64/configs/msm8998_defconfig
Normal file
File diff suppressed because it is too large
Load diff
5742
arch/arm64/configs/oneplus5_defconfig
Normal file
5742
arch/arm64/configs/oneplus5_defconfig
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -810,15 +810,20 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = {
|
|||
.num_clks = ARRAY_SIZE(qcs404_clks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin,
|
||||
3);
|
||||
DEFINE_CLK_SMD_RPM_BRANCH(msm8998, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
|
||||
19200000);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk3, ln_bb_clk3_a, 3);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, 3);
|
||||
DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk,
|
||||
QCOM_SMD_RPM_AGGR_CLK, 1);
|
||||
DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk,
|
||||
QCOM_SMD_RPM_AGGR_CLK, 2);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6);
|
||||
|
||||
static struct clk_smd_rpm *msm8998_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
[RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
|
||||
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
|
||||
|
|
@ -831,12 +836,22 @@ static struct clk_smd_rpm *msm8998_clks[] = {
|
|||
[RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk,
|
||||
[RPM_SMD_DIV_CLK1] = &msm8974_div_clk1,
|
||||
[RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1,
|
||||
[RPM_SMD_DIV_CLK2] = &msm8974_div_clk2,
|
||||
[RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2,
|
||||
[RPM_SMD_DIV_CLK3] = &msm8992_div_clk3,
|
||||
[RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a,
|
||||
[RPM_SMD_IPA_CLK] = &msm8976_ipa_clk,
|
||||
[RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk,
|
||||
[RPM_SMD_LN_BB_CLK1] = &msm8916_bb_clk1,
|
||||
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
|
||||
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
|
||||
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
|
||||
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
|
||||
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
|
||||
[RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk,
|
||||
|
|
@ -849,10 +864,14 @@ static struct clk_smd_rpm *msm8998_clks[] = {
|
|||
[RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,
|
||||
[RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,
|
||||
[RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,
|
||||
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
|
||||
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
|
||||
[RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
|
||||
[RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
|
||||
[RPM_SMD_RF_CLK3] = &msm8998_rf_clk3,
|
||||
[RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a,
|
||||
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
|
||||
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
|
||||
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
|
||||
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
|
||||
[RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin,
|
||||
[RPM_SMD_RF_CLK3_A_PIN] = &msm8998_rf_clk3_a_pin,
|
||||
};
|
||||
|
|
@ -862,14 +881,9 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = {
|
|||
.num_clks = ARRAY_SIZE(msm8998_clks),
|
||||
};
|
||||
|
||||
DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
|
||||
19200000);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, ln_bb_clk3_pin_a, 3);
|
||||
|
||||
static struct clk_smd_rpm *sdm660_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk,
|
||||
[RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk,
|
||||
|
|
@ -896,16 +910,16 @@ static struct clk_smd_rpm *sdm660_clks[] = {
|
|||
[RPM_SMD_LN_BB_A_CLK] = &msm8916_bb_clk1_a,
|
||||
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
|
||||
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
|
||||
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
|
||||
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
|
||||
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
|
||||
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a,
|
||||
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
|
||||
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
|
||||
};
|
||||
|
||||
static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
|
||||
|
|
@ -914,8 +928,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
|
|||
};
|
||||
|
||||
static struct clk_smd_rpm *mdm9607_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
|
||||
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
|
|
@ -936,8 +950,8 @@ static const struct rpm_smd_clk_desc rpm_clk_mdm9607 = {
|
|||
};
|
||||
|
||||
static struct clk_smd_rpm *msm8953_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
|
||||
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
|
||||
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
|
||||
|
|
@ -985,8 +999,8 @@ DEFINE_CLK_SMD_RPM(sm6125, snoc_lpass_clk, snoc_lpass_a_clk,
|
|||
QCOM_SMD_RPM_BUS_CLK, 5);
|
||||
|
||||
static struct clk_smd_rpm *sm6125_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
|
|
@ -1007,8 +1021,8 @@ static struct clk_smd_rpm *sm6125_clks[] = {
|
|||
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
|
||||
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
|
||||
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
|
||||
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
|
||||
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
|
||||
[RPM_SMD_QUP_CLK] = &sm6125_qup_clk,
|
||||
[RPM_SMD_QUP_A_CLK] = &sm6125_qup_a_clk,
|
||||
[RPM_SMD_MMRT_CLK] = &sm6125_mmrt_clk,
|
||||
|
|
@ -1028,8 +1042,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sm6125 = {
|
|||
|
||||
/* SM6115 */
|
||||
static struct clk_smd_rpm *sm6115_clks[] = {
|
||||
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
|
||||
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
|
||||
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
|
||||
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ static struct clk_fixed_factor xo = {
|
|||
.div = 1,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "xo",
|
||||
.parent_names = (const char *[]){ "xo_board" },
|
||||
.parent_names = (const char *[]){ "bi_tcxo" },
|
||||
.num_parents = 1,
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
},
|
||||
|
|
@ -2041,6 +2041,7 @@ static struct clk_branch gcc_bimc_gfx_clk = {
|
|||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gcc_bimc_gfx_clk",
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
|
@ -2181,6 +2182,7 @@ static struct clk_rcg2 hmss_gpll0_clk_src = {
|
|||
.name = "hmss_gpll0_clk_src",
|
||||
.parent_names = gcc_parent_names_1,
|
||||
.num_parents = ARRAY_SIZE(gcc_parent_names_1),
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_rcg2_ops,
|
||||
},
|
||||
};
|
||||
|
|
@ -2784,6 +2786,43 @@ static struct clk_branch gcc_rx1_usb2_clkref_clk = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_branch hlos1_vote_lpass_core_smmu_clk = {
|
||||
.halt_reg = 0x7D010,
|
||||
.clkr = {
|
||||
.enable_reg = 0x7D010,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hlos1_vote_lpass_core_smmu_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch hlos1_vote_lpass_adsp_smmu_clk = {
|
||||
.halt_reg = 0x7D014,
|
||||
.clkr = {
|
||||
.enable_reg = 0x7D014,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hlos1_vote_lpass_adsp_smmu_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
|
||||
.halt_reg = 0x8A040,
|
||||
.clkr = {
|
||||
.enable_reg = 0x8A040,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "gcc_mss_q6_bimc_axi_clk",
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct gdsc pcie_0_gdsc = {
|
||||
.gdscr = 0x6b004,
|
||||
.gds_hw_ctrl = 0x0,
|
||||
|
|
@ -2814,6 +2853,26 @@ static struct gdsc usb_30_gdsc = {
|
|||
.flags = VOTABLE,
|
||||
};
|
||||
|
||||
static struct gdsc hlos1_vote_lpass_adsp = {
|
||||
.gdscr = 0x7d034,
|
||||
.gds_hw_ctrl = 0x0,
|
||||
.pd = {
|
||||
.name = "lpass_adsp_gdsc",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = VOTABLE,
|
||||
};
|
||||
|
||||
static struct gdsc hlos1_vote_lpass_core = {
|
||||
.gdscr = 0x7d038,
|
||||
.gds_hw_ctrl = 0x0,
|
||||
.pd = {
|
||||
.name = "lpass_core_gdsc",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = ALWAYS_ON,
|
||||
};
|
||||
|
||||
static struct clk_regmap *gcc_msm8998_clocks[] = {
|
||||
[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
|
||||
[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
|
||||
|
|
@ -2987,12 +3046,17 @@ static struct clk_regmap *gcc_msm8998_clocks[] = {
|
|||
[GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
|
||||
[GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
|
||||
[HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
|
||||
[GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
|
||||
[HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = &hlos1_vote_lpass_core_smmu_clk.clkr,
|
||||
[HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &hlos1_vote_lpass_adsp_smmu_clk.clkr,
|
||||
};
|
||||
|
||||
static struct gdsc *gcc_msm8998_gdscs[] = {
|
||||
[PCIE_0_GDSC] = &pcie_0_gdsc,
|
||||
[UFS_GDSC] = &ufs_gdsc,
|
||||
[USB_30_GDSC] = &usb_30_gdsc,
|
||||
[LPASS_ADSP_GDSC] = &hlos1_vote_lpass_adsp,
|
||||
[LPASS_CORE_GDSC] = &hlos1_vote_lpass_core,
|
||||
};
|
||||
|
||||
static const struct qcom_reset_map gcc_msm8998_resets[] = {
|
||||
|
|
@ -3148,6 +3212,14 @@ static int gcc_msm8998_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* GCC_MMSS_MISC - GCC_GPU_MISC:
|
||||
* 1. Disable the GPLL0 active input to MMSS and GPU
|
||||
* 2. Select clk division 1 (CLK/2)
|
||||
*/
|
||||
regmap_write(regmap, 0x0902C, 0x10003); /* MMSS*/
|
||||
regmap_write(regmap, 0x71028, 0x10003); /* GPU */
|
||||
|
||||
return qcom_cc_really_probe(pdev, &gcc_msm8998_desc, regmap);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ static struct clk_rcg2 byte0_clk_src = {
|
|||
.parent_data = mmss_xo_dsibyte,
|
||||
.num_parents = 4,
|
||||
.ops = &clk_byte2_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -533,7 +533,7 @@ static struct clk_rcg2 byte1_clk_src = {
|
|||
.parent_data = mmss_xo_dsibyte,
|
||||
.num_parents = 4,
|
||||
.ops = &clk_byte2_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -1084,7 +1084,7 @@ static struct clk_rcg2 pclk0_clk_src = {
|
|||
.parent_data = mmss_xo_dsi0pll_dsi1pll,
|
||||
.num_parents = 4,
|
||||
.ops = &clk_pixel_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -1098,7 +1098,7 @@ static struct clk_rcg2 pclk1_clk_src = {
|
|||
.parent_data = mmss_xo_dsi0pll_dsi1pll,
|
||||
.num_parents = 4,
|
||||
.ops = &clk_pixel_ops,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -136,11 +136,15 @@ static const struct of_device_id blocklist[] __initconst = {
|
|||
|
||||
{ .compatible = "qcom,apq8096", },
|
||||
{ .compatible = "qcom,msm8996", },
|
||||
{ .compatible = "qcom,msm8998", },
|
||||
{ .compatible = "qcom,qcs404", },
|
||||
{ .compatible = "qcom,sa8155p" },
|
||||
{ .compatible = "qcom,sc7180", },
|
||||
{ .compatible = "qcom,sc7280", },
|
||||
{ .compatible = "qcom,sc8180x", },
|
||||
{ .compatible = "qcom,sdm630", },
|
||||
{ .compatible = "qcom,sdm636", },
|
||||
{ .compatible = "qcom,sdm660", },
|
||||
{ .compatible = "qcom,sdm845", },
|
||||
{ .compatible = "qcom,sm6350", },
|
||||
{ .compatible = "qcom,sm8150", },
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -112,6 +112,7 @@ config ARM_QCOM_SPM_CPUIDLE
|
|||
select CPU_IDLE_MULTIPLE_DRIVERS
|
||||
select DT_IDLE_STATES
|
||||
select QCOM_SCM
|
||||
select QCOM_SPM
|
||||
help
|
||||
Select this to enable cpuidle for Qualcomm processors.
|
||||
The Subsystem Power Manager (SPM) controls low power modes for the
|
||||
|
|
|
|||
|
|
@ -18,158 +18,18 @@
|
|||
#include <linux/cpuidle.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
#include <soc/qcom/spm.h>
|
||||
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include "dt_idle_states.h"
|
||||
|
||||
#define MAX_PMIC_DATA 2
|
||||
#define MAX_SEQ_DATA 64
|
||||
#define SPM_CTL_INDEX 0x7f
|
||||
#define SPM_CTL_INDEX_SHIFT 4
|
||||
#define SPM_CTL_EN BIT(0)
|
||||
|
||||
enum pm_sleep_mode {
|
||||
PM_SLEEP_MODE_STBY,
|
||||
PM_SLEEP_MODE_RET,
|
||||
PM_SLEEP_MODE_SPC,
|
||||
PM_SLEEP_MODE_PC,
|
||||
PM_SLEEP_MODE_NR,
|
||||
};
|
||||
|
||||
enum spm_reg {
|
||||
SPM_REG_CFG,
|
||||
SPM_REG_SPM_CTL,
|
||||
SPM_REG_DLY,
|
||||
SPM_REG_PMIC_DLY,
|
||||
SPM_REG_PMIC_DATA_0,
|
||||
SPM_REG_PMIC_DATA_1,
|
||||
SPM_REG_VCTL,
|
||||
SPM_REG_SEQ_ENTRY,
|
||||
SPM_REG_SPM_STS,
|
||||
SPM_REG_PMIC_STS,
|
||||
SPM_REG_NR,
|
||||
};
|
||||
|
||||
struct spm_reg_data {
|
||||
const u8 *reg_offset;
|
||||
u32 spm_cfg;
|
||||
u32 spm_dly;
|
||||
u32 pmic_dly;
|
||||
u32 pmic_data[MAX_PMIC_DATA];
|
||||
u8 seq[MAX_SEQ_DATA];
|
||||
u8 start_index[PM_SLEEP_MODE_NR];
|
||||
};
|
||||
|
||||
struct spm_driver_data {
|
||||
struct cpuidle_qcom_spm_data {
|
||||
struct cpuidle_driver cpuidle_driver;
|
||||
void __iomem *reg_base;
|
||||
const struct spm_reg_data *reg_data;
|
||||
struct spm_driver_data *spm;
|
||||
};
|
||||
|
||||
static const u8 spm_reg_offset_v2_1[SPM_REG_NR] = {
|
||||
[SPM_REG_CFG] = 0x08,
|
||||
[SPM_REG_SPM_CTL] = 0x30,
|
||||
[SPM_REG_DLY] = 0x34,
|
||||
[SPM_REG_SEQ_ENTRY] = 0x80,
|
||||
};
|
||||
|
||||
/* SPM register data for 8974, 8084 */
|
||||
static const struct spm_reg_data spm_reg_8974_8084_cpu = {
|
||||
.reg_offset = spm_reg_offset_v2_1,
|
||||
.spm_cfg = 0x1,
|
||||
.spm_dly = 0x3C102800,
|
||||
.seq = { 0x03, 0x0B, 0x0F, 0x00, 0x20, 0x80, 0x10, 0xE8, 0x5B, 0x03,
|
||||
0x3B, 0xE8, 0x5B, 0x82, 0x10, 0x0B, 0x30, 0x06, 0x26, 0x30,
|
||||
0x0F },
|
||||
.start_index[PM_SLEEP_MODE_STBY] = 0,
|
||||
.start_index[PM_SLEEP_MODE_SPC] = 3,
|
||||
};
|
||||
|
||||
/* SPM register data for 8226 */
|
||||
static const struct spm_reg_data spm_reg_8226_cpu = {
|
||||
.reg_offset = spm_reg_offset_v2_1,
|
||||
.spm_cfg = 0x0,
|
||||
.spm_dly = 0x3C102800,
|
||||
.seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90,
|
||||
0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B,
|
||||
0x80, 0x10, 0x26, 0x30, 0x0F },
|
||||
.start_index[PM_SLEEP_MODE_STBY] = 0,
|
||||
.start_index[PM_SLEEP_MODE_SPC] = 5,
|
||||
};
|
||||
|
||||
static const u8 spm_reg_offset_v1_1[SPM_REG_NR] = {
|
||||
[SPM_REG_CFG] = 0x08,
|
||||
[SPM_REG_SPM_CTL] = 0x20,
|
||||
[SPM_REG_PMIC_DLY] = 0x24,
|
||||
[SPM_REG_PMIC_DATA_0] = 0x28,
|
||||
[SPM_REG_PMIC_DATA_1] = 0x2C,
|
||||
[SPM_REG_SEQ_ENTRY] = 0x80,
|
||||
};
|
||||
|
||||
/* SPM register data for 8064 */
|
||||
static const struct spm_reg_data spm_reg_8064_cpu = {
|
||||
.reg_offset = spm_reg_offset_v1_1,
|
||||
.spm_cfg = 0x1F,
|
||||
.pmic_dly = 0x02020004,
|
||||
.pmic_data[0] = 0x0084009C,
|
||||
.pmic_data[1] = 0x00A4001C,
|
||||
.seq = { 0x03, 0x0F, 0x00, 0x24, 0x54, 0x10, 0x09, 0x03, 0x01,
|
||||
0x10, 0x54, 0x30, 0x0C, 0x24, 0x30, 0x0F },
|
||||
.start_index[PM_SLEEP_MODE_STBY] = 0,
|
||||
.start_index[PM_SLEEP_MODE_SPC] = 2,
|
||||
};
|
||||
|
||||
static inline void spm_register_write(struct spm_driver_data *drv,
|
||||
enum spm_reg reg, u32 val)
|
||||
{
|
||||
if (drv->reg_data->reg_offset[reg])
|
||||
writel_relaxed(val, drv->reg_base +
|
||||
drv->reg_data->reg_offset[reg]);
|
||||
}
|
||||
|
||||
/* Ensure a guaranteed write, before return */
|
||||
static inline void spm_register_write_sync(struct spm_driver_data *drv,
|
||||
enum spm_reg reg, u32 val)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
if (!drv->reg_data->reg_offset[reg])
|
||||
return;
|
||||
|
||||
do {
|
||||
writel_relaxed(val, drv->reg_base +
|
||||
drv->reg_data->reg_offset[reg]);
|
||||
ret = readl_relaxed(drv->reg_base +
|
||||
drv->reg_data->reg_offset[reg]);
|
||||
if (ret == val)
|
||||
break;
|
||||
cpu_relax();
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static inline u32 spm_register_read(struct spm_driver_data *drv,
|
||||
enum spm_reg reg)
|
||||
{
|
||||
return readl_relaxed(drv->reg_base + drv->reg_data->reg_offset[reg]);
|
||||
}
|
||||
|
||||
static void spm_set_low_power_mode(struct spm_driver_data *drv,
|
||||
enum pm_sleep_mode mode)
|
||||
{
|
||||
u32 start_index;
|
||||
u32 ctl_val;
|
||||
|
||||
start_index = drv->reg_data->start_index[mode];
|
||||
|
||||
ctl_val = spm_register_read(drv, SPM_REG_SPM_CTL);
|
||||
ctl_val &= ~(SPM_CTL_INDEX << SPM_CTL_INDEX_SHIFT);
|
||||
ctl_val |= start_index << SPM_CTL_INDEX_SHIFT;
|
||||
ctl_val |= SPM_CTL_EN;
|
||||
spm_register_write_sync(drv, SPM_REG_SPM_CTL, ctl_val);
|
||||
}
|
||||
|
||||
static int qcom_pm_collapse(unsigned long int unused)
|
||||
{
|
||||
qcom_scm_cpu_power_down(QCOM_SCM_CPU_PWR_DOWN_L2_ON);
|
||||
|
|
@ -201,10 +61,10 @@ static int qcom_cpu_spc(struct spm_driver_data *drv)
|
|||
static int spm_enter_idle_state(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int idx)
|
||||
{
|
||||
struct spm_driver_data *data = container_of(drv, struct spm_driver_data,
|
||||
cpuidle_driver);
|
||||
struct cpuidle_qcom_spm_data *data = container_of(drv, struct cpuidle_qcom_spm_data,
|
||||
cpuidle_driver);
|
||||
|
||||
return CPU_PM_CPU_IDLE_ENTER_PARAM(qcom_cpu_spc, idx, data);
|
||||
return CPU_PM_CPU_IDLE_ENTER_PARAM(qcom_cpu_spc, idx, data->spm);
|
||||
}
|
||||
|
||||
static struct cpuidle_driver qcom_spm_idle_driver = {
|
||||
|
|
@ -225,134 +85,92 @@ static const struct of_device_id qcom_idle_state_match[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
static int spm_cpuidle_init(struct cpuidle_driver *drv, int cpu)
|
||||
static int spm_cpuidle_register(struct device *cpuidle_dev, int cpu)
|
||||
{
|
||||
struct platform_device *pdev = NULL;
|
||||
struct device_node *cpu_node, *saw_node;
|
||||
struct cpuidle_qcom_spm_data *data = NULL;
|
||||
int ret;
|
||||
|
||||
memcpy(drv, &qcom_spm_idle_driver, sizeof(*drv));
|
||||
drv->cpumask = (struct cpumask *)cpumask_of(cpu);
|
||||
cpu_node = of_cpu_device_node_get(cpu);
|
||||
if (!cpu_node)
|
||||
return -ENODEV;
|
||||
|
||||
/* Parse idle states from device tree */
|
||||
ret = dt_init_idle_driver(drv, qcom_idle_state_match, 1);
|
||||
saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
|
||||
if (!saw_node)
|
||||
return -ENODEV;
|
||||
|
||||
pdev = of_find_device_by_node(saw_node);
|
||||
of_node_put(saw_node);
|
||||
of_node_put(cpu_node);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(cpuidle_dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->spm = dev_get_drvdata(&pdev->dev);
|
||||
if (!data->spm)
|
||||
return -EINVAL;
|
||||
|
||||
data->cpuidle_driver = qcom_spm_idle_driver;
|
||||
data->cpuidle_driver.cpumask = (struct cpumask *)cpumask_of(cpu);
|
||||
|
||||
ret = dt_init_idle_driver(&data->cpuidle_driver,
|
||||
qcom_idle_state_match, 1);
|
||||
if (ret <= 0)
|
||||
return ret ? : -ENODEV;
|
||||
|
||||
/* We have atleast one power down mode */
|
||||
return qcom_scm_set_warm_boot_addr(cpu_resume_arm, drv->cpumask);
|
||||
ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm, cpumask_of(cpu));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return cpuidle_register(&data->cpuidle_driver, NULL);
|
||||
}
|
||||
|
||||
static struct spm_driver_data *spm_get_drv(struct platform_device *pdev,
|
||||
int *spm_cpu)
|
||||
static int spm_cpuidle_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spm_driver_data *drv = NULL;
|
||||
struct device_node *cpu_node, *saw_node;
|
||||
int cpu;
|
||||
bool found = 0;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
cpu_node = of_cpu_device_node_get(cpu);
|
||||
if (!cpu_node)
|
||||
continue;
|
||||
saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
|
||||
found = (saw_node == pdev->dev.of_node);
|
||||
of_node_put(saw_node);
|
||||
of_node_put(cpu_node);
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
|
||||
if (drv)
|
||||
*spm_cpu = cpu;
|
||||
}
|
||||
|
||||
return drv;
|
||||
}
|
||||
|
||||
static const struct of_device_id spm_match_table[] = {
|
||||
{ .compatible = "qcom,msm8226-saw2-v2.1-cpu",
|
||||
.data = &spm_reg_8226_cpu },
|
||||
{ .compatible = "qcom,msm8974-saw2-v2.1-cpu",
|
||||
.data = &spm_reg_8974_8084_cpu },
|
||||
{ .compatible = "qcom,apq8084-saw2-v2.1-cpu",
|
||||
.data = &spm_reg_8974_8084_cpu },
|
||||
{ .compatible = "qcom,apq8064-saw2-v1.1-cpu",
|
||||
.data = &spm_reg_8064_cpu },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int spm_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spm_driver_data *drv;
|
||||
struct resource *res;
|
||||
const struct of_device_id *match_id;
|
||||
void __iomem *addr;
|
||||
int cpu, ret;
|
||||
|
||||
if (!qcom_scm_is_available())
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
drv = spm_get_drv(pdev, &cpu);
|
||||
if (!drv)
|
||||
return -EINVAL;
|
||||
platform_set_drvdata(pdev, drv);
|
||||
for_each_possible_cpu(cpu) {
|
||||
ret = spm_cpuidle_register(&pdev->dev, cpu);
|
||||
if (ret && ret != -ENODEV) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot register for CPU%d: %d\n", cpu, ret);
|
||||
}
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
drv->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(drv->reg_base))
|
||||
return PTR_ERR(drv->reg_base);
|
||||
|
||||
match_id = of_match_node(spm_match_table, pdev->dev.of_node);
|
||||
if (!match_id)
|
||||
return -ENODEV;
|
||||
|
||||
drv->reg_data = match_id->data;
|
||||
|
||||
ret = spm_cpuidle_init(&drv->cpuidle_driver, cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Write the SPM sequences first.. */
|
||||
addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY];
|
||||
__iowrite32_copy(addr, drv->reg_data->seq,
|
||||
ARRAY_SIZE(drv->reg_data->seq) / 4);
|
||||
|
||||
/*
|
||||
* ..and then the control registers.
|
||||
* On some SoC if the control registers are written first and if the
|
||||
* CPU was held in reset, the reset signal could trigger the SPM state
|
||||
* machine, before the sequences are completely written.
|
||||
*/
|
||||
spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg);
|
||||
spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly);
|
||||
spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly);
|
||||
spm_register_write(drv, SPM_REG_PMIC_DATA_0,
|
||||
drv->reg_data->pmic_data[0]);
|
||||
spm_register_write(drv, SPM_REG_PMIC_DATA_1,
|
||||
drv->reg_data->pmic_data[1]);
|
||||
|
||||
/* Set up Standby as the default low power mode */
|
||||
spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY);
|
||||
|
||||
return cpuidle_register(&drv->cpuidle_driver, NULL);
|
||||
}
|
||||
|
||||
static int spm_dev_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spm_driver_data *drv = platform_get_drvdata(pdev);
|
||||
|
||||
cpuidle_unregister(&drv->cpuidle_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver spm_driver = {
|
||||
.probe = spm_dev_probe,
|
||||
.remove = spm_dev_remove,
|
||||
static struct platform_driver spm_cpuidle_driver = {
|
||||
.probe = spm_cpuidle_drv_probe,
|
||||
.driver = {
|
||||
.name = "saw",
|
||||
.of_match_table = spm_match_table,
|
||||
.name = "qcom-spm-cpuidle",
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(spm_driver);
|
||||
static int __init qcom_spm_cpuidle_init(void)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&spm_cpuidle_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pdev = platform_device_register_simple("qcom-spm-cpuidle",
|
||||
-1, NULL, 0);
|
||||
if (IS_ERR(pdev)) {
|
||||
platform_driver_unregister(&spm_cpuidle_driver);
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(qcom_spm_cpuidle_init);
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ config DRM_MSM_DSI_14NM_PHY
|
|||
Choose this option if DSI PHY on 8996 is used on the platform.
|
||||
|
||||
config DRM_MSM_DSI_10NM_PHY
|
||||
bool "Enable DSI 10nm PHY driver in MSM DRM (used by SDM845)"
|
||||
bool "Enable DSI 10nm PHY driver in MSM DRM (used by MSM8998/SDM845)"
|
||||
depends on DRM_MSM_DSI
|
||||
default y
|
||||
help
|
||||
|
|
|
|||
|
|
@ -122,6 +122,48 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
|
|||
msm_gpu_retire(gpu);
|
||||
}
|
||||
|
||||
static void a5xx_set_pagetable(struct a5xx_gpu *a5xx_gpu,
|
||||
struct msm_ringbuffer *ring, struct msm_file_private *ctx)
|
||||
{
|
||||
phys_addr_t ttbr;
|
||||
u32 asid;
|
||||
u64 memptr = rbmemptr(ring, ttbr0);
|
||||
|
||||
if (ctx == a5xx_gpu->cur_ctx)
|
||||
return;
|
||||
|
||||
if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid))
|
||||
return;
|
||||
|
||||
/* Execute the table update */
|
||||
OUT_PKT7(ring, CP_SMMU_TABLE_UPDATE, 3);
|
||||
OUT_RING(ring, CP_SMMU_TABLE_UPDATE_0_TTBR0_LO(lower_32_bits(ttbr)));
|
||||
|
||||
OUT_RING(ring,
|
||||
CP_SMMU_TABLE_UPDATE_1_TTBR0_HI(upper_32_bits(ttbr)) |
|
||||
CP_SMMU_TABLE_UPDATE_1_ASID(asid));
|
||||
OUT_RING(ring, CP_SMMU_TABLE_UPDATE_2_CONTEXTIDR(0));
|
||||
|
||||
/*
|
||||
* Write the new TTBR0 to the memstore. This is good for debugging.
|
||||
*/
|
||||
OUT_PKT7(ring, CP_MEM_WRITE, 4);
|
||||
OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr)));
|
||||
OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr)));
|
||||
OUT_RING(ring, lower_32_bits(ttbr));
|
||||
OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr));
|
||||
|
||||
/*
|
||||
* And finally, trigger a uche flush to be sure there isn't anything
|
||||
* lingering in that part of the GPU
|
||||
*/
|
||||
|
||||
OUT_PKT7(ring, CP_EVENT_WRITE, 1);
|
||||
OUT_RING(ring, 0x31);
|
||||
|
||||
a5xx_gpu->cur_ctx = ctx;
|
||||
}
|
||||
|
||||
static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
{
|
||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||
|
|
@ -153,13 +195,17 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
OUT_RING(ring, 1);
|
||||
|
||||
/* Enable local preemption for finegrain preemption */
|
||||
OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1);
|
||||
OUT_RING(ring, 0x02);
|
||||
//OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1);
|
||||
//OUT_RING(ring, 0x02);
|
||||
OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1);
|
||||
OUT_RING(ring, 0x01);
|
||||
|
||||
/* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */
|
||||
OUT_PKT7(ring, CP_YIELD_ENABLE, 1);
|
||||
OUT_RING(ring, 0x02);
|
||||
|
||||
a5xx_set_pagetable(a5xx_gpu, ring, submit->queue->ctx);
|
||||
|
||||
/* Submit the commands */
|
||||
for (i = 0; i < submit->nr_cmds; i++) {
|
||||
switch (submit->cmd[i].type) {
|
||||
|
|
@ -563,8 +609,12 @@ static void a5xx_ucode_check_version(struct a5xx_gpu *a5xx_gpu,
|
|||
* has been patched. The actual version is in dword [3] but we only care
|
||||
* about the patchlevel which is the lowest nibble of dword [3]
|
||||
*/
|
||||
if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1)
|
||||
if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) {
|
||||
pr_err("adreno HAS WHEREAMI!\n");
|
||||
a5xx_gpu->has_whereami = true;
|
||||
} else {
|
||||
pr_err("adreno has no whereami support\n");
|
||||
}
|
||||
|
||||
msm_gem_put_vaddr(obj);
|
||||
}
|
||||
|
|
@ -936,6 +986,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
|
|||
a5xx_preempt_fini(gpu);
|
||||
gpu->nr_rings = 1;
|
||||
}
|
||||
a5xx_gpu->cur_ctx = NULL;
|
||||
|
||||
a5xx_preempt_hw_init(gpu);
|
||||
|
||||
|
|
@ -1684,6 +1735,20 @@ static uint32_t a5xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
|
|||
return ring->memptrs->rptr = gpu_read(gpu, REG_A5XX_CP_RB_RPTR);
|
||||
}
|
||||
|
||||
static struct msm_gem_address_space *
|
||||
a5xx_create_private_address_space(struct msm_gpu *gpu)
|
||||
{
|
||||
struct msm_mmu *mmu;
|
||||
|
||||
mmu = msm_iommu_pagetable_create(gpu->aspace->mmu);
|
||||
|
||||
if (IS_ERR(mmu))
|
||||
return ERR_CAST(mmu);
|
||||
|
||||
return msm_gem_address_space_create(mmu,
|
||||
"gpu", 0x100000000ULL, 0x1ffffffffULL);
|
||||
}
|
||||
|
||||
static const struct adreno_gpu_funcs funcs = {
|
||||
.base = {
|
||||
.get_param = adreno_get_param,
|
||||
|
|
@ -1705,6 +1770,7 @@ static const struct adreno_gpu_funcs funcs = {
|
|||
.gpu_state_get = a5xx_gpu_state_get,
|
||||
.gpu_state_put = a5xx_gpu_state_put,
|
||||
.create_address_space = adreno_iommu_create_address_space,
|
||||
.create_private_address_space = a5xx_create_private_address_space,
|
||||
.get_rptr = a5xx_get_rptr,
|
||||
},
|
||||
.get_timestamp = a5xx_get_timestamp,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ struct a5xx_gpu {
|
|||
|
||||
struct msm_ringbuffer *cur_ring;
|
||||
struct msm_ringbuffer *next_ring;
|
||||
struct msm_file_private *cur_ctx;
|
||||
|
||||
struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS];
|
||||
struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS];
|
||||
|
|
|
|||
|
|
@ -338,6 +338,10 @@ MODULE_FIRMWARE("qcom/a530_zap.mdt");
|
|||
MODULE_FIRMWARE("qcom/a530_zap.b00");
|
||||
MODULE_FIRMWARE("qcom/a530_zap.b01");
|
||||
MODULE_FIRMWARE("qcom/a530_zap.b02");
|
||||
MODULE_FIRMWARE("qcom/a508_zap.mdt");
|
||||
MODULE_FIRMWARE("qcom/a508_zap.b00");
|
||||
MODULE_FIRMWARE("qcom/a508_zap.b01");
|
||||
MODULE_FIRMWARE("qcom/a508_zap.b02");
|
||||
MODULE_FIRMWARE("qcom/a630_sqe.fw");
|
||||
MODULE_FIRMWARE("qcom/a630_gmu.bin");
|
||||
MODULE_FIRMWARE("qcom/a630_zap.mbn");
|
||||
|
|
|
|||
|
|
@ -682,6 +682,9 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done(
|
|||
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
|
||||
return 0;
|
||||
|
||||
if (phys_enc->hw_ctl->ops.is_started)
|
||||
return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc);
|
||||
|
||||
return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT))
|
||||
|
||||
#define VIG_MSM8998_MASK \
|
||||
(VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3))
|
||||
|
||||
#define VIG_SDM845_MASK \
|
||||
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3))
|
||||
|
||||
|
|
@ -25,6 +28,11 @@
|
|||
#define VIG_SM8250_MASK \
|
||||
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE))
|
||||
|
||||
#define DMA_MSM8998_MASK \
|
||||
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
|
||||
BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT))
|
||||
|
||||
#define DMA_SDM845_MASK \
|
||||
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
|
||||
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
|
||||
|
|
@ -33,6 +41,9 @@
|
|||
#define DMA_CURSOR_SDM845_MASK \
|
||||
(DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR))
|
||||
|
||||
#define DMA_CURSOR_MSM8998_MASK \
|
||||
(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
|
||||
|
||||
#define MIXER_SDM845_MASK \
|
||||
(BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER))
|
||||
|
||||
|
|
@ -49,6 +60,8 @@
|
|||
|
||||
#define MERGE_3D_SM8150_MASK (0)
|
||||
|
||||
#define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC)
|
||||
|
||||
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
|
||||
|
||||
#define INTF_SDM845_MASK (0)
|
||||
|
|
@ -181,6 +194,22 @@ static const uint32_t plane_formats_yuv[] = {
|
|||
* DPU sub blocks config
|
||||
*************************************************************/
|
||||
/* DPU top level caps */
|
||||
static const struct dpu_caps msm8998_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0x7,
|
||||
.qseed_type = DPU_SSPP_SCALER_QSEED3,
|
||||
.smart_dma_rev = DPU_SSPP_SMART_DMA_V1,
|
||||
.ubwc_version = DPU_HW_UBWC_VER_10,
|
||||
.has_src_split = true,
|
||||
.has_dim_layer = true,
|
||||
.has_idle_pc = true,
|
||||
.has_3d_merge = true,
|
||||
.max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
|
||||
.max_hdeci_exp = MAX_HORZ_DECIMATION,
|
||||
.max_vdeci_exp = MAX_VERT_DECIMATION,
|
||||
};
|
||||
|
||||
static const struct dpu_caps sdm845_dpu_caps = {
|
||||
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
|
||||
.max_mixer_blendstages = 0xb,
|
||||
|
|
@ -251,6 +280,35 @@ static const struct dpu_caps sc7280_dpu_caps = {
|
|||
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg msm8998_mdp[] = {
|
||||
{
|
||||
.name = "top_0", .id = MDP_TOP,
|
||||
.base = 0x0, .len = 0x458,
|
||||
.features = 0,
|
||||
.highest_bank_bit = 0x2,
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG0] = {
|
||||
.reg_off = 0x2AC, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG1] = {
|
||||
.reg_off = 0x2B4, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG2] = {
|
||||
.reg_off = 0x2BC, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_VIG3] = {
|
||||
.reg_off = 0x2C4, .bit_off = 0},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA0] = {
|
||||
.reg_off = 0x2AC, .bit_off = 8},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA1] = {
|
||||
.reg_off = 0x2B4, .bit_off = 8},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA2] = {
|
||||
.reg_off = 0x2C4, .bit_off = 8},
|
||||
.clk_ctrls[DPU_CLK_CTRL_DMA3] = {
|
||||
.reg_off = 0x2C4, .bit_off = 12},
|
||||
.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = {
|
||||
.reg_off = 0x3A8, .bit_off = 15},
|
||||
.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = {
|
||||
.reg_off = 0x3B0, .bit_off = 15},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_mdp_cfg sdm845_mdp[] = {
|
||||
{
|
||||
.name = "top_0", .id = MDP_TOP,
|
||||
|
|
@ -339,6 +397,39 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = {
|
|||
/*************************************************************
|
||||
* CTL sub blocks config
|
||||
*************************************************************/
|
||||
static const struct dpu_ctl_cfg msm8998_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
.base = 0x1000, .len = 0x94,
|
||||
.features = BIT(DPU_CTL_SPLIT_DISPLAY),
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
|
||||
},
|
||||
{
|
||||
.name = "ctl_1", .id = CTL_1,
|
||||
.base = 0x1200, .len = 0x94,
|
||||
.features = 0,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
|
||||
},
|
||||
{
|
||||
.name = "ctl_2", .id = CTL_2,
|
||||
.base = 0x1400, .len = 0x94,
|
||||
.features = BIT(DPU_CTL_SPLIT_DISPLAY),
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
|
||||
},
|
||||
{
|
||||
.name = "ctl_3", .id = CTL_3,
|
||||
.base = 0x1600, .len = 0x94,
|
||||
.features = 0,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
|
||||
},
|
||||
{
|
||||
.name = "ctl_4", .id = CTL_4,
|
||||
.base = 0x1800, .len = 0x94,
|
||||
.features = 0,
|
||||
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_ctl_cfg sdm845_ctl[] = {
|
||||
{
|
||||
.name = "ctl_0", .id = CTL_0,
|
||||
|
|
@ -497,6 +588,15 @@ static const struct dpu_ctl_cfg sc7280_ctl[] = {
|
|||
.virt_num_formats = ARRAY_SIZE(plane_formats), \
|
||||
}
|
||||
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 =
|
||||
_VIG_SBLK("0", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 =
|
||||
_VIG_SBLK("1", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 =
|
||||
_VIG_SBLK("2", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 =
|
||||
_VIG_SBLK("3", 0, DPU_SSPP_SCALER_QSEED3);
|
||||
|
||||
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 =
|
||||
_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3);
|
||||
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 =
|
||||
|
|
@ -523,6 +623,25 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4);
|
|||
.clk_ctrl = _clkctrl \
|
||||
}
|
||||
|
||||
static const struct dpu_sspp_cfg msm8998_sspp[] = {
|
||||
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
|
||||
SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
|
||||
SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
|
||||
SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_MSM8998_MASK,
|
||||
msm8998_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
|
||||
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_MSM8998_MASK,
|
||||
sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
|
||||
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_MSM8998_MASK,
|
||||
sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
|
||||
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_MSM8998_MASK,
|
||||
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
|
||||
SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_MSM8998_MASK,
|
||||
sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
|
||||
};
|
||||
|
||||
static const struct dpu_sspp_cfg sdm845_sspp[] = {
|
||||
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK,
|
||||
sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
|
||||
|
|
@ -599,17 +718,6 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = {
|
|||
* MIXER sub blocks config
|
||||
*************************************************************/
|
||||
|
||||
/* SDM845 */
|
||||
|
||||
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,
|
||||
0xb0, 0xc8, 0xe0, 0xf8, 0x110
|
||||
},
|
||||
};
|
||||
|
||||
#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \
|
||||
{ \
|
||||
.name = _name, .id = _id, \
|
||||
|
|
@ -621,6 +729,43 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
|
|||
.dspp = _dspp \
|
||||
}
|
||||
|
||||
/* MSM8998 */
|
||||
|
||||
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,
|
||||
0x260, 0x290
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg msm8998_lm[] = {
|
||||
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0),
|
||||
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1),
|
||||
LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_2, LM_0, 0),
|
||||
LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
|
||||
LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
|
||||
LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
|
||||
&msm8998_lm_sblk, PINGPONG_3, LM_1, 0),
|
||||
};
|
||||
|
||||
/* SDM845 */
|
||||
|
||||
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,
|
||||
0xb0, 0xc8, 0xe0, 0xf8, 0x110
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_lm_cfg sdm845_lm[] = {
|
||||
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
|
||||
&sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
|
||||
|
|
@ -682,6 +827,13 @@ static const struct dpu_lm_cfg sc7280_lm[] = {
|
|||
/*************************************************************
|
||||
* DSPP sub blocks config
|
||||
*************************************************************/
|
||||
static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = {
|
||||
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
|
||||
.len = 0x90, .version = 0x10007},
|
||||
.gc = { .id = DPU_DSPP_GC, .base = 0x17c0,
|
||||
.len = 0x90, .version = 0x10007},
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
|
||||
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
|
||||
.len = 0x90, .version = 0x10000},
|
||||
|
|
@ -700,6 +852,13 @@ static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = {
|
|||
.sblk = _sblk \
|
||||
}
|
||||
|
||||
static const struct dpu_dspp_cfg msm8998_dspp[] = {
|
||||
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_MSM8998_MASK,
|
||||
&msm8998_dspp_sblk),
|
||||
DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_MSM8998_MASK,
|
||||
&msm8998_dspp_sblk),
|
||||
};
|
||||
|
||||
static const struct dpu_dspp_cfg sc7180_dspp[] = {
|
||||
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
|
||||
&sc7180_dspp_sblk),
|
||||
|
|
@ -836,6 +995,13 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
|
|||
.intr_vsync = DPU_IRQ_IDX(_reg, _vsync_bit), \
|
||||
}
|
||||
|
||||
static const struct dpu_intf_cfg msm8998_intf[] = {
|
||||
INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
|
||||
INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
|
||||
INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
|
||||
INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_HDMI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
|
||||
};
|
||||
|
||||
static const struct dpu_intf_cfg sdm845_intf[] = {
|
||||
INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
|
||||
INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
|
||||
|
|
@ -865,9 +1031,55 @@ static const struct dpu_intf_cfg sc7280_intf[] = {
|
|||
* VBIF sub blocks config
|
||||
*************************************************************/
|
||||
/* VBIF QOS remap */
|
||||
static const u32 msm8998_rt_pri_lvl[] = {1, 2, 2, 2};
|
||||
static const u32 msm8998_nrt_pri_lvl[] = {1, 1, 1, 1};
|
||||
static const u32 sdm845_rt_pri_lvl[] = {3, 3, 4, 4, 5, 5, 6, 6};
|
||||
static const u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3};
|
||||
|
||||
static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
|
||||
{
|
||||
.pps = 1088 * 1920 * 30,
|
||||
.ot_limit = 2,
|
||||
},
|
||||
{
|
||||
.pps = 1088 * 1920 * 60,
|
||||
.ot_limit = 6,
|
||||
},
|
||||
{
|
||||
.pps = 3840 * 2160 * 30,
|
||||
.ot_limit = 16,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg msm8998_vbif[] = {
|
||||
{
|
||||
.name = "vbif_0", .id = VBIF_0,
|
||||
.base = 0, .len = 0x1040,
|
||||
.default_ot_rd_limit = 32,
|
||||
.default_ot_wr_limit = 32,
|
||||
.features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
|
||||
.xin_halt_timeout = 0x4000,
|
||||
.dynamic_ot_rd_tbl = {
|
||||
.count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
|
||||
.cfg = msm8998_ot_rdwr_cfg,
|
||||
},
|
||||
.dynamic_ot_wr_tbl = {
|
||||
.count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
|
||||
.cfg = msm8998_ot_rdwr_cfg,
|
||||
},
|
||||
.qos_rt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl),
|
||||
.priority_lvl = msm8998_rt_pri_lvl,
|
||||
},
|
||||
.qos_nrt_tbl = {
|
||||
.npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl),
|
||||
.priority_lvl = msm8998_nrt_pri_lvl,
|
||||
},
|
||||
.memtype_count = 14,
|
||||
.memtype = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dpu_vbif_cfg sdm845_vbif[] = {
|
||||
{
|
||||
.name = "vbif_0", .id = VBIF_0,
|
||||
|
|
@ -908,6 +1120,22 @@ static const struct dpu_reg_dma_cfg sm8250_regdma = {
|
|||
*************************************************************/
|
||||
|
||||
/* SSPP QOS LUTs */
|
||||
static const struct dpu_qos_lut_entry msm8998_qos_linear[] = {
|
||||
{.fl = 4, .lut = 0x1b},
|
||||
{.fl = 5, .lut = 0x5b},
|
||||
{.fl = 6, .lut = 0x15b},
|
||||
{.fl = 7, .lut = 0x55b},
|
||||
{.fl = 8, .lut = 0x155b},
|
||||
{.fl = 9, .lut = 0x555b},
|
||||
{.fl = 10, .lut = 0x1555b},
|
||||
{.fl = 11, .lut = 0x5555b},
|
||||
{.fl = 12, .lut = 0x15555b},
|
||||
{.fl = 13, .lut = 0x55555b},
|
||||
{.fl = 14, .lut = 0},
|
||||
{.fl = 1, .lut = 0x1b},
|
||||
{.fl = 0, .lut = 0}
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
|
||||
{.fl = 4, .lut = 0x357},
|
||||
{.fl = 5, .lut = 0x3357},
|
||||
|
|
@ -923,6 +1151,15 @@ static const struct dpu_qos_lut_entry sdm845_qos_linear[] = {
|
|||
{.fl = 0, .lut = 0x11222222223357}
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry msm8998_qos_macrotile[] = {
|
||||
{.fl = 10, .lut = 0x1aaff},
|
||||
{.fl = 11, .lut = 0x5aaff},
|
||||
{.fl = 12, .lut = 0x15aaff},
|
||||
{.fl = 13, .lut = 0x55aaff},
|
||||
{.fl = 1, .lut = 0x1aaff},
|
||||
{.fl = 0, .lut = 0},
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry sc7180_qos_linear[] = {
|
||||
{.fl = 0, .lut = 0x0011222222335777},
|
||||
};
|
||||
|
|
@ -944,6 +1181,10 @@ static const struct dpu_qos_lut_entry sc7180_qos_macrotile[] = {
|
|||
{.fl = 0, .lut = 0x0011223344556677},
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry msm8998_qos_nrt[] = {
|
||||
{.fl = 0, .lut = 0x0},
|
||||
};
|
||||
|
||||
static const struct dpu_qos_lut_entry sdm845_qos_nrt[] = {
|
||||
{.fl = 0, .lut = 0x0},
|
||||
};
|
||||
|
|
@ -952,6 +1193,48 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
|
|||
{.fl = 0, .lut = 0x0},
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg msm8998_perf_data = {
|
||||
.max_bw_low = 6700000,
|
||||
.max_bw_high = 6700000,
|
||||
.min_core_ib = 2400000,
|
||||
.min_llcc_ib = 800000,
|
||||
.min_dram_ib = 800000,
|
||||
.core_ib_ff = "6.0",
|
||||
.core_clk_ff = "1.0",
|
||||
.comp_ratio_rt =
|
||||
"NV12/5/1/1.23 AB24/5/1/1.23 XB24/5/1/1.23",
|
||||
.comp_ratio_nrt =
|
||||
"NV12/5/1/1.25 AB24/5/1/1.25 XB24/5/1/1.25",
|
||||
.undersized_prefill_lines = 2,
|
||||
.xtra_prefill_lines = 2,
|
||||
.dest_scale_prefill_lines = 3,
|
||||
.macrotile_prefill_lines = 4,
|
||||
.yuv_nv12_prefill_lines = 8,
|
||||
.linear_prefill_lines = 1,
|
||||
.downscaling_prefill_lines = 1,
|
||||
.amortizable_threshold = 25,
|
||||
.min_prefill_lines = 25,
|
||||
.danger_lut_tbl = {0xf, 0xffff, 0x0},
|
||||
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
|
||||
.qos_lut_tbl = {
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
|
||||
.entries = msm8998_qos_linear
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
|
||||
.entries = msm8998_qos_macrotile
|
||||
},
|
||||
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
|
||||
.entries = msm8998_qos_nrt
|
||||
},
|
||||
},
|
||||
.cdp_cfg = {
|
||||
{.rd_enable = 1, .wr_enable = 1},
|
||||
{.rd_enable = 1, .wr_enable = 0}
|
||||
},
|
||||
.clk_inefficiency_factor = 200,
|
||||
.bw_inefficiency_factor = 120,
|
||||
};
|
||||
|
||||
static const struct dpu_perf_cfg sdm845_perf_data = {
|
||||
.max_bw_low = 6800000,
|
||||
.max_bw_high = 6800000,
|
||||
|
|
@ -1112,6 +1395,34 @@ static const struct dpu_perf_cfg sc7280_perf_data = {
|
|||
* Hardware catalog init
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
* msm8998_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
|
||||
* and instance counts.
|
||||
*/
|
||||
static void msm8998_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
|
||||
{
|
||||
*dpu_cfg = (struct dpu_mdss_cfg){
|
||||
.caps = &msm8998_dpu_caps,
|
||||
.mdp_count = ARRAY_SIZE(msm8998_mdp),
|
||||
.mdp = msm8998_mdp,
|
||||
.ctl_count = ARRAY_SIZE(msm8998_ctl),
|
||||
.ctl = msm8998_ctl,
|
||||
.sspp_count = ARRAY_SIZE(msm8998_sspp),
|
||||
.sspp = msm8998_sspp,
|
||||
.mixer_count = ARRAY_SIZE(msm8998_lm),
|
||||
.mixer = msm8998_lm,
|
||||
.pingpong_count = ARRAY_SIZE(sdm845_pp),
|
||||
.pingpong = sdm845_pp,
|
||||
.intf_count = ARRAY_SIZE(msm8998_intf),
|
||||
.intf = msm8998_intf,
|
||||
.vbif_count = ARRAY_SIZE(msm8998_vbif),
|
||||
.vbif = msm8998_vbif,
|
||||
.reg_dma_count = 0,
|
||||
.perf = msm8998_perf_data,
|
||||
.mdss_irqs = IRQ_SM8250_MASK,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* sdm845_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
|
||||
* and instance counts.
|
||||
|
|
@ -1262,6 +1573,8 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
|
|||
}
|
||||
|
||||
static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = {
|
||||
{ .hw_rev = DPU_HW_VER_300, .cfg_init = msm8998_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_301, .cfg_init = msm8998_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init},
|
||||
{ .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init},
|
||||
|
|
|
|||
|
|
@ -432,6 +432,8 @@ enum dpu_clk_ctrl_type {
|
|||
DPU_CLK_CTRL_RGB3,
|
||||
DPU_CLK_CTRL_DMA0,
|
||||
DPU_CLK_CTRL_DMA1,
|
||||
DPU_CLK_CTRL_DMA2,
|
||||
DPU_CLK_CTRL_DMA3,
|
||||
DPU_CLK_CTRL_CURSOR0,
|
||||
DPU_CLK_CTRL_CURSOR1,
|
||||
DPU_CLK_CTRL_INLINE_ROT0_SSPP,
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@ static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
|
|||
DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);
|
||||
}
|
||||
|
||||
static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
|
||||
{
|
||||
return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
|
||||
}
|
||||
|
||||
static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)
|
||||
{
|
||||
trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,
|
||||
|
|
@ -579,6 +584,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
|
|||
ops->get_pending_flush = dpu_hw_ctl_get_pending_flush;
|
||||
ops->get_flush_register = dpu_hw_ctl_get_flush_register;
|
||||
ops->trigger_start = dpu_hw_ctl_trigger_start;
|
||||
ops->is_started = dpu_hw_ctl_is_started;
|
||||
ops->trigger_pending = dpu_hw_ctl_trigger_pending;
|
||||
ops->reset = dpu_hw_ctl_reset_control;
|
||||
ops->wait_reset_status = dpu_hw_ctl_wait_reset_status;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ struct dpu_hw_ctl_ops {
|
|||
*/
|
||||
void (*trigger_start)(struct dpu_hw_ctl *ctx);
|
||||
|
||||
/**
|
||||
* check if the ctl is started
|
||||
* @ctx : ctl path ctx pointer
|
||||
* @Return: true if started, false if stopped
|
||||
*/
|
||||
bool (*is_started)(struct dpu_hw_ctl *ctx);
|
||||
|
||||
/**
|
||||
* kickoff prepare is in progress hw operation for sw
|
||||
* controlled interfaces: DSI cmd mode and WB interface
|
||||
|
|
|
|||
|
|
@ -1270,6 +1270,7 @@ static const struct dev_pm_ops dpu_pm_ops = {
|
|||
};
|
||||
|
||||
static const struct of_device_id dpu_dt_match[] = {
|
||||
{ .compatible = "qcom,msm8998-dpu", },
|
||||
{ .compatible = "qcom,sdm845-dpu", },
|
||||
{ .compatible = "qcom,sc7180-dpu", },
|
||||
{ .compatible = "qcom,sc7280-dpu", },
|
||||
|
|
|
|||
|
|
@ -950,13 +950,12 @@ static const struct mdp5_cfg_hw sdm630_config = {
|
|||
.mdp = {
|
||||
.count = 1,
|
||||
.caps = MDP_CAP_CDM |
|
||||
MDP_CAP_SRC_SPLIT |
|
||||
0,
|
||||
},
|
||||
.ctl = {
|
||||
.count = 5,
|
||||
.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
|
||||
.flush_hw_mask = 0xf4ffffff,
|
||||
.flush_hw_mask = 0xf54338c1,
|
||||
},
|
||||
.pipe_vig = {
|
||||
.count = 1,
|
||||
|
|
@ -969,16 +968,6 @@ static const struct mdp5_cfg_hw sdm630_config = {
|
|||
MDP_PIPE_CAP_SW_PIX_EXT |
|
||||
0,
|
||||
},
|
||||
.pipe_rgb = {
|
||||
.count = 4,
|
||||
.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP |
|
||||
MDP_PIPE_CAP_VFLIP |
|
||||
MDP_PIPE_CAP_SCALE |
|
||||
MDP_PIPE_CAP_DECIMATION |
|
||||
MDP_PIPE_CAP_SW_PIX_EXT |
|
||||
0,
|
||||
},
|
||||
.pipe_dma = {
|
||||
.count = 2, /* driver supports max of 2 currently */
|
||||
.base = { 0x24000, 0x26000, 0x28000 },
|
||||
|
|
@ -998,13 +987,12 @@ static const struct mdp5_cfg_hw sdm630_config = {
|
|||
},
|
||||
|
||||
.lm = {
|
||||
.count = 2,
|
||||
.base = { 0x44000, 0x46000 },
|
||||
.count = 3, /* LM_1 seems broken */
|
||||
.base = { 0x44000, 0x45000, 0x46000 },
|
||||
.instances = {
|
||||
{ .id = 0, .pp = 0, .dspp = 0,
|
||||
.caps = MDP_LM_CAP_DISPLAY |
|
||||
MDP_LM_CAP_PAIR, },
|
||||
{ .id = 1, .pp = 1, .dspp = -1,
|
||||
.caps = MDP_LM_CAP_DISPLAY, },
|
||||
{ .id = 2, .pp = 2, .dspp = -1,
|
||||
.caps = MDP_LM_CAP_WB, },
|
||||
},
|
||||
.nb_stages = 8,
|
||||
|
|
@ -1020,8 +1008,8 @@ static const struct mdp5_cfg_hw sdm630_config = {
|
|||
.base = { 0x78000, 0x78800 },
|
||||
},
|
||||
.pp = {
|
||||
.count = 3,
|
||||
.base = { 0x70000, 0x71000, 0x72000 },
|
||||
.count = 3, /* Do not use PP1 */
|
||||
.base = { 0x70000, 0x70800, 0x71000 },
|
||||
},
|
||||
.cdm = {
|
||||
.count = 1,
|
||||
|
|
@ -1049,11 +1037,11 @@ static const struct mdp5_cfg_hw sdm660_config = {
|
|||
.ctl = {
|
||||
.count = 5,
|
||||
.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
|
||||
.flush_hw_mask = 0xf4ffffff,
|
||||
.flush_hw_mask = 0xf5437bc3,
|
||||
},
|
||||
.pipe_vig = {
|
||||
.count = 2,
|
||||
.base = { 0x04000, 0x6000 },
|
||||
.base = { 0x04000, 0x06000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP |
|
||||
MDP_PIPE_CAP_VFLIP |
|
||||
MDP_PIPE_CAP_SCALE |
|
||||
|
|
@ -1062,16 +1050,6 @@ static const struct mdp5_cfg_hw sdm660_config = {
|
|||
MDP_PIPE_CAP_SW_PIX_EXT |
|
||||
0,
|
||||
},
|
||||
.pipe_rgb = {
|
||||
.count = 4,
|
||||
.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
|
||||
.caps = MDP_PIPE_CAP_HFLIP |
|
||||
MDP_PIPE_CAP_VFLIP |
|
||||
MDP_PIPE_CAP_SCALE |
|
||||
MDP_PIPE_CAP_DECIMATION |
|
||||
MDP_PIPE_CAP_SW_PIX_EXT |
|
||||
0,
|
||||
},
|
||||
.pipe_dma = {
|
||||
.count = 2, /* driver supports max of 2 currently */
|
||||
.base = { 0x24000, 0x26000, 0x28000 },
|
||||
|
|
@ -1091,19 +1069,19 @@ static const struct mdp5_cfg_hw sdm660_config = {
|
|||
},
|
||||
|
||||
.lm = {
|
||||
.count = 4,
|
||||
.base = { 0x44000, 0x45000, 0x46000, 0x49000 },
|
||||
.count = 6, /* Do not use LM_3, LM_4 */
|
||||
.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
|
||||
.instances = {
|
||||
{ .id = 0, .pp = 0, .dspp = 0,
|
||||
.caps = MDP_LM_CAP_DISPLAY |
|
||||
MDP_LM_CAP_PAIR, },
|
||||
{ .id = 1, .pp = 1, .dspp = 1,
|
||||
.caps = MDP_LM_CAP_DISPLAY, },
|
||||
{ .id = 2, .pp = 2, .dspp = -1,
|
||||
{ .id = 2, .pp = -1, .dspp = -1,
|
||||
.caps = MDP_LM_CAP_WB, },
|
||||
{ .id = 5, .pp = 4, .dspp = -1,
|
||||
.caps = MDP_LM_CAP_DISPLAY |
|
||||
MDP_LM_CAP_PAIR, },
|
||||
{ .id = 3, .pp = 3, .dspp = -1,
|
||||
.caps = MDP_LM_CAP_WB, },
|
||||
},
|
||||
.nb_stages = 8,
|
||||
.max_width = 2560,
|
||||
|
|
@ -1118,7 +1096,7 @@ static const struct mdp5_cfg_hw sdm660_config = {
|
|||
.base = { 0x78000, 0x78800 },
|
||||
},
|
||||
.pp = {
|
||||
.count = 5,
|
||||
.count = 5, /* Do not use PP_2 and PP_3 */
|
||||
.base = { 0x70000, 0x70800, 0x71000, 0x71800, 0x72000 },
|
||||
},
|
||||
.cdm = {
|
||||
|
|
@ -1132,10 +1110,10 @@ static const struct mdp5_cfg_hw sdm660_config = {
|
|||
.intf = {
|
||||
.base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800 },
|
||||
.connect = {
|
||||
[0] = INTF_DISABLED,
|
||||
[0] = INTF_HDMI,
|
||||
[1] = INTF_DSI,
|
||||
[2] = INTF_DSI,
|
||||
[3] = INTF_HDMI,
|
||||
[3] = INTF_DISABLED,
|
||||
},
|
||||
},
|
||||
.max_clk = 412500000,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ struct mdp5_crtc {
|
|||
|
||||
struct completion pp_completion;
|
||||
|
||||
atomic_t pp_complete;
|
||||
|
||||
bool lm_cursor_enabled;
|
||||
|
||||
struct {
|
||||
|
|
@ -83,6 +85,9 @@ static void request_pending(struct drm_crtc *crtc, uint32_t pending)
|
|||
static void request_pp_done_pending(struct drm_crtc *crtc)
|
||||
{
|
||||
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
|
||||
|
||||
atomic_set(&mdp5_crtc->pp_complete, 0);
|
||||
|
||||
reinit_completion(&mdp5_crtc->pp_completion);
|
||||
}
|
||||
|
||||
|
|
@ -1195,6 +1200,15 @@ static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
|
|||
{
|
||||
struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc,
|
||||
pp_done);
|
||||
struct drm_crtc *crtc = &mdp5_crtc->base;
|
||||
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
|
||||
|
||||
atomic_set(&mdp5_crtc->pp_complete, 1);
|
||||
|
||||
if (mdp5_cstate->cmd_mode) {
|
||||
struct mdp5_ctl *ctl = mdp5_cstate->ctl;
|
||||
mdp5_ctl_commit_finished(ctl);
|
||||
}
|
||||
|
||||
complete_all(&mdp5_crtc->pp_completion);
|
||||
}
|
||||
|
|
@ -1206,6 +1220,9 @@ static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
|
|||
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
|
||||
int ret;
|
||||
|
||||
if (atomic_read(&mdp5_crtc->pp_complete))
|
||||
return;
|
||||
|
||||
ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion,
|
||||
msecs_to_jiffies(50));
|
||||
if (ret == 0)
|
||||
|
|
@ -1319,6 +1336,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
|
|||
spin_lock_init(&mdp5_crtc->lm_lock);
|
||||
spin_lock_init(&mdp5_crtc->cursor.lock);
|
||||
init_completion(&mdp5_crtc->pp_completion);
|
||||
atomic_set(&mdp5_crtc->pp_complete, 0);
|
||||
|
||||
mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
|
||||
mdp5_crtc->err.irq = mdp5_crtc_err_irq;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ struct mdp5_ctl {
|
|||
/* True if the current CTL has FLUSH bits pending for single FLUSH. */
|
||||
bool flush_pending;
|
||||
|
||||
bool busy;
|
||||
|
||||
struct mdp5_ctl *pair; /* Paired CTL to be flushed together */
|
||||
};
|
||||
|
||||
|
|
@ -209,6 +211,11 @@ static void send_start_signal(struct mdp5_ctl *ctl)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctl->hw_lock, flags);
|
||||
if (ctl->busy) {
|
||||
spin_unlock_irqrestore(&ctl->hw_lock, flags);
|
||||
return;
|
||||
}
|
||||
ctl->busy = true;
|
||||
ctl_write(ctl, REG_MDP5_CTL_START(ctl->id), 1);
|
||||
spin_unlock_irqrestore(&ctl->hw_lock, flags);
|
||||
}
|
||||
|
|
@ -242,6 +249,11 @@ int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mdp5_ctl_commit_finished(struct mdp5_ctl *ctl)
|
||||
{
|
||||
ctl->busy = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note:
|
||||
* CTL registers need to be flushed after calling this function
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ u32 mdp_ctl_flush_mask_cursor(int cursor_id);
|
|||
u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
|
||||
|
||||
/* @flush_mask: see CTL flush masks definitions below */
|
||||
void mdp5_ctl_commit_finished(struct mdp5_ctl *ctl);
|
||||
u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
|
||||
u32 flush_mask, bool start);
|
||||
u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll, struct dsi_pll_confi
|
|||
|
||||
pll_freq = pll->vco_current_rate;
|
||||
|
||||
divider = fref * 2;
|
||||
divider = fref;
|
||||
|
||||
multiplier = 1 << FRAC_BITS;
|
||||
dec_multiple = div_u64(pll_freq * multiplier, divider);
|
||||
|
|
@ -428,12 +428,11 @@ static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,
|
|||
* 1. Assumes prescaler is disabled
|
||||
*/
|
||||
multiplier = 1 << FRAC_BITS;
|
||||
pll_freq = dec * (ref_clk * 2);
|
||||
tmp64 = (ref_clk * 2 * frac);
|
||||
pll_freq = dec * ref_clk;
|
||||
tmp64 = ref_clk * frac;
|
||||
pll_freq += div_u64(tmp64, multiplier);
|
||||
|
||||
vco_rate = pll_freq;
|
||||
pll_10nm->vco_current_rate = vco_rate;
|
||||
|
||||
DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
|
||||
pll_10nm->phy->id, (unsigned long)vco_rate, dec, frac);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,17 @@ config DRM_PANEL_ASUS_Z00T_TM5P5_NT35596
|
|||
NT35596 1080x1920 video mode panel as found in some Asus
|
||||
Zenfone 2 Laser Z00T devices.
|
||||
|
||||
config DRM_PANEL_BOE_BF060Y8M_AJ0
|
||||
tristate "Boe BF060Y8M-AJ0 panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for Boe BF060Y8M-AJ0
|
||||
5.99" AMOLED modules. The panel has a 1080x2160 resolution and
|
||||
uses 24 bit RGB per pixel. It provides a MIPI DSI interface to
|
||||
the host and backlight is controlled through DSI commands.
|
||||
|
||||
config DRM_PANEL_BOE_HIMAX8279D
|
||||
tristate "Boe Himax8279d panel"
|
||||
depends on OF
|
||||
|
|
@ -260,6 +271,17 @@ config DRM_PANEL_NOVATEK_NT35510
|
|||
around the Novatek NT35510 display controller, such as some
|
||||
Hydis panels.
|
||||
|
||||
config DRM_PANEL_NOVATEK_NT35950
|
||||
tristate "Novatek NT35950 DSI panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for the panels built
|
||||
around the Novatek NT35950 display controller, such as some
|
||||
Sharp panels used in Sony Xperia Z5 Premium and XZ Premium
|
||||
mobile phones.
|
||||
|
||||
config DRM_PANEL_NOVATEK_NT36672A
|
||||
tristate "Novatek NT36672A DSI panel"
|
||||
depends on OF
|
||||
|
|
@ -393,6 +415,36 @@ config DRM_PANEL_SAMSUNG_S6D16D0
|
|||
depends on DRM_MIPI_DSI
|
||||
select VIDEOMODE_HELPERS
|
||||
|
||||
config DRM_PANEL_SAMSUNG_S6E3FA5
|
||||
tristate "Samsung S6E3FA5 DSI command mode panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y here if you want to enable support for Samsung S6E3FA5 AMOLED
|
||||
command mode panel as found in OnePlus 5 (2017) devices. The panel has a
|
||||
FHD (1080x1920) resolution and uses 24 bit RGB per pixel. It provides a
|
||||
MIPI DSI interface to the host and has a built-in LED backlight.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called panel-samsung-s6e3fa5.
|
||||
|
||||
config DRM_PANEL_SAMSUNG_S6E3FC1
|
||||
tristate "Samsung S6E3FC1 DSI command mode panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y here if you want to enable support for Samsung S6E3FC1 AMOLED
|
||||
command mode panel as found in OnePlus 5T (2017) devices. The panel has a
|
||||
FHD (1080x2160) resolution and uses 24 bit RGB per pixel. It provides a
|
||||
MIPI DSI interface to the host and has a built-in LED backlight.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called panel-samsung-s6e3fc1.
|
||||
|
||||
config DRM_PANEL_SAMSUNG_S6E3HA2
|
||||
tristate "Samsung S6E3HA2 DSI video mode panel"
|
||||
depends on OF
|
||||
|
|
@ -547,6 +599,36 @@ config DRM_PANEL_SONY_ACX565AKM
|
|||
Say Y here if you want to enable support for the Sony ACX565AKM
|
||||
800x600 3.5" panel (found on the Nokia N900).
|
||||
|
||||
config DRM_PANEL_SONY_DISCOVERY_TD4322_INNOLUX
|
||||
tristate "Sony Discovery TD4322 Innolux panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable the Innolux TD4322
|
||||
1080-1920 command mode panel (as found on Sony Xperia
|
||||
XA2 Ultra devices).
|
||||
|
||||
config DRM_PANEL_SONY_PIONEER_TD4322_TRULY
|
||||
tristate "Sony Pioneer TD4322 Truly panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable the Truly TD4322 1080x
|
||||
1920 command mode display panel (as found on Sony Xperia XA2
|
||||
devices).
|
||||
|
||||
config DRM_PANEL_SONY_VOYAGER_TD4328_TIANMA
|
||||
tristate "Sony Voyager TD4328 Tianma panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable the Tianma TD4328 1080x
|
||||
2160 command mode panel (as found on Sony Xperia XA2 Plus
|
||||
devices).
|
||||
|
||||
config DRM_PANEL_TDO_TL070WSH30
|
||||
tristate "TDO TL070WSH30 DSI panel"
|
||||
depends on OF
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
obj-$(CONFIG_DRM_PANEL_ABT_Y030XX067A) += panel-abt-y030xx067a.o
|
||||
obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o
|
||||
obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.o
|
||||
obj-$(CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0) += panel-boe-bf060y8m-aj0.o
|
||||
obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
|
||||
obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o
|
||||
obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o
|
||||
|
|
@ -24,6 +25,7 @@ obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
|
|||
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
|
||||
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
|
||||
obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
|
||||
|
|
@ -39,6 +41,8 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o
|
|||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FA5) += panel-samsung-s6e3fa5.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FC1) += panel-samsung-s6e3fc1.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
|
||||
|
|
@ -56,6 +60,9 @@ obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o
|
|||
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_ACX424AKP) += panel-sony-acx424akp.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_DISCOVERY_TD4322_INNOLUX) += panel-td4322-innolux-fhd.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_PIONEER_TD4322_TRULY) += panel-td4322-truly-fhd.o
|
||||
obj-$(CONFIG_DRM_PANEL_SONY_VOYAGER_TD4328_TIANMA) += panel-td4328-tianma-fhdplus.o
|
||||
obj-$(CONFIG_DRM_PANEL_TDO_TL070WSH30) += panel-tdo-tl070wsh30.o
|
||||
obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
|
||||
obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
|
||||
|
|
|
|||
445
drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c
Normal file
445
drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c
Normal file
|
|
@ -0,0 +1,445 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* BOE BF060Y8M-AJ0 5.99" MIPI-DSI OLED Panel on SW43404 DriverIC
|
||||
*
|
||||
* Copyright (c) 2020 AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <video/mipi_display.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#define DCS_ALLOW_HBM_RANGE 0x0c
|
||||
#define DCS_DISALLOW_HBM_RANGE 0x08
|
||||
|
||||
enum boe_bf060y8m_aj0_supplies {
|
||||
BF060Y8M_VREG_VCC,
|
||||
BF060Y8M_VREG_VDDIO,
|
||||
BF060Y8M_VREG_VCI,
|
||||
BF060Y8M_VREG_EL_VDD,
|
||||
BF060Y8M_VREG_EL_VSS,
|
||||
BF060Y8M_VREG_MAX
|
||||
};
|
||||
|
||||
struct boe_bf060y8m_aj0 {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator_bulk_data vregs[BF060Y8M_VREG_MAX];
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct boe_bf060y8m_aj0 *to_boe_bf060y8m_aj0(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct boe_bf060y8m_aj0, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void boe_bf060y8m_aj0_reset(struct boe_bf060y8m_aj0 *boe)
|
||||
{
|
||||
gpiod_set_value_cansleep(boe->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(boe->reset_gpio, 1);
|
||||
usleep_range(15000, 16000);
|
||||
gpiod_set_value_cansleep(boe->reset_gpio, 0);
|
||||
usleep_range(5000, 6000);
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_on(struct boe_bf060y8m_aj0 *boe)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = boe->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x4c);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x10);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, DCS_ALLOW_HBM_RANGE);
|
||||
dsi_dcs_write_seq(dsi, 0xf8,
|
||||
0x00, 0x08, 0x10, 0x00, 0x22, 0x00, 0x00, 0x2d);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(30);
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xc0,
|
||||
0x08, 0x48, 0x65, 0x33, 0x33, 0x33,
|
||||
0x2a, 0x31, 0x39, 0x20, 0x09);
|
||||
dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
dsi_dcs_write_seq(dsi, 0xe2, 0x20, 0x04, 0x10, 0x12, 0x92,
|
||||
0x4f, 0x8f, 0x44, 0x84, 0x83, 0x83, 0x83,
|
||||
0x5c, 0x5c, 0x5c);
|
||||
dsi_dcs_write_seq(dsi, 0xde, 0x01, 0x2c, 0x00, 0x77, 0x3e);
|
||||
|
||||
msleep(30);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(50);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_off(struct boe_bf060y8m_aj0 *boe)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = boe->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
/* OFF commands sent in HS mode */
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct boe_bf060y8m_aj0 *boe = to_boe_bf060y8m_aj0(panel);
|
||||
struct device *dev = &boe->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (boe->prepared)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Enable EL Driving Voltage first - doing that at the beginning
|
||||
* or at the end of the power sequence doesn't matter, so enable
|
||||
* it here to avoid yet another usleep at the end.
|
||||
*/
|
||||
ret = regulator_enable(boe->vregs[BF060Y8M_VREG_EL_VDD].consumer);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = regulator_enable(boe->vregs[BF060Y8M_VREG_EL_VSS].consumer);
|
||||
if (ret)
|
||||
goto err_elvss;
|
||||
|
||||
ret = regulator_enable(boe->vregs[BF060Y8M_VREG_VCC].consumer);
|
||||
if (ret)
|
||||
goto err_vcc;
|
||||
usleep_range(1000, 2000);
|
||||
ret = regulator_enable(boe->vregs[BF060Y8M_VREG_VDDIO].consumer);
|
||||
if (ret)
|
||||
goto err_vddio;
|
||||
usleep_range(500, 1000);
|
||||
ret = regulator_enable(boe->vregs[BF060Y8M_VREG_VCI].consumer);
|
||||
if (ret)
|
||||
goto err_vci;
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
boe_bf060y8m_aj0_reset(boe);
|
||||
|
||||
ret = boe_bf060y8m_aj0_on(boe);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(boe->reset_gpio, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
boe->prepared = true;
|
||||
return 0;
|
||||
|
||||
err_vci:
|
||||
regulator_disable(boe->vregs[BF060Y8M_VREG_VDDIO].consumer);
|
||||
err_vddio:
|
||||
regulator_disable(boe->vregs[BF060Y8M_VREG_VCC].consumer);
|
||||
err_vcc:
|
||||
regulator_disable(boe->vregs[BF060Y8M_VREG_EL_VSS].consumer);
|
||||
err_elvss:
|
||||
regulator_disable(boe->vregs[BF060Y8M_VREG_EL_VDD].consumer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct boe_bf060y8m_aj0 *boe = to_boe_bf060y8m_aj0(panel);
|
||||
struct device *dev = &boe->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!boe->prepared)
|
||||
return 0;
|
||||
|
||||
ret = boe_bf060y8m_aj0_off(boe);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(boe->reset_gpio, 1);
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(boe->vregs), boe->vregs);
|
||||
|
||||
boe->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode boe_bf060y8m_aj0_mode = {
|
||||
.clock = 165268,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 36,
|
||||
.hsync_end = 1080 + 36 + 24,
|
||||
.htotal = 1080 + 36 + 24 + 96,
|
||||
.vdisplay = 2160,
|
||||
.vsync_start = 2160 + 16,
|
||||
.vsync_end = 2160 + 16 + 1,
|
||||
.vtotal = 2160 + 16 + 1 + 15,
|
||||
.width_mm = 68, /* 68.04 mm */
|
||||
.height_mm = 136, /* 136.08 mm */
|
||||
};
|
||||
|
||||
static int boe_bf060y8m_aj0_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &boe_bf060y8m_aj0_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs boe_bf060y8m_aj0_panel_funcs = {
|
||||
.prepare = boe_bf060y8m_aj0_prepare,
|
||||
.unprepare = boe_bf060y8m_aj0_unprepare,
|
||||
.get_modes = boe_bf060y8m_aj0_get_modes,
|
||||
};
|
||||
|
||||
static int boe_bf060y8m_aj0_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness = backlight_get_brightness(bl);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return brightness & 0xff;
|
||||
}
|
||||
|
||||
static const struct backlight_ops boe_bf060y8m_aj0_bl_ops = {
|
||||
.update_status = boe_bf060y8m_aj0_bl_update_status,
|
||||
.get_brightness = boe_bf060y8m_aj0_bl_get_brightness,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
boe_bf060y8m_aj0_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 127,
|
||||
.max_brightness = 255,
|
||||
.scale = BACKLIGHT_SCALE_NON_LINEAR,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&boe_bf060y8m_aj0_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_init_vregs(struct boe_bf060y8m_aj0 *boe,
|
||||
struct device *dev)
|
||||
{
|
||||
struct regulator *vreg;
|
||||
int ret;
|
||||
|
||||
boe->vregs[BF060Y8M_VREG_VCC].supply = "vcc";
|
||||
boe->vregs[BF060Y8M_VREG_VDDIO].supply = "vddio";
|
||||
boe->vregs[BF060Y8M_VREG_VCI].supply = "vci";
|
||||
boe->vregs[BF060Y8M_VREG_EL_VDD].supply = "elvdd";
|
||||
boe->vregs[BF060Y8M_VREG_EL_VSS].supply = "elvss";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(boe->vregs),
|
||||
boe->vregs);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vreg = boe->vregs[BF060Y8M_VREG_VCC].consumer;
|
||||
ret = regulator_is_supported_voltage(vreg, 2700000, 3600000);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
vreg = boe->vregs[BF060Y8M_VREG_VDDIO].consumer;
|
||||
ret = regulator_is_supported_voltage(vreg, 1620000, 1980000);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
vreg = boe->vregs[BF060Y8M_VREG_VCI].consumer;
|
||||
ret = regulator_is_supported_voltage(vreg, 2600000, 3600000);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
vreg = boe->vregs[BF060Y8M_VREG_EL_VDD].consumer;
|
||||
ret = regulator_is_supported_voltage(vreg, 4400000, 4800000);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
/* ELVSS is negative: -5.00V to -1.40V */
|
||||
vreg = boe->vregs[BF060Y8M_VREG_EL_VSS].consumer;
|
||||
ret = regulator_is_supported_voltage(vreg, 1400000, 5000000);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Set min/max rated current, known only for VCI and VDDIO and,
|
||||
* in case of failure, just go on gracefully, as this step is not
|
||||
* guaranteed to succeed on all regulator HW but do a debug print
|
||||
* to inform the developer during debugging.
|
||||
* In any case, these two supplies are also optional, so they may
|
||||
* be fixed-regulator which, at the time of writing, does not
|
||||
* support fake current limiting.
|
||||
*/
|
||||
vreg = boe->vregs[BF060Y8M_VREG_VDDIO].consumer;
|
||||
ret = regulator_set_current_limit(vreg, 1500, 2500);
|
||||
if (ret)
|
||||
dev_dbg(dev, "Current limit cannot be set on %s: %d\n",
|
||||
boe->vregs[1].supply, ret);
|
||||
|
||||
vreg = boe->vregs[BF060Y8M_VREG_VCI].consumer;
|
||||
ret = regulator_set_current_limit(vreg, 20000, 40000);
|
||||
if (ret)
|
||||
dev_dbg(dev, "Current limit cannot be set on %s: %d\n",
|
||||
boe->vregs[2].supply, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct boe_bf060y8m_aj0 *boe;
|
||||
int ret;
|
||||
|
||||
boe = devm_kzalloc(dev, sizeof(*boe), GFP_KERNEL);
|
||||
if (!boe)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = boe_bf060y8m_aj0_init_vregs(boe, dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to initialize supplies.\n");
|
||||
|
||||
boe->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
|
||||
if (IS_ERR(boe->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(boe->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
boe->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, boe);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_EOT_PACKET |
|
||||
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS |
|
||||
MIPI_DSI_MODE_LPM;
|
||||
|
||||
drm_panel_init(&boe->panel, dev, &boe_bf060y8m_aj0_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
boe->panel.backlight = boe_bf060y8m_aj0_create_backlight(dsi);
|
||||
if (IS_ERR(boe->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(boe->panel.backlight),
|
||||
"Failed to create backlight\n");
|
||||
|
||||
drm_panel_add(&boe->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boe_bf060y8m_aj0_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct boe_bf060y8m_aj0 *boe = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&boe->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id boe_bf060y8m_aj0_of_match[] = {
|
||||
{ .compatible = "boe,bf060y8m-aj0" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, boe_bf060y8m_aj0_of_match);
|
||||
|
||||
static struct mipi_dsi_driver boe_bf060y8m_aj0_driver = {
|
||||
.probe = boe_bf060y8m_aj0_probe,
|
||||
.remove = boe_bf060y8m_aj0_remove,
|
||||
.driver = {
|
||||
.name = "panel-sw43404-boe-fhd-amoled",
|
||||
.of_match_table = boe_bf060y8m_aj0_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(boe_bf060y8m_aj0_driver);
|
||||
|
||||
MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>");
|
||||
MODULE_DESCRIPTION("BOE BF060Y8M-AJ0 MIPI-DSI OLED panel");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
704
drivers/gpu/drm/panel/panel-novatek-nt35950.c
Normal file
704
drivers/gpu/drm/panel/panel-novatek-nt35950.c
Normal file
|
|
@ -0,0 +1,704 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Novatek NT35950 DriverIC panels driver
|
||||
*
|
||||
* Copyright (c) 2021 AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#define MCS_CMD_MAUCCTR 0xf0 /* Manufacturer command enable */
|
||||
#define MCS_PARAM_SCALER_FUNCTION 0x58 /* Scale-up function */
|
||||
#define MCS_PARAM_SCALEUP_MODE 0xc9
|
||||
#define MCS_SCALEUP_SIMPLE 0x0
|
||||
#define MCS_SCALEUP_BILINEAR BIT(0)
|
||||
#define MCS_SCALEUP_DUPLICATE BIT(0) | BIT(4)
|
||||
|
||||
/* VESA Display Stream Compression param */
|
||||
#define MCS_PARAM_VESA_DSC_ON 0x03
|
||||
|
||||
/* Data Compression mode */
|
||||
#define MCS_PARAM_DATA_COMPRESSION 0x90
|
||||
#define MCS_DATA_COMPRESSION_NONE 0x00
|
||||
#define MCS_DATA_COMPRESSION_FBC 0x02
|
||||
#define MCS_DATA_COMPRESSION_DSC 0x03
|
||||
|
||||
/* Display Output control */
|
||||
#define MCS_PARAM_DISP_OUTPUT_CTRL 0xb4
|
||||
#define MCS_DISP_OUT_SRAM_EN BIT(0)
|
||||
#define MCS_DISP_OUT_VIDEO_MODE BIT(4)
|
||||
|
||||
/* VESA Display Stream Compression setting */
|
||||
#define MCS_PARAM_VESA_DSC_SETTING 0xc0
|
||||
|
||||
/* SubPixel Rendering (SPR) */
|
||||
#define MCS_PARAM_SPR_EN 0xe3
|
||||
#define MCS_PARAM_SPR_MODE 0xef
|
||||
#define MCS_SPR_MODE_YYG_RAINBOW_RGB 0x01
|
||||
|
||||
#define NT35950_VREG_MAX 4
|
||||
|
||||
struct nt35950 {
|
||||
struct drm_panel panel;
|
||||
struct drm_connector *connector;
|
||||
struct mipi_dsi_device *dsi[2];
|
||||
struct regulator_bulk_data vregs[NT35950_VREG_MAX];
|
||||
struct gpio_desc *reset_gpio;
|
||||
const struct nt35950_panel_desc *desc;
|
||||
|
||||
int cur_mode;
|
||||
u8 last_page;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
struct nt35950_panel_mode {
|
||||
const struct drm_display_mode mode;
|
||||
|
||||
bool enable_sram;
|
||||
bool is_video_mode;
|
||||
u8 scaler_on;
|
||||
u8 scaler_mode;
|
||||
u8 compression;
|
||||
u8 spr_en;
|
||||
u8 spr_mode;
|
||||
};
|
||||
|
||||
struct nt35950_panel_desc {
|
||||
const char* model_name;
|
||||
const struct mipi_dsi_device_info dsi_info;
|
||||
const struct nt35950_panel_mode *mode_data;
|
||||
|
||||
bool is_dual_dsi;
|
||||
u8 num_lanes;
|
||||
u8 num_modes;
|
||||
};
|
||||
|
||||
static inline struct nt35950 *to_nt35950(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct nt35950, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void nt35950_reset(struct nt35950 *nt)
|
||||
{
|
||||
gpiod_set_value_cansleep(nt->reset_gpio, 1);
|
||||
usleep_range(12000, 13000);
|
||||
gpiod_set_value_cansleep(nt->reset_gpio, 0);
|
||||
usleep_range(300, 400);
|
||||
gpiod_set_value_cansleep(nt->reset_gpio, 1);
|
||||
usleep_range(12000, 13000);
|
||||
}
|
||||
|
||||
/*
|
||||
* nt35950_set_cmd2_page - Select manufacturer control (CMD2) page
|
||||
* @nt: Main driver structure
|
||||
* @page: Page number (0-7)
|
||||
*
|
||||
* Return: Number of transferred bytes or negative number on error
|
||||
*/
|
||||
static int nt35950_set_cmd2_page(struct nt35950 *nt, u8 page)
|
||||
{
|
||||
const u8 mauc_cmd2_page[] = { MCS_CMD_MAUCCTR, 0x55, 0xaa, 0x52,
|
||||
0x08, page };
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], mauc_cmd2_page,
|
||||
ARRAY_SIZE(mauc_cmd2_page));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
nt->last_page = page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nt35950_set_data_compression - Set data compression mode
|
||||
* @nt: Main driver structure
|
||||
* @comp_mode: Compression mode
|
||||
*
|
||||
* Return: Number of transferred bytes or negative number on error
|
||||
*/
|
||||
static int nt35950_set_data_compression(struct nt35950 *nt, u8 comp_mode)
|
||||
{
|
||||
u8 cmd_data_compression[] = { MCS_PARAM_DATA_COMPRESSION, comp_mode };
|
||||
u8 cmd_vesa_dsc_on[] = { MCS_PARAM_VESA_DSC_ON, !!comp_mode };
|
||||
u8 cmd_vesa_dsc_setting[] = { MCS_PARAM_VESA_DSC_SETTING, 0x03 };
|
||||
u8 last_page = nt->last_page;
|
||||
int ret;
|
||||
|
||||
/* Set CMD2 Page 0 if we're not there yet */
|
||||
if (last_page != 0) {
|
||||
ret = nt35950_set_cmd2_page(nt, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_data_compression,
|
||||
ARRAY_SIZE(cmd_data_compression));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_vesa_dsc_on,
|
||||
ARRAY_SIZE(cmd_vesa_dsc_on));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Set the vesa dsc setting on Page 4 */
|
||||
ret = nt35950_set_cmd2_page(nt, 4);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Display Stream Compression setting, always 0x03 */
|
||||
ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_vesa_dsc_setting,
|
||||
ARRAY_SIZE(cmd_vesa_dsc_setting));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Get back to the previously set page */
|
||||
return nt35950_set_cmd2_page(nt, last_page);
|
||||
}
|
||||
|
||||
/*
|
||||
* nt35950_set_scaler - Enable/disable resolution upscaling
|
||||
* @nt: Main driver structure
|
||||
* @scale_up: Scale up function control
|
||||
*
|
||||
* Return: Number of transferred bytes or negative number on error
|
||||
*/
|
||||
static int nt35950_set_scaler(struct nt35950 *nt, u8 scale_up)
|
||||
{
|
||||
u8 cmd_scaler[] = { MCS_PARAM_SCALER_FUNCTION, scale_up };
|
||||
|
||||
return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_scaler,
|
||||
ARRAY_SIZE(cmd_scaler));
|
||||
}
|
||||
|
||||
/*
|
||||
* nt35950_set_scale_mode - Resolution upscaling mode
|
||||
* @nt: Main driver structure
|
||||
* @mode: Scaler mode
|
||||
*
|
||||
* Return: Number of transferred bytes or negative number on error
|
||||
*/
|
||||
static int nt35950_set_scale_mode(struct nt35950 *nt, u8 mode)
|
||||
{
|
||||
u8 cmd_scaler[] = { MCS_PARAM_SCALEUP_MODE, mode };
|
||||
|
||||
return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_scaler,
|
||||
ARRAY_SIZE(cmd_scaler));
|
||||
}
|
||||
|
||||
/*
|
||||
* nt35950_inject_black_image - Display a completely black image
|
||||
* @nt: Main driver structure
|
||||
*
|
||||
* After IC setup, the attached panel may show random data
|
||||
* due to driveric behavior changes (resolution, compression,
|
||||
* scaling, etc). This function, called after parameters setup,
|
||||
* makes the driver ic to output a completely black image to
|
||||
* the display.
|
||||
* It makes sense to push a black image before sending the sleep-out
|
||||
* and display-on commands.
|
||||
*
|
||||
* Return: Number of transferred bytes or negative number on error
|
||||
*/
|
||||
static int nt35950_inject_black_image(struct nt35950 *nt)
|
||||
{
|
||||
const u8 cmd0_black_img[] = { 0x6f, 0x01 };
|
||||
const u8 cmd1_black_img[] = { 0xf3, 0x10 };
|
||||
u8 cmd_test[] = { 0xff, 0xaa, 0x55, 0xa5, 0x80 };
|
||||
int ret;
|
||||
|
||||
/* Enable test command */
|
||||
ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_test, ARRAY_SIZE(cmd_test));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Send a black image */
|
||||
ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd0_black_img,
|
||||
ARRAY_SIZE(cmd0_black_img));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd1_black_img,
|
||||
ARRAY_SIZE(cmd1_black_img));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Disable test command */
|
||||
cmd_test[ARRAY_SIZE(cmd_test) - 1] = 0x00;
|
||||
return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_test, ARRAY_SIZE(cmd_test));
|
||||
}
|
||||
|
||||
/*
|
||||
* nt35950_set_dispout - Set Display Output register parameters
|
||||
* @nt: Main driver structure
|
||||
*
|
||||
* Return: Number of transferred bytes or negative number on error
|
||||
*/
|
||||
static int nt35950_set_dispout(struct nt35950 *nt)
|
||||
{
|
||||
u8 cmd_dispout[] = { MCS_PARAM_DISP_OUTPUT_CTRL, 0x00 };
|
||||
const struct nt35950_panel_mode *mode_data = nt->desc->mode_data;
|
||||
|
||||
if (mode_data[nt->cur_mode].is_video_mode)
|
||||
cmd_dispout[1] |= MCS_DISP_OUT_VIDEO_MODE;
|
||||
if (mode_data[nt->cur_mode].enable_sram)
|
||||
cmd_dispout[1] |= MCS_DISP_OUT_SRAM_EN;
|
||||
|
||||
return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_dispout,
|
||||
ARRAY_SIZE(cmd_dispout));
|
||||
}
|
||||
|
||||
static int nt35950_get_current_mode(struct nt35950 *nt)
|
||||
{
|
||||
struct drm_connector *connector = nt->connector;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int i;
|
||||
|
||||
/* Return the default (first) mode if no info available yet */
|
||||
if (!connector->state || !connector->state->crtc)
|
||||
return 0;
|
||||
|
||||
crtc_state = connector->state->crtc->state;
|
||||
|
||||
for (i = 0; i < nt->desc->num_modes; i++) {
|
||||
if (drm_mode_match(&crtc_state->mode,
|
||||
&nt->desc->mode_data[i].mode,
|
||||
DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_CLOCK))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt35950_on(struct nt35950 *nt)
|
||||
{
|
||||
const struct nt35950_panel_mode *mode_data = nt->desc->mode_data;
|
||||
struct mipi_dsi_device *dsi = nt->dsi[0];
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
nt->cur_mode = nt35950_get_current_mode(nt);
|
||||
nt->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
nt->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = nt35950_set_cmd2_page(nt, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nt35950_set_data_compression(nt, mode_data[nt->cur_mode].compression);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nt35950_set_scale_mode(nt, mode_data[nt->cur_mode].scaler_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nt35950_set_scaler(nt, mode_data[nt->cur_mode].scaler_on);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nt35950_set_dispout(nt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear scanline: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* CMD2 Page 1 */
|
||||
ret = nt35950_set_cmd2_page(nt, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Unknown command */
|
||||
dsi_dcs_write_seq(dsi, 0xd4, 0x88, 0x88);
|
||||
|
||||
/* CMD2 Page 7 */
|
||||
ret = nt35950_set_cmd2_page(nt, 7);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enable SubPixel Rendering */
|
||||
dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_EN, 0x01);
|
||||
|
||||
/* SPR Mode: YYG Rainbow-RGB */
|
||||
dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_MODE, MCS_SPR_MODE_YYG_RAINBOW_RGB);
|
||||
|
||||
/* CMD3 */
|
||||
ret = nt35950_inject_black_image(nt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(120);
|
||||
|
||||
nt->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
nt->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt35950_off(struct nt35950 *nt)
|
||||
{
|
||||
struct device *dev = &nt->dsi[0]->dev;
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(nt->dsi[0]);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
goto set_lpm;
|
||||
}
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(nt->dsi[0]);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
goto set_lpm;
|
||||
}
|
||||
msleep(150);
|
||||
|
||||
set_lpm:
|
||||
nt->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
nt->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt35950_sharp_init_vregs(struct nt35950 *nt, struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
nt->vregs[0].supply = "vddio";
|
||||
nt->vregs[1].supply = "avdd";
|
||||
nt->vregs[2].supply = "avee";
|
||||
nt->vregs[3].supply = "dvdd";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(nt->vregs),
|
||||
nt->vregs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regulator_is_supported_voltage(nt->vregs[0].consumer,
|
||||
1750000, 1950000);
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
ret = regulator_is_supported_voltage(nt->vregs[1].consumer,
|
||||
5200000, 5900000);
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
/* AVEE is negative: -5.90V to -5.20V */
|
||||
ret = regulator_is_supported_voltage(nt->vregs[2].consumer,
|
||||
5200000, 5900000);
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regulator_is_supported_voltage(nt->vregs[3].consumer,
|
||||
1300000, 1400000);
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt35950_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nt35950 *nt = to_nt35950(panel);
|
||||
struct device *dev = &nt->dsi[0]->dev;
|
||||
int ret;
|
||||
|
||||
if (nt->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(nt->vregs[0].consumer);
|
||||
if (ret)
|
||||
return ret;
|
||||
usleep_range(2000, 5000);
|
||||
|
||||
ret = regulator_enable(nt->vregs[3].consumer);
|
||||
if (ret)
|
||||
goto end;
|
||||
usleep_range(15000, 18000);
|
||||
|
||||
ret = regulator_enable(nt->vregs[1].consumer);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
ret = regulator_enable(nt->vregs[2].consumer);
|
||||
if (ret)
|
||||
goto end;
|
||||
usleep_range(12000, 13000);
|
||||
|
||||
nt35950_reset(nt);
|
||||
|
||||
ret = nt35950_on(nt);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
goto end;
|
||||
}
|
||||
nt->prepared = true;
|
||||
|
||||
end:
|
||||
if (ret < 0) {
|
||||
regulator_bulk_disable(ARRAY_SIZE(nt->vregs), nt->vregs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt35950_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nt35950 *nt = to_nt35950(panel);
|
||||
struct device *dev = &nt->dsi[0]->dev;
|
||||
int ret;
|
||||
|
||||
if (!nt->prepared)
|
||||
return 0;
|
||||
|
||||
ret = nt35950_off(nt);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to deinitialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(nt->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(nt->vregs), nt->vregs);
|
||||
|
||||
nt->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt35950_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct nt35950 *nt = to_nt35950(panel);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nt->desc->num_modes; i++) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev,
|
||||
&nt->desc->mode_data[i].mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type |= DRM_MODE_TYPE_DRIVER;
|
||||
if (nt->desc->num_modes == 1)
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
}
|
||||
|
||||
connector->display_info.bpc = 8;
|
||||
connector->display_info.height_mm = nt->desc->mode_data[0].mode.height_mm;
|
||||
connector->display_info.width_mm = nt->desc->mode_data[0].mode.width_mm;
|
||||
nt->connector = connector;
|
||||
|
||||
return nt->desc->num_modes;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs nt35950_panel_funcs = {
|
||||
.prepare = nt35950_prepare,
|
||||
.unprepare = nt35950_unprepare,
|
||||
.get_modes = nt35950_get_modes,
|
||||
};
|
||||
|
||||
static int nt35950_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct device_node *dsi_r;
|
||||
struct mipi_dsi_host *dsi_r_host;
|
||||
struct nt35950 *nt;
|
||||
const struct mipi_dsi_device_info *info;
|
||||
int i, num_dsis = 1, ret;
|
||||
|
||||
nt = devm_kzalloc(dev, sizeof(*nt), GFP_KERNEL);
|
||||
if (!nt)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = nt35950_sharp_init_vregs(nt, dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Regulator init failure.\n");
|
||||
|
||||
nt->desc = of_device_get_match_data(dev);
|
||||
if (!nt->desc)
|
||||
return -ENODEV;
|
||||
|
||||
nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
|
||||
if (IS_ERR(nt->reset_gpio)) {
|
||||
return dev_err_probe(dev, PTR_ERR(nt->reset_gpio),
|
||||
"Failed to get reset gpio\n");
|
||||
}
|
||||
|
||||
/* If the panel is connected on two DSIs then DSI0 left, DSI1 right */
|
||||
if (nt->desc->is_dual_dsi) {
|
||||
info = &nt->desc->dsi_info;
|
||||
dsi_r = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
|
||||
if (!dsi_r) {
|
||||
dev_err(dev, "Cannot get secondary DSI node.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dsi_r_host = of_find_mipi_dsi_host_by_node(dsi_r);
|
||||
of_node_put(dsi_r);
|
||||
if (!dsi_r_host) {
|
||||
dev_err(dev, "Cannot get secondary DSI host\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
nt->dsi[1] = mipi_dsi_device_register_full(dsi_r_host, info);
|
||||
if (!nt->dsi[1]) {
|
||||
dev_err(dev, "Cannot get secondary DSI node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
num_dsis++;
|
||||
}
|
||||
|
||||
nt->dsi[0] = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, nt);
|
||||
|
||||
drm_panel_init(&nt->panel, dev, &nt35950_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&nt->panel);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get backlight\n");
|
||||
|
||||
drm_panel_add(&nt->panel);
|
||||
|
||||
for (i = 0; i < num_dsis; i++) {
|
||||
nt->dsi[i]->lanes = nt->desc->num_lanes;
|
||||
nt->dsi[i]->format = MIPI_DSI_FMT_RGB888;
|
||||
|
||||
nt->dsi[i]->mode_flags = MIPI_DSI_MODE_EOT_PACKET |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS |
|
||||
MIPI_DSI_MODE_LPM;
|
||||
|
||||
if (nt->desc->mode_data[0].is_video_mode)
|
||||
nt->dsi[i]->mode_flags |= MIPI_DSI_MODE_VIDEO;
|
||||
|
||||
ret = mipi_dsi_attach(nt->dsi[i]);
|
||||
if (ret < 0) {
|
||||
return dev_err_probe(dev, ret,
|
||||
"Cannot attach to DSI%d host.\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure to set RESX LOW before starting the power-on sequence */
|
||||
gpiod_set_value_cansleep(nt->reset_gpio, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nt35950_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct nt35950 *nt = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(nt->dsi[0]);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev,
|
||||
"Failed to detach from DSI0 host: %d\n", ret);
|
||||
|
||||
if (nt->dsi[1]) {
|
||||
ret = mipi_dsi_detach(nt->dsi[1]);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev,
|
||||
"Failed to detach from DSI1 host: %d\n", ret);
|
||||
mipi_dsi_device_unregister(nt->dsi[1]);
|
||||
};
|
||||
|
||||
drm_panel_remove(&nt->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nt35950_panel_mode sharp_ls055d1sx04_modes[] = {
|
||||
{
|
||||
/* 1920x1080 60Hz no compression */
|
||||
.mode = {
|
||||
.clock = 214537,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 400,
|
||||
.hsync_end = 1080 + 400 + 40,
|
||||
.htotal = 1080 + 400 + 40 + 300,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 12,
|
||||
.vsync_end = 1920 + 12 + 2,
|
||||
.vtotal = 1920 + 12 + 2 + 10,
|
||||
.width_mm = 68,
|
||||
.height_mm = 121,
|
||||
.type = DRM_MODE_TYPE_PREFERRED,
|
||||
},
|
||||
.compression = MCS_DATA_COMPRESSION_NONE,
|
||||
.enable_sram = true,
|
||||
.is_video_mode = false,
|
||||
.scaler_on = 1,
|
||||
.scaler_mode = MCS_SCALEUP_DUPLICATE,
|
||||
},
|
||||
/* TODO: Add 2160x3840 60Hz when DSC is supported */
|
||||
};
|
||||
|
||||
const struct nt35950_panel_desc sharp_ls055d1sx04 = {
|
||||
.model_name = "Sharp LS055D1SX04",
|
||||
.dsi_info = {
|
||||
.type = "LS055D1SX04",
|
||||
.channel = 0,
|
||||
.node = NULL,
|
||||
},
|
||||
.mode_data = sharp_ls055d1sx04_modes,
|
||||
.num_modes = ARRAY_SIZE(sharp_ls055d1sx04_modes),
|
||||
.is_dual_dsi = true,
|
||||
.num_lanes = 4,
|
||||
};
|
||||
|
||||
static const struct of_device_id nt35950_of_match[] = {
|
||||
{ .compatible = "sharp,ls055d1sx04", .data = &sharp_ls055d1sx04 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, nt35950_of_match);
|
||||
|
||||
static struct mipi_dsi_driver nt35950_driver = {
|
||||
.probe = nt35950_probe,
|
||||
.remove = nt35950_remove,
|
||||
.driver = {
|
||||
.name = "panel-novatek-nt35950",
|
||||
.of_match_table = nt35950_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(nt35950_driver);
|
||||
|
||||
MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>");
|
||||
MODULE_DESCRIPTION("Novatek NT35950 DriverIC panels driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
351
drivers/gpu/drm/panel/panel-samsung-s6e3fa5.c
Normal file
351
drivers/gpu/drm/panel/panel-samsung-s6e3fa5.c
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2021 Jami Kettunen <jami.kettunen@protonmail.com>
|
||||
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct s6e3fa5 {
|
||||
struct drm_panel panel;
|
||||
enum drm_panel_orientation orientation;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct s6e3fa5 *to_s6e3fa5_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct s6e3fa5, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void s6e3fa5_reset(struct s6e3fa5 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
static int s6e3fa5_on(struct s6e3fa5 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x04);
|
||||
dsi_dcs_write_seq(dsi, 0xb4, 0x06, 0x0c, 0x12);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xc3, 0x01);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x18);
|
||||
dsi_dcs_write_seq(dsi, 0xc3, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_off(struct s6e3fa5 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(40);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(160);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fa5 *ctx = to_s6e3fa5_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(ctx->supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s6e3fa5_reset(ctx);
|
||||
|
||||
ret = s6e3fa5_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fa5 *ctx = to_s6e3fa5_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = s6e3fa5_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode s6e3fa5_mode = {
|
||||
.clock = (1080 + 120 + 19 + 70) * (1920 + 18 + 2 + 4) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 120,
|
||||
.hsync_end = 1080 + 120 + 19,
|
||||
.htotal = 1080 + 120 + 19 + 70,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 18,
|
||||
.vsync_end = 1920 + 18 + 2,
|
||||
.vtotal = 1920 + 18 + 2 + 4,
|
||||
.width_mm = 68,
|
||||
.height_mm = 122,
|
||||
};
|
||||
|
||||
static int s6e3fa5_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct s6e3fa5 *ctx;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &s6e3fa5_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
ctx = to_s6e3fa5_panel(panel);
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_connector_set_panel_orientation(connector, ctx->orientation);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs s6e3fa5_panel_funcs = {
|
||||
.prepare = s6e3fa5_prepare,
|
||||
.unprepare = s6e3fa5_unprepare,
|
||||
.get_modes = s6e3fa5_get_modes,
|
||||
};
|
||||
|
||||
static int s6e3fa5_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness = backlight_get_brightness(bl);
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return brightness & 0xff;
|
||||
}
|
||||
|
||||
static const struct backlight_ops s6e3fa5_bl_ops = {
|
||||
.update_status = s6e3fa5_bl_update_status,
|
||||
.get_brightness = s6e3fa5_bl_get_brightness,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
s6e3fa5_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 255,
|
||||
.max_brightness = 255,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&s6e3fa5_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int s6e3fa5_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct s6e3fa5 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supply = devm_regulator_get(dev, "vddio");
|
||||
if (IS_ERR(ctx->supply))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->supply),
|
||||
"Failed to get vddio regulator\n");
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE |
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to parse rotation property: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &s6e3fa5_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->panel.backlight = s6e3fa5_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
|
||||
"Failed to create backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fa5_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct s6e3fa5 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id s6e3fa5_of_match[] = {
|
||||
{ .compatible = "samsung,s6e3fa5" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, s6e3fa5_of_match);
|
||||
|
||||
static struct mipi_dsi_driver s6e3fa5_driver = {
|
||||
.probe = s6e3fa5_probe,
|
||||
.remove = s6e3fa5_remove,
|
||||
.driver = {
|
||||
.name = "panel-samsung-s6e3fa5",
|
||||
.of_match_table = s6e3fa5_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(s6e3fa5_driver);
|
||||
|
||||
MODULE_AUTHOR("Jami Kettunen <jami.kettunen@protonmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for Samsung S6E3FA5 AMOLED DSI cmd mode panel found on OnePlus 5 phones");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
345
drivers/gpu/drm/panel/panel-samsung-s6e3fc1.c
Normal file
345
drivers/gpu/drm/panel/panel-samsung-s6e3fc1.c
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2021 Jami Kettunen <jami.kettunen@protonmail.com>
|
||||
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/swab.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct s6e3fc1 {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct s6e3fc1 *to_s6e3fc1_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct s6e3fc1, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void s6e3fc1_reset(struct s6e3fc1 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
static int s6e3fc1_on(struct s6e3fc1 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(25);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xe8, 0x64, 0x08, 0x0c);
|
||||
dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x01);
|
||||
dsi_dcs_write_seq(dsi, 0xed, 0x04);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_off(struct s6e3fc1 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(160);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fc1 *ctx = to_s6e3fc1_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(ctx->supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s6e3fc1_reset(ctx);
|
||||
|
||||
ret = s6e3fc1_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct s6e3fc1 *ctx = to_s6e3fc1_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = s6e3fc1_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode s6e3fc1_mode = {
|
||||
.clock = (1080 + 128 + 16 + 64) * (2160 + 18 + 2 + 4) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 128,
|
||||
.hsync_end = 1080 + 128 + 16,
|
||||
.htotal = 1080 + 128 + 16 + 64,
|
||||
.vdisplay = 2160,
|
||||
.vsync_start = 2160 + 18,
|
||||
.vsync_end = 2160 + 18 + 2,
|
||||
.vtotal = 2160 + 18 + 2 + 4,
|
||||
.width_mm = 68,
|
||||
.height_mm = 137,
|
||||
};
|
||||
|
||||
static int s6e3fc1_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &s6e3fc1_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs s6e3fc1_panel_funcs = {
|
||||
.prepare = s6e3fc1_prepare,
|
||||
.unprepare = s6e3fc1_unprepare,
|
||||
.get_modes = s6e3fc1_get_modes,
|
||||
};
|
||||
|
||||
static int s6e3fc1_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
brightness = (u16)backlight_get_brightness(bl);
|
||||
// This panel needs the high and low bytes swapped for the brightness value
|
||||
brightness = __swab16(brightness);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
// This panel needs the high and low bytes swapped for the brightness value
|
||||
brightness = __swab16(brightness);
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
return brightness;
|
||||
}
|
||||
|
||||
static const struct backlight_ops s6e3fc1_bl_ops = {
|
||||
.update_status = s6e3fc1_bl_update_status,
|
||||
.get_brightness = s6e3fc1_bl_get_brightness,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
s6e3fc1_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 1023,
|
||||
.max_brightness = 1023,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&s6e3fc1_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int s6e3fc1_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct s6e3fc1 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supply = devm_regulator_get(dev, "vddio");
|
||||
if (IS_ERR(ctx->supply))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->supply),
|
||||
"Failed to get vddio regulator\n");
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &s6e3fc1_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->panel.backlight = s6e3fc1_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
|
||||
"Failed to create backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s6e3fc1_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct s6e3fc1 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id s6e3fc1_of_match[] = {
|
||||
{ .compatible = "samsung,s6e3fc1" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, s6e3fc1_of_match);
|
||||
|
||||
static struct mipi_dsi_driver s6e3fc1_driver = {
|
||||
.probe = s6e3fc1_probe,
|
||||
.remove = s6e3fc1_remove,
|
||||
.driver = {
|
||||
.name = "panel-samsung-s6e3fc1",
|
||||
.of_match_table = s6e3fc1_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(s6e3fc1_driver);
|
||||
|
||||
MODULE_AUTHOR("Jami Kettunen <jami.kettunen@protonmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for Samsung S6E3FC1 AMOLED DSI cmd mode panel found on OnePlus 5T phones");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -5158,6 +5158,68 @@ static const struct panel_desc_dsi osd101t2045_53ts = {
|
|||
.lanes = 4,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode sony_kirin_nt36672a_truly_mode = {
|
||||
.clock = (1080 + 25 + 12 + 120) * (2520 + 12 + 4 + 10) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 25,
|
||||
.hsync_end = 1080 + 25 + 12,
|
||||
.htotal = 1080 + 25 + 12 + 120,
|
||||
.vdisplay = 2520,
|
||||
.vsync_start = 2520 + 12,
|
||||
.vsync_end = 2520 + 12 + 4,
|
||||
.vtotal = 2520 + 12 + 4 + 10,
|
||||
.width_mm = 60,
|
||||
.height_mm = 139,
|
||||
};
|
||||
|
||||
static const struct panel_desc_dsi sony_kirin_nt36672a_truly = {
|
||||
.desc = {
|
||||
.modes = &sony_kirin_nt36672a_truly_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 60,
|
||||
.height = 139,
|
||||
},
|
||||
.connector_type = DRM_MODE_CONNECTOR_DSI,
|
||||
},
|
||||
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.lanes = 4,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode sony_mermaid_nt36672a_tianma_mode = {
|
||||
.clock = (1080 + 102 + 20 + 40) * (2520 + 10 + 2 + 8) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 102,
|
||||
.hsync_end = 1080 + 102 + 20,
|
||||
.htotal = 1080 + 102 + 20 + 40,
|
||||
.vdisplay = 2520,
|
||||
.vsync_start = 2520 + 10,
|
||||
.vsync_end = 2520 + 10 + 2,
|
||||
.vtotal = 2520 + 10 + 2 + 8,
|
||||
.width_mm = 65,
|
||||
.height_mm = 151,
|
||||
};
|
||||
|
||||
static const struct panel_desc_dsi sony_mermaid_nt36672a_tianma = {
|
||||
.desc = {
|
||||
.modes = &sony_mermaid_nt36672a_tianma_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 65,
|
||||
.height = 151,
|
||||
},
|
||||
.connector_type = DRM_MODE_CONNECTOR_DSI,
|
||||
},
|
||||
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.lanes = 4,
|
||||
};
|
||||
|
||||
static const struct of_device_id dsi_of_match[] = {
|
||||
{
|
||||
.compatible = "auo,b080uan01",
|
||||
|
|
@ -5180,6 +5242,12 @@ static const struct of_device_id dsi_of_match[] = {
|
|||
}, {
|
||||
.compatible = "osddisplays,osd101t2045-53ts",
|
||||
.data = &osd101t2045_53ts
|
||||
}, {
|
||||
.compatible = "sony,kirin-nt36672a-truly",
|
||||
.data = &sony_kirin_nt36672a_truly
|
||||
}, {
|
||||
.compatible = "sony,mermaid-nt36672a-tianma",
|
||||
.data = &sony_mermaid_nt36672a_tianma
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
|
|
|
|||
265
drivers/gpu/drm/panel/panel-td4322-innolux-fhd.c
Normal file
265
drivers/gpu/drm/panel/panel-td4322-innolux-fhd.c
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct td4322_innolux_fhd {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator_bulk_data supplies[4];
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct td4322_innolux_fhd *to_td4322_innolux_fhd(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct td4322_innolux_fhd, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void td4322_innolux_fhd_reset(struct td4322_innolux_fhd *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
msleep(30);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
msleep(150);
|
||||
}
|
||||
|
||||
static int td4322_innolux_fhd_on(struct td4322_innolux_fhd *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(70);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_innolux_fhd_off(struct td4322_innolux_fhd *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_innolux_fhd_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct td4322_innolux_fhd *ctx = to_td4322_innolux_fhd(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
td4322_innolux_fhd_reset(ctx);
|
||||
|
||||
ret = td4322_innolux_fhd_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_innolux_fhd_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct td4322_innolux_fhd *ctx = to_td4322_innolux_fhd(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = td4322_innolux_fhd_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode td4322_innolux_fhd_mode = {
|
||||
.clock = (1080 + 96 + 20 + 48) * (1920 + 5 + 2 + 3) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 96,
|
||||
.hsync_end = 1080 + 96 + 20,
|
||||
.htotal = 1080 + 96 + 20 + 48,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 5,
|
||||
.vsync_end = 1920 + 5 + 2,
|
||||
.vtotal = 1920 + 5 + 2 + 3,
|
||||
.width_mm = 74,
|
||||
.height_mm = 132,
|
||||
};
|
||||
|
||||
static int td4322_innolux_fhd_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &td4322_innolux_fhd_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs td4322_innolux_fhd_panel_funcs = {
|
||||
.prepare = td4322_innolux_fhd_prepare,
|
||||
.unprepare = td4322_innolux_fhd_unprepare,
|
||||
.get_modes = td4322_innolux_fhd_get_modes,
|
||||
};
|
||||
|
||||
static int td4322_innolux_fhd_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct td4322_innolux_fhd *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supplies[0].supply = "vdd";
|
||||
ctx->supplies[1].supply = "vddio";
|
||||
ctx->supplies[2].supply = "vsn";
|
||||
ctx->supplies[3].supply = "vsp";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to get regulators\n");
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &td4322_innolux_fhd_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_innolux_fhd_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct td4322_innolux_fhd *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id td4322_innolux_fhd_of_match[] = {
|
||||
{ .compatible = "sony,discovery-td4322-innolux" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, td4322_innolux_fhd_of_match);
|
||||
|
||||
static struct mipi_dsi_driver td4322_innolux_fhd_driver = {
|
||||
.probe = td4322_innolux_fhd_probe,
|
||||
.remove = td4322_innolux_fhd_remove,
|
||||
.driver = {
|
||||
.name = "panel-td4322-innolux-fhd",
|
||||
.of_match_table = td4322_innolux_fhd_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(td4322_innolux_fhd_driver);
|
||||
|
||||
MODULE_AUTHOR("Konrad Dybcio <konradybcio@gmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for Sony TD4322 Innolux FHD panel");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
277
drivers/gpu/drm/panel/panel-td4322-truly-fhd.c
Normal file
277
drivers/gpu/drm/panel/panel-td4322-truly-fhd.c
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct td4322_truly_fhd {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator_bulk_data supplies[4];
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct td4322_truly_fhd *to_td4322_truly_fhd(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct td4322_truly_fhd, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void td4322_truly_fhd_reset(struct td4322_truly_fhd *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
msleep(30);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
msleep(150);
|
||||
}
|
||||
|
||||
static int td4322_truly_fhd_on(struct td4322_truly_fhd *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd5,
|
||||
0x03, 0x00, 0x00, 0x02, 0x23, 0x02, 0x23);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(30);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_truly_fhd_off(struct td4322_truly_fhd *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_truly_fhd_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct td4322_truly_fhd *ctx = to_td4322_truly_fhd(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
td4322_truly_fhd_reset(ctx);
|
||||
|
||||
ret = td4322_truly_fhd_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_truly_fhd_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct td4322_truly_fhd *ctx = to_td4322_truly_fhd(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = td4322_truly_fhd_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode td4322_truly_fhd_mode = {
|
||||
.clock = (1080 + 104 + 20 + 56) * (1920 + 10 + 2 + 8) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 104,
|
||||
.hsync_end = 1080 + 104 + 20,
|
||||
.htotal = 1080 + 104 + 20 + 56,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 10,
|
||||
.vsync_end = 1920 + 10 + 2,
|
||||
.vtotal = 1920 + 10 + 2 + 8,
|
||||
.width_mm = 64,
|
||||
.height_mm = 115,
|
||||
};
|
||||
|
||||
static int td4322_truly_fhd_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &td4322_truly_fhd_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs td4322_truly_fhd_panel_funcs = {
|
||||
.prepare = td4322_truly_fhd_prepare,
|
||||
.unprepare = td4322_truly_fhd_unprepare,
|
||||
.get_modes = td4322_truly_fhd_get_modes,
|
||||
};
|
||||
|
||||
static int td4322_truly_fhd_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct td4322_truly_fhd *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supplies[0].supply = "vdd";
|
||||
ctx->supplies[1].supply = "vddio";
|
||||
ctx->supplies[2].supply = "vsn";
|
||||
ctx->supplies[3].supply = "vsp";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio)) {
|
||||
ret = PTR_ERR(ctx->reset_gpio);
|
||||
dev_err(dev, "Failed to get reset-gpios: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &td4322_truly_fhd_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get backlight: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add panel: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4322_truly_fhd_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct td4322_truly_fhd *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id td4322_truly_fhd_of_match[] = {
|
||||
{ .compatible = "sony,pioneer-td4322-truly" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, td4322_truly_fhd_of_match);
|
||||
|
||||
static struct mipi_dsi_driver td4322_truly_fhd_driver = {
|
||||
.probe = td4322_truly_fhd_probe,
|
||||
.remove = td4322_truly_fhd_remove,
|
||||
.driver = {
|
||||
.name = "panel-td4322-truly-fhd",
|
||||
.of_match_table = td4322_truly_fhd_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(td4322_truly_fhd_driver);
|
||||
|
||||
MODULE_AUTHOR("Konrad Dybcio <konradybcio@gmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for TD4322 Truly FHD CMD mode panel");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
264
drivers/gpu/drm/panel/panel-td4328-tianma-fhdplus.c
Normal file
264
drivers/gpu/drm/panel/panel-td4328-tianma-fhdplus.c
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct td4328_tianma_fhdplus {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator_bulk_data supplies[4];
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct td4328_tianma_fhdplus *to_td4328_tianma_fhdplus(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct td4328_tianma_fhdplus, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void td4328_tianma_fhdplus_reset(struct td4328_tianma_fhdplus *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
msleep(30);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
msleep(150);
|
||||
}
|
||||
|
||||
static int td4328_tianma_fhdplus_on(struct td4328_tianma_fhdplus *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x04);
|
||||
dsi_generic_write_seq(dsi, 0xb3, 0x00, 0x00, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xd6, 0x01);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(70);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4328_tianma_fhdplus_off(struct td4328_tianma_fhdplus *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(50);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4328_tianma_fhdplus_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct td4328_tianma_fhdplus *ctx = to_td4328_tianma_fhdplus(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
td4328_tianma_fhdplus_reset(ctx);
|
||||
|
||||
ret = td4328_tianma_fhdplus_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4328_tianma_fhdplus_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct td4328_tianma_fhdplus *ctx = to_td4328_tianma_fhdplus(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = td4328_tianma_fhdplus_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode td4328_tianma_fhdplus_mode = {
|
||||
.clock = (1080 + 76 + 4 + 20) * (2160 + 5 + 1 + 30) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 76,
|
||||
.hsync_end = 1080 + 76 + 4,
|
||||
.htotal = 1080 + 76 + 4 + 20,
|
||||
.vdisplay = 2160,
|
||||
.vsync_start = 2160 + 5,
|
||||
.vsync_end = 2160 + 5 + 1,
|
||||
.vtotal = 2160 + 5 + 1 + 30,
|
||||
.width_mm = 68,
|
||||
.height_mm = 136,
|
||||
};
|
||||
|
||||
static int td4328_tianma_fhdplus_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &td4328_tianma_fhdplus_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs td4328_tianma_fhdplus_panel_funcs = {
|
||||
.prepare = td4328_tianma_fhdplus_prepare,
|
||||
.unprepare = td4328_tianma_fhdplus_unprepare,
|
||||
.get_modes = td4328_tianma_fhdplus_get_modes,
|
||||
};
|
||||
|
||||
static int td4328_tianma_fhdplus_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct td4328_tianma_fhdplus *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supplies[0].supply = "vdd";
|
||||
ctx->supplies[1].supply = "vddio";
|
||||
ctx->supplies[2].supply = "vsn";
|
||||
ctx->supplies[3].supply = "vsp";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to get regulators\n");
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &td4328_tianma_fhdplus_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int td4328_tianma_fhdplus_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct td4328_tianma_fhdplus *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id td4328_tianma_fhdplus_of_match[] = {
|
||||
{ .compatible = "sony,voyager-td4328-tianma" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, td4328_tianma_fhdplus_of_match);
|
||||
|
||||
static struct mipi_dsi_driver td4328_tianma_fhdplus_driver = {
|
||||
.probe = td4328_tianma_fhdplus_probe,
|
||||
.remove = td4328_tianma_fhdplus_remove,
|
||||
.driver = {
|
||||
.name = "panel-td4328-tianma-fhdplus",
|
||||
.of_match_table = td4328_tianma_fhdplus_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(td4328_tianma_fhdplus_driver);
|
||||
|
||||
MODULE_AUTHOR("Konrad Dybcio <konradybcio@gmail.com>");
|
||||
MODULE_DESCRIPTION("DRM driver for 7");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -39,6 +39,8 @@
|
|||
#define QUP_MX_READ_CNT 0x208
|
||||
#define QUP_IN_FIFO_BASE 0x218
|
||||
#define QUP_I2C_CLK_CTL 0x400
|
||||
#define QUP_I2C_CLK_CTL_SDA_NR GENMASK(27, 26)
|
||||
#define QUP_I2C_CLK_CTL_SCL_NR GENMASK(25, 24)
|
||||
#define QUP_I2C_STATUS 0x404
|
||||
#define QUP_I2C_MASTER_GEN 0x408
|
||||
|
||||
|
|
@ -1663,6 +1665,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
|
|||
int ret, fs_div, hs_div;
|
||||
u32 src_clk_freq = DEFAULT_SRC_CLK;
|
||||
u32 clk_freq = DEFAULT_CLK_FREQ;
|
||||
u32 noise_reject_scl = 0, noise_reject_sda = 0;
|
||||
int blocks;
|
||||
bool is_qup_v1;
|
||||
|
||||
|
|
@ -1860,6 +1863,19 @@ nodma:
|
|||
qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
|
||||
}
|
||||
|
||||
/* SCL/SDA Noise rejection (optional) */
|
||||
ret = device_property_read_u32(qup->dev, "qcom,noise-reject-scl",
|
||||
&noise_reject_scl);
|
||||
if (ret == 0)
|
||||
qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SCL_NR,
|
||||
noise_reject_scl);
|
||||
|
||||
ret = device_property_read_u32(qup->dev, "qcom,noise-reject-sda",
|
||||
&noise_reject_sda);
|
||||
if (ret == 0)
|
||||
qup->clk_ctl |= FIELD_PREP(QUP_I2C_CLK_CTL_SDA_NR,
|
||||
noise_reject_sda);
|
||||
|
||||
/*
|
||||
* Time it takes for a byte to be clocked out on the bus.
|
||||
* Each byte takes 9 clock cycles (8 bits + 1 ack).
|
||||
|
|
|
|||
|
|
@ -242,6 +242,19 @@ config KEYBOARD_GPIO
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called gpio_keys.
|
||||
|
||||
config KEYBOARD_GPIO_FASTMATRIX
|
||||
tristate "GPIO Keyboard"
|
||||
depends on GPIOLIB
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
This driver implements support for matrix keypads and/or
|
||||
keyboards connected directly to GPIO pins of a CPU, made
|
||||
to also perform with slow I2C GPIO expanders and even
|
||||
on matrices with no protection diodes.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gpio_fastmatrix
|
||||
|
||||
config KEYBOARD_GPIO_POLLED
|
||||
tristate "Polled GPIO buttons"
|
||||
depends on GPIOLIB
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ obj-$(CONFIG_KEYBOARD_DLINK_DIR685) += dlink-dir685-touchkeys.o
|
|||
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO_FASTMATRIX) += gpio_fastmatrix.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o
|
||||
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_TCA8418) += tca8418_keypad.o
|
||||
|
|
|
|||
528
drivers/input/keyboard/gpio_fastmatrix.c
Normal file
528
drivers/input/keyboard/gpio_fastmatrix.c
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Fast GPIO driven keyboard/keypad matrix driver
|
||||
*
|
||||
* Copyright (c) 2020 AngeloGioacchino Del Regno
|
||||
* <angelogioacchino.delregno@somainline.org>
|
||||
* Based on matrix_keypad.c
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
struct gpio_keyboard {
|
||||
struct device *dev;
|
||||
struct input_dev *input_dev;
|
||||
unsigned int row_shift;
|
||||
|
||||
struct gpio_descs *row_gpios;
|
||||
struct gpio_descs *col_gpios;
|
||||
u32 autorescan_ms;
|
||||
u32 debounce_ms;
|
||||
u32 col_scan_us;
|
||||
int clustered_irq;
|
||||
|
||||
DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
|
||||
|
||||
u32 last_key_state[MATRIX_MAX_COLS];
|
||||
struct delayed_work work;
|
||||
struct mutex lock;
|
||||
|
||||
bool drive_inactive_cols;
|
||||
bool gpio_all_disabled;
|
||||
bool scan_pending;
|
||||
bool stopped;
|
||||
};
|
||||
|
||||
static int activate_one_column(struct gpio_keyboard *gkb, int col, bool wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpiod_direction_output(gkb->col_gpios->desc[col], 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (wait && gkb->col_scan_us)
|
||||
udelay(gkb->col_scan_us);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: If drive_inactive_cols is false, then the GPIO has to be put into
|
||||
* HiZ when de-activated to cause minmal side effect when scanning other
|
||||
* columns. In that case it is configured here to be input, otherwise it is
|
||||
* driven with the inactive value.
|
||||
*/
|
||||
static int deactivate_one_column(struct gpio_keyboard *gkb, int col)
|
||||
{
|
||||
gpiod_set_value_cansleep(gkb->col_gpios->desc[col], 0);
|
||||
if (!gkb->drive_inactive_cols)
|
||||
return gpiod_direction_input(gkb->col_gpios->desc[col]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int activate_all_cols(struct gpio_keyboard *gkb)
|
||||
{
|
||||
unsigned long val = ULONG_MAX;
|
||||
int ret, col;
|
||||
|
||||
/*
|
||||
* Shortcut! If we don't have to set direction, we can use
|
||||
* the way faster gpiod array setting instead.
|
||||
*/
|
||||
if (gkb->drive_inactive_cols) {
|
||||
return gpiod_set_array_value_cansleep(gkb->col_gpios->ndescs,
|
||||
gkb->col_gpios->desc,
|
||||
gkb->col_gpios->info,
|
||||
&val);
|
||||
}
|
||||
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++) {
|
||||
ret = activate_one_column(gkb, col, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int deactivate_all_cols(struct gpio_keyboard *gkb)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
int col, ret;
|
||||
|
||||
/*
|
||||
* If the GPIO controller supports setting all pins at once it
|
||||
* is going to be way faster, otherwise this function will fall
|
||||
* back to setting all pins one at a time.
|
||||
*/
|
||||
ret = gpiod_set_array_value_cansleep(gkb->col_gpios->ndescs,
|
||||
gkb->col_gpios->desc,
|
||||
gkb->col_gpios->info, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!gkb->drive_inactive_cols) {
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++)
|
||||
gpiod_direction_input(gkb->col_gpios->desc[col]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void enable_row_irqs(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (gkb->clustered_irq > 0)
|
||||
enable_irq(gkb->clustered_irq);
|
||||
else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++)
|
||||
enable_irq(gpiod_to_irq(gkb->row_gpios->desc[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void disable_row_irqs(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (gkb->clustered_irq > 0)
|
||||
disable_irq_nosync(gkb->clustered_irq);
|
||||
else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++)
|
||||
disable_irq_nosync(gpiod_to_irq(gkb->row_gpios->desc[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This gets the keys from keyboard and reports it to input subsystem
|
||||
*/
|
||||
static void gpio_keyboard_scan(struct work_struct *work)
|
||||
{
|
||||
struct gpio_keyboard *gkb =
|
||||
container_of(work, struct gpio_keyboard, work.work);
|
||||
struct input_dev *input_dev = gkb->input_dev;
|
||||
const unsigned short *keycodes = input_dev->keycode;
|
||||
u32 *new_state;
|
||||
unsigned long row_values;
|
||||
int ret, row, col, code;
|
||||
u32 keymask = 0;
|
||||
|
||||
new_state = kzalloc(gkb->col_gpios->ndescs * sizeof(*new_state),
|
||||
GFP_KERNEL);
|
||||
if (!new_state)
|
||||
return;
|
||||
|
||||
/* de-activate all columns for scanning */
|
||||
deactivate_all_cols(gkb);
|
||||
|
||||
/* assert each column and read the row status out */
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++) {
|
||||
activate_one_column(gkb, col, true);
|
||||
|
||||
ret = gpiod_get_array_value_cansleep(gkb->row_gpios->ndescs,
|
||||
gkb->row_gpios->desc,
|
||||
gkb->row_gpios->info,
|
||||
&row_values);
|
||||
new_state[col] = row_values;
|
||||
keymask |= new_state[col];
|
||||
|
||||
if (deactivate_one_column(gkb, col)) {
|
||||
activate_all_cols(gkb);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
activate_all_cols(gkb);
|
||||
|
||||
for (col = 0; col < gkb->col_gpios->ndescs; col++) {
|
||||
u32 bits_changed = gkb->last_key_state[col] ^ new_state[col];
|
||||
if (bits_changed == 0)
|
||||
continue;
|
||||
|
||||
for (row = 0; bits_changed; row++, bits_changed >>=1 ) {
|
||||
if (!(bits_changed & BIT(0)))
|
||||
continue;
|
||||
|
||||
code = MATRIX_SCAN_CODE(row, col, gkb->row_shift);
|
||||
input_event(input_dev, EV_MSC, MSC_SCAN, code);
|
||||
input_report_key(input_dev, keycodes[code],
|
||||
new_state[col] & (1 << row));
|
||||
}
|
||||
}
|
||||
input_sync(input_dev);
|
||||
|
||||
memcpy(gkb->last_key_state, new_state, sizeof(gkb->last_key_state));
|
||||
kfree(new_state);
|
||||
|
||||
/* Avoid missing key release events on quirky hardware */
|
||||
if (gkb->autorescan_ms && keymask) {
|
||||
queue_delayed_work(system_highpri_wq, &gkb->work,
|
||||
msecs_to_jiffies(gkb->autorescan_ms));
|
||||
return;
|
||||
}
|
||||
end:
|
||||
/* Enable IRQs again */
|
||||
mutex_lock(&gkb->lock);
|
||||
gkb->scan_pending = false;
|
||||
enable_row_irqs(gkb);
|
||||
mutex_unlock(&gkb->lock);
|
||||
}
|
||||
|
||||
static irqreturn_t gpio_keyboard_interrupt(int irq, void *id)
|
||||
{
|
||||
struct gpio_keyboard *gkb = id;
|
||||
|
||||
/*
|
||||
* See if another IRQ beaten us to it and scheduled the
|
||||
* scan already. In that case we should not try to
|
||||
* disable IRQs again.
|
||||
*/
|
||||
if (unlikely(gkb->scan_pending || gkb->stopped))
|
||||
goto out;
|
||||
|
||||
mutex_lock(&gkb->lock);
|
||||
|
||||
disable_row_irqs(gkb);
|
||||
gkb->scan_pending = true;
|
||||
mod_delayed_work(system_highpri_wq, &gkb->work,
|
||||
msecs_to_jiffies(gkb->debounce_ms));
|
||||
|
||||
out:
|
||||
mutex_unlock(&gkb->lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_start(struct input_dev *dev)
|
||||
{
|
||||
struct gpio_keyboard *gkb = input_get_drvdata(dev);
|
||||
|
||||
gkb->stopped = false;
|
||||
|
||||
/*
|
||||
* Schedule an immediate key scan to capture current key state;
|
||||
* columns will be activated and IRQs be enabled after the scan.
|
||||
*/
|
||||
schedule_delayed_work(&gkb->work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_keyboard_stop(struct input_dev *dev)
|
||||
{
|
||||
struct gpio_keyboard *gkb = input_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&gkb->lock);
|
||||
gkb->stopped = true;
|
||||
mutex_unlock(&gkb->lock);
|
||||
|
||||
flush_delayed_work(&gkb->work);
|
||||
/*
|
||||
* gpio_keyboard_scan() will leave IRQs enabled;
|
||||
* we should disable them now.
|
||||
*/
|
||||
disable_row_irqs(gkb);
|
||||
}
|
||||
|
||||
static void __maybe_unused gpio_keyboard_wakeup_en(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int irq, i;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
if (enable_irq_wake(gkb->clustered_irq) == 0)
|
||||
gkb->gpio_all_disabled = true;
|
||||
} else {
|
||||
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++) {
|
||||
if (!test_bit(i, gkb->disabled_gpios)) {
|
||||
irq = gpiod_to_irq(gkb->row_gpios->desc[i]);
|
||||
|
||||
if (enable_irq_wake(irq) == 0)
|
||||
__set_bit(i, gkb->disabled_gpios);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __maybe_unused gpio_keyboard_wakeup_dis(struct gpio_keyboard *gkb)
|
||||
{
|
||||
int irq, i;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
if (gkb->gpio_all_disabled) {
|
||||
disable_irq_wake(gkb->clustered_irq);
|
||||
gkb->gpio_all_disabled = false;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++) {
|
||||
if (test_and_clear_bit(i, gkb->disabled_gpios)) {
|
||||
irq = gpiod_to_irq(gkb->row_gpios->desc[i]);
|
||||
disable_irq_wake(irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __maybe_unused gpio_keyboard_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct gpio_keyboard *gkb = platform_get_drvdata(pdev);
|
||||
|
||||
gpio_keyboard_stop(gkb->input_dev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
gpio_keyboard_wakeup_en(gkb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused gpio_keyboard_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct gpio_keyboard *gkb = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
gpio_keyboard_wakeup_dis(gkb);
|
||||
|
||||
gpio_keyboard_start(gkb->input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static SIMPLE_DEV_PM_OPS(gpio_keyboard_pm_ops,
|
||||
gpio_keyboard_suspend, gpio_keyboard_resume);
|
||||
|
||||
static int gpio_keyboard_init_gpio(struct platform_device *pdev,
|
||||
struct gpio_keyboard *gkb)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
ret = devm_request_threaded_irq(gkb->dev, gkb->clustered_irq,
|
||||
NULL, gpio_keyboard_interrupt,
|
||||
IRQF_ONESHOT, "gpio-keyboard", gkb);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot get IRQ %d\n", gkb->clustered_irq);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++) {
|
||||
ret = devm_request_threaded_irq(
|
||||
gkb->dev,
|
||||
gpiod_to_irq(gkb->row_gpios->desc[i]),
|
||||
NULL, gpio_keyboard_interrupt,
|
||||
IRQF_TRIGGER_HIGH |
|
||||
IRQF_TRIGGER_LOW,
|
||||
"gpio-keyboard", gkb);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot get IRQ for gpio%d\n",
|
||||
desc_to_gpio(gkb->row_gpios->desc[i]));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* initialized as disabled - enabled by input->open */
|
||||
disable_row_irqs(gkb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_parse_dt(struct gpio_keyboard *gkb)
|
||||
{
|
||||
struct device *dev = gkb->dev;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Get as GPIOD_ASIS to use the configuration that comes from
|
||||
* device-tree. Anyway, in many cases the row is configured as
|
||||
* input, while the column is configured as output-high.
|
||||
*
|
||||
* This may vary depending on the hardware.
|
||||
*/
|
||||
gkb->row_gpios = devm_gpiod_get_array(dev, "row", GPIOD_ASIS);
|
||||
if (IS_ERR(gkb->row_gpios))
|
||||
return PTR_ERR(gkb->row_gpios);
|
||||
|
||||
gkb->col_gpios = devm_gpiod_get_array(dev, "col", GPIOD_ASIS);
|
||||
if (IS_ERR(gkb->col_gpios))
|
||||
return PTR_ERR(gkb->col_gpios);
|
||||
|
||||
/* All of these additional properties are optional */
|
||||
device_property_read_string(dev, "label", &gkb->input_dev->name);
|
||||
|
||||
if (device_property_read_bool(dev, "autorepeat"))
|
||||
__set_bit(EV_REP, gkb->input_dev->evbit);
|
||||
|
||||
gkb->drive_inactive_cols =
|
||||
device_property_read_bool(dev, "drive-inactive-cols");
|
||||
|
||||
rc = device_property_read_u32(dev, "autorescan-ms",
|
||||
&gkb->autorescan_ms);
|
||||
if (rc < 0)
|
||||
gkb->autorescan_ms = 0;
|
||||
|
||||
rc = device_property_read_u32(dev, "debounce-delay-ms",
|
||||
&gkb->debounce_ms);
|
||||
if (rc < 0)
|
||||
gkb->debounce_ms = 0;
|
||||
|
||||
rc = device_property_read_u32(dev, "col-scan-delay-us",
|
||||
&gkb->col_scan_us);
|
||||
if (rc < 0)
|
||||
gkb->col_scan_us = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_keyboard *gkb;
|
||||
bool wake;
|
||||
int irq, ret;
|
||||
|
||||
gkb = devm_kmalloc(&pdev->dev, sizeof(*gkb), GFP_KERNEL);
|
||||
if (!gkb)
|
||||
return -ENOMEM;
|
||||
|
||||
gkb->dev = &pdev->dev;
|
||||
gkb->input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!gkb->input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = gpio_keyboard_parse_dt(gkb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
irq = platform_get_irq_optional(pdev, 0);
|
||||
gkb->clustered_irq = (irq > 0) ? irq : 0;
|
||||
gkb->row_shift = get_count_order(gkb->col_gpios->ndescs);
|
||||
gkb->stopped = true;
|
||||
INIT_DELAYED_WORK(&gkb->work, gpio_keyboard_scan);
|
||||
memset(gkb->last_key_state, 0, sizeof(gkb->last_key_state));
|
||||
mutex_init(&gkb->lock);
|
||||
|
||||
if (!gkb->input_dev->name)
|
||||
gkb->input_dev->name = pdev->name;
|
||||
gkb->input_dev->id.bustype = BUS_HOST;
|
||||
gkb->input_dev->dev.parent = &pdev->dev;
|
||||
gkb->input_dev->open = gpio_keyboard_start;
|
||||
gkb->input_dev->close = gpio_keyboard_stop;
|
||||
|
||||
ret = matrix_keypad_build_keymap(NULL, NULL,
|
||||
gkb->row_gpios->ndescs,
|
||||
gkb->col_gpios->ndescs,
|
||||
NULL, gkb->input_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to build keymap\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
input_set_capability(gkb->input_dev, EV_MSC, MSC_SCAN);
|
||||
input_set_drvdata(gkb->input_dev, gkb);
|
||||
|
||||
ret = gpio_keyboard_init_gpio(pdev, gkb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = input_register_device(gkb->input_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
wake = device_property_read_bool(&pdev->dev, "wakeup-source");
|
||||
device_init_wakeup(&pdev->dev, wake);
|
||||
|
||||
platform_set_drvdata(pdev, gkb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_keyboard_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_keyboard *gkb = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
if (gkb->clustered_irq > 0) {
|
||||
free_irq(gkb->clustered_irq, gkb);
|
||||
} else {
|
||||
for (i = 0; i < gkb->row_gpios->ndescs; i++)
|
||||
free_irq(gpiod_to_irq(gkb->row_gpios->desc[i]), gkb);
|
||||
}
|
||||
input_unregister_device(gkb->input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id gpio_keyboard_dt_match[] = {
|
||||
{ .compatible = "gpio-fastmatrix-keyboard" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, gpio_keyboard_dt_match);
|
||||
|
||||
static struct platform_driver gpio_keyboard_driver = {
|
||||
.probe = gpio_keyboard_probe,
|
||||
.remove = gpio_keyboard_remove,
|
||||
.driver = {
|
||||
.name = "gpio-fastmatrix-keyboard",
|
||||
.pm = &gpio_keyboard_pm_ops,
|
||||
.of_match_table = gpio_keyboard_dt_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(gpio_keyboard_driver);
|
||||
|
||||
MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>");
|
||||
MODULE_DESCRIPTION("Fast GPIO driven keyboard/keypad matrix driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:gpio-fastmatrix-keyboard");
|
||||
|
|
@ -186,6 +186,18 @@ config INPUT_PMIC8XXX_PWRKEY
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called pmic8xxx-pwrkey.
|
||||
|
||||
config INPUT_QCOM_SPMI_HAPTICS
|
||||
tristate "Qualcomm SPMI HAPTICS"
|
||||
depends on ARCH_QCOM
|
||||
depends on SPMI
|
||||
select INPUT_FF_MEMLESS
|
||||
help
|
||||
This option enables support for the haptics found in pmi8998 and
|
||||
related PMICs. Based on the ff-memless interface.
|
||||
|
||||
To compile this driver as module, choose M here: the
|
||||
module will be called qcom_spmi_haptics.
|
||||
|
||||
config INPUT_SPARCSPKR
|
||||
tristate "SPARC Speaker support"
|
||||
depends on PCI && SPARC64
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
|
|||
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
|
||||
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
|
||||
obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o
|
||||
obj-$(CONFIG_INPUT_QCOM_SPMI_HAPTICS) += qcom-spmi-haptics.o
|
||||
obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += rave-sp-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
|
||||
obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o
|
||||
|
|
|
|||
981
drivers/input/misc/qcom-spmi-haptics.c
Normal file
981
drivers/input/misc/qcom-spmi-haptics.c
Normal file
|
|
@ -0,0 +1,981 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, Caleb Connolly <caleb@connolly.tech>
|
||||
* Qualcomm QPMI haptics driver for pmi8998 and related PMICs.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/input/qcom,spmi-haptics.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
#define HAP_STATUS_1_REG 0x0A
|
||||
#define HAP_BUSY_BIT BIT(1)
|
||||
#define SC_FLAG_BIT BIT(3)
|
||||
#define AUTO_RES_ERROR_BIT BIT(4)
|
||||
|
||||
#define HAP_LRA_AUTO_RES_LO_REG 0x0B
|
||||
#define HAP_LRA_AUTO_RES_HI_REG 0x0C
|
||||
|
||||
#define HAP_EN_CTL_REG 0x46
|
||||
#define HAP_EN_BIT BIT(7)
|
||||
|
||||
#define HAP_EN_CTL2_REG 0x48
|
||||
#define BRAKE_EN_BIT BIT(0)
|
||||
|
||||
#define HAP_AUTO_RES_CTRL_REG 0x4B
|
||||
#define AUTO_RES_EN_BIT BIT(7)
|
||||
#define AUTO_RES_ERR_RECOVERY_BIT BIT(3)
|
||||
#define AUTO_RES_EN_FLAG_BIT BIT(0)
|
||||
|
||||
#define HAP_CFG1_REG 0x4C
|
||||
#define HAP_ACT_TYPE_MASK BIT(0)
|
||||
|
||||
#define HAP_CFG2_REG 0x4D
|
||||
#define HAP_LRA_RES_TYPE_MASK BIT(0)
|
||||
|
||||
#define HAP_SEL_REG 0x4E
|
||||
#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
|
||||
#define HAP_WF_SOURCE_SHIFT 4
|
||||
|
||||
#define HAP_LRA_AUTO_RES_REG 0x4F
|
||||
#define LRA_AUTO_RES_MODE_MASK GENMASK(6, 4)
|
||||
#define LRA_AUTO_RES_MODE_SHIFT 4
|
||||
#define LRA_HIGH_Z_MASK GENMASK(3, 2)
|
||||
#define LRA_HIGH_Z_SHIFT 2
|
||||
#define LRA_RES_CAL_MASK GENMASK(1, 0)
|
||||
#define HAP_RES_CAL_PERIOD_MIN 4
|
||||
#define HAP_RES_CAL_PERIOD_MAX 32
|
||||
|
||||
#define HAP_VMAX_CFG_REG 0x51
|
||||
#define HAP_VMAX_OVD_BIT BIT(6)
|
||||
#define HAP_VMAX_MASK GENMASK(5, 1)
|
||||
#define HAP_VMAX_SHIFT 1
|
||||
|
||||
#define HAP_ILIM_CFG_REG 0x52
|
||||
#define HAP_ILIM_SEL_MASK BIT(0)
|
||||
#define HAP_ILIM_400_MA 0
|
||||
#define HAP_ILIM_800_MA 1
|
||||
|
||||
#define HAP_SC_DEB_REG 0x53
|
||||
#define HAP_SC_DEB_MASK GENMASK(2, 0)
|
||||
#define HAP_SC_DEB_CYCLES_MIN 0
|
||||
#define HAP_DEF_SC_DEB_CYCLES 8
|
||||
#define HAP_SC_DEB_CYCLES_MAX 32
|
||||
|
||||
#define HAP_RATE_CFG1_REG 0x54
|
||||
#define HAP_RATE_CFG1_MASK GENMASK(7, 0)
|
||||
#define HAP_RATE_CFG2_SHIFT 8 // As CFG2 is the most significant byte
|
||||
|
||||
#define HAP_RATE_CFG2_REG 0x55
|
||||
#define HAP_RATE_CFG2_MASK GENMASK(3, 0)
|
||||
|
||||
#define HAP_SC_CLR_REG 0x59
|
||||
#define SC_CLR_BIT BIT(0)
|
||||
|
||||
#define HAP_BRAKE_REG 0x5C
|
||||
#define HAP_BRAKE_PAT_MASK 0x3
|
||||
|
||||
#define HAP_WF_REPEAT_REG 0x5E
|
||||
#define WF_REPEAT_MASK GENMASK(6, 4)
|
||||
#define WF_REPEAT_SHIFT 4
|
||||
#define WF_REPEAT_MIN 1
|
||||
#define WF_REPEAT_MAX 128
|
||||
#define WF_S_REPEAT_MASK GENMASK(1, 0)
|
||||
#define WF_S_REPEAT_MIN 1
|
||||
#define WF_S_REPEAT_MAX 8
|
||||
|
||||
#define HAP_WF_S1_REG 0x60
|
||||
#define HAP_WF_SIGN_BIT BIT(7)
|
||||
#define HAP_WF_OVD_BIT BIT(6)
|
||||
#define HAP_WF_SAMP_MAX GENMASK(5, 1)
|
||||
#define HAP_WF_SAMPLE_LEN 8
|
||||
|
||||
#define HAP_PLAY_REG 0x70
|
||||
#define HAP_PLAY_BIT BIT(7)
|
||||
#define HAP_PAUSE_BIT BIT(0)
|
||||
|
||||
#define HAP_SEC_ACCESS_REG 0xD0
|
||||
#define HAP_SEC_ACCESS_UNLOCK 0xA5
|
||||
|
||||
#define HAP_TEST2_REG 0xE3
|
||||
|
||||
|
||||
#define HAP_VMAX_MIN_MV 116
|
||||
#define HAP_VMAX_MAX_MV 3596
|
||||
#define HAP_VMAX_MAX_MV_STRONG 3596
|
||||
|
||||
#define HAP_WAVE_PLAY_RATE_MIN_US 0
|
||||
#define HAP_WAVE_PLAY_RATE_MAX_US 20475
|
||||
#define HAP_WAVE_PLAY_TIME_MAX_MS 15000
|
||||
|
||||
#define AUTO_RES_ERR_POLL_TIME_NS (20 * NSEC_PER_MSEC)
|
||||
#define HAPTICS_BACK_EMF_DELAY_US 20000
|
||||
|
||||
#define HAP_BRAKE_PAT_LEN 4
|
||||
#define HAP_WAVE_SAMP_LEN 8
|
||||
#define NUM_WF_SET 4
|
||||
#define HAP_WAVE_SAMP_SET_LEN (HAP_WAVE_SAMP_LEN * NUM_WF_SET)
|
||||
#define HAP_RATE_CFG_STEP_US 5
|
||||
|
||||
#define SC_MAX_COUNT 5
|
||||
#define SC_COUNT_RST_DELAY_US 1000000
|
||||
|
||||
enum hap_play_control {
|
||||
HAP_STOP,
|
||||
HAP_PAUSE,
|
||||
HAP_PLAY,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spmi_haptics - struct for spmi haptics data.
|
||||
*
|
||||
* @dev: Our device parent.
|
||||
* @regmap: Register map for the hardware block.
|
||||
* @input_dev: The input device used to receive events.
|
||||
* @work: Work struct to play effects.
|
||||
* @base: Base address of the regmap.
|
||||
* @active: Atomic value used to track if haptics are currently playing.
|
||||
* @play_irq: Fired to load the next wave pattern.
|
||||
* @sc_irq: Short circuit irq.
|
||||
* @last_sc_time: Time since the short circuit IRQ last fired.
|
||||
* @sc_count: Number of times the short circuit IRQ has fired in this interval.
|
||||
* @actuator_type: The type of actuator in use.
|
||||
* @wave_shape: The shape of the waves to use (sine or square).
|
||||
* @play_mode: The play mode to use (direct, buffer, pwm, audio).
|
||||
* @magnitude: The strength we should be playing at.
|
||||
* @vmax: Max voltage to use when playing.
|
||||
* @current_limit: The current limit for this hardware (400mA or 800mA).
|
||||
* @play_wave_rate: The wave rate to use for this hardware.
|
||||
* @wave_samp: The array of wave samples to write for buffer mode.
|
||||
* @brake_pat: The pattern to apply when braking.
|
||||
* @play_lock: Lock to be held when updating the hardware state.
|
||||
*/
|
||||
struct spmi_haptics {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct input_dev *haptics_input_dev;
|
||||
struct work_struct work;
|
||||
u32 base;
|
||||
|
||||
atomic_t active;
|
||||
|
||||
int play_irq;
|
||||
int sc_irq;
|
||||
ktime_t last_sc_time;
|
||||
u8 sc_count;
|
||||
|
||||
u8 actuator_type;
|
||||
u8 wave_shape;
|
||||
u8 play_mode;
|
||||
int magnitude;
|
||||
u32 vmax;
|
||||
u32 current_limit;
|
||||
u32 play_wave_rate;
|
||||
|
||||
u32 wave_samp[HAP_WAVE_SAMP_SET_LEN];
|
||||
u8 brake_pat[HAP_BRAKE_PAT_LEN];
|
||||
|
||||
struct mutex play_lock;
|
||||
};
|
||||
|
||||
static inline bool is_secure_addr(u16 addr)
|
||||
{
|
||||
return (addr & 0xFF) > 0xD0;
|
||||
}
|
||||
|
||||
static int spmi_haptics_read(struct spmi_haptics *haptics,
|
||||
u16 addr, u8 *val, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(haptics->regmap, addr, val, len);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error reading address: 0x%x, ret %d\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spmi_haptics_write(struct spmi_haptics *haptics,
|
||||
u16 addr, u8 *val, int len)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (is_secure_addr(addr)) {
|
||||
for (i = 0; i < len; i++) {
|
||||
dev_dbg(haptics->dev, "%s: unlocking for addr: 0x%x, val: 0x%x", __func__,
|
||||
addr, val[i]);
|
||||
ret = regmap_write(haptics->regmap,
|
||||
haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error writing unlock code, ret %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(haptics->regmap, addr + i, val[i]);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error writing address 0x%x, ret %d\n",
|
||||
addr + i, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (len > 1)
|
||||
ret = regmap_bulk_write(haptics->regmap, addr, val, len);
|
||||
else
|
||||
ret = regmap_write(haptics->regmap, addr, *val);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "%s: Error writing address: 0x%x, ret %d\n",
|
||||
__func__, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_masked(struct spmi_haptics *haptics,
|
||||
u16 addr, u8 mask, u8 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (is_secure_addr(addr)) {
|
||||
ret = regmap_write(haptics->regmap,
|
||||
haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error writing unlock code - ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(haptics->regmap, addr, mask, val);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error writing address: 0x%x - ret %d\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool is_haptics_idle(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (haptics->play_mode == HAP_PLAY_DIRECT ||
|
||||
haptics->play_mode == HAP_PLAY_PWM)
|
||||
return true;
|
||||
|
||||
ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
|
||||
if (ret < 0 || (val & HAP_BUSY_BIT))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int spmi_haptics_module_enable(struct spmi_haptics *haptics, bool enable)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
dev_dbg(haptics->dev, "Setting module enable: %d", enable);
|
||||
|
||||
val = enable ? HAP_EN_BIT : 0;
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_EN_CTL_REG, &val, 1);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_vmax(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 val = 0;
|
||||
u32 vmax_mv = haptics->vmax;
|
||||
|
||||
vmax_mv = clamp_t(u32, vmax_mv, HAP_VMAX_MIN_MV, HAP_VMAX_MAX_MV);
|
||||
|
||||
dev_dbg(haptics->dev, "Setting vmax to: %d", vmax_mv);
|
||||
|
||||
val = DIV_ROUND_CLOSEST(vmax_mv, HAP_VMAX_MIN_MV);
|
||||
val = FIELD_PREP(HAP_VMAX_MASK, val);
|
||||
|
||||
// TODO: pm660 can enable overdrive here
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_VMAX_CFG_REG,
|
||||
HAP_VMAX_MASK | HAP_WF_OVD_BIT, val);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_current_limit(struct spmi_haptics *haptics)
|
||||
{
|
||||
haptics->current_limit = clamp_t(u32, haptics->current_limit,
|
||||
HAP_ILIM_400_MA, HAP_ILIM_800_MA);
|
||||
|
||||
dev_dbg(haptics->dev, "Setting current_limit to: 0x%x", haptics->current_limit);
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_ILIM_CFG_REG,
|
||||
HAP_ILIM_SEL_MASK, haptics->current_limit);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_play_mode(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 val = 0;
|
||||
|
||||
if (!is_haptics_idle(haptics))
|
||||
return -EBUSY;
|
||||
|
||||
dev_dbg(haptics->dev, "Setting play_mode to: 0x%x", haptics->play_mode);
|
||||
|
||||
val = FIELD_PREP(HAP_WF_SOURCE_MASK, haptics->play_mode);
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_SEL_REG,
|
||||
HAP_WF_SOURCE_MASK, val);
|
||||
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_play_rate(struct spmi_haptics *haptics, u16 play_rate)
|
||||
{
|
||||
u8 val[2];
|
||||
|
||||
dev_dbg(haptics->dev, "Setting play_rate to: %d", play_rate);
|
||||
|
||||
val[0] = FIELD_PREP(HAP_RATE_CFG1_MASK, play_rate);
|
||||
val[1] = FIELD_PREP(HAP_RATE_CFG2_MASK, play_rate >> HAP_RATE_CFG2_SHIFT);
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_RATE_CFG1_REG, val, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* spmi_haptics_set_auto_res() - Auto resonance
|
||||
* allows the haptics to automatically adjust the
|
||||
* speed of the oscillation in order to maintain
|
||||
* the resonant frequency.
|
||||
*/
|
||||
static int spmi_haptics_set_auto_res(struct spmi_haptics *haptics, bool enable)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
// LRAs are the only type to support auto res
|
||||
if (haptics->actuator_type != HAP_TYPE_LRA)
|
||||
return 0;
|
||||
|
||||
val = enable ? AUTO_RES_EN_BIT : 0;
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_TEST2_REG,
|
||||
AUTO_RES_EN_BIT, val);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_brake(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret, i;
|
||||
u8 val;
|
||||
|
||||
dev_dbg(haptics->dev, "Configuring brake pattern");
|
||||
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_EN_CTL2_REG,
|
||||
BRAKE_EN_BIT, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = HAP_BRAKE_PAT_LEN - 1, val = 0; i >= 0; i--) {
|
||||
u8 p = haptics->brake_pat[i] & HAP_BRAKE_PAT_MASK;
|
||||
|
||||
val |= p << (i * 2);
|
||||
}
|
||||
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_BRAKE_REG, &val, 1);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_buffer_config(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 buf[HAP_WAVE_SAMP_LEN];
|
||||
int i;
|
||||
|
||||
dev_dbg(haptics->dev, "Writing buffer config");
|
||||
|
||||
for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
|
||||
buf[i] = haptics->wave_samp[i];
|
||||
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_WF_S1_REG, buf,
|
||||
HAP_WAVE_SAMP_LEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* spmi_haptics_write_wave_repeat() - write wave repeat values.
|
||||
*/
|
||||
static int spmi_haptics_write_wave_repeat(struct spmi_haptics *haptics)
|
||||
{
|
||||
u8 val, mask;
|
||||
|
||||
/* The number of times to repeat each wave */
|
||||
mask = WF_REPEAT_MASK | WF_S_REPEAT_MASK;
|
||||
val = FIELD_PREP(WF_REPEAT_MASK, 0) |
|
||||
FIELD_PREP(WF_S_REPEAT_MASK, 0);
|
||||
|
||||
return spmi_haptics_write_masked(haptics, haptics->base + HAP_WF_REPEAT_REG,
|
||||
mask, val);
|
||||
}
|
||||
|
||||
static int spmi_haptics_write_play_control(struct spmi_haptics *haptics,
|
||||
enum hap_play_control ctrl)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
switch (ctrl) {
|
||||
case HAP_STOP:
|
||||
val = 0;
|
||||
break;
|
||||
case HAP_PAUSE:
|
||||
val = HAP_PAUSE_BIT;
|
||||
break;
|
||||
case HAP_PLAY:
|
||||
val = HAP_PLAY_BIT;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_dbg(haptics->dev, "haptics play ctrl: %d\n", ctrl);
|
||||
return spmi_haptics_write(haptics, haptics->base + HAP_PLAY_REG, &val, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This IRQ is fired to tell us to load the next wave sample set.
|
||||
* As we only currently support a single sample set, it's unused.
|
||||
*/
|
||||
static irqreturn_t spmi_haptics_play_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct spmi_haptics *haptics = data;
|
||||
|
||||
dev_dbg(haptics->dev, "play_irq triggered");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fires every ~50ms whilst the haptics are active.
|
||||
* If the SC_FLAG_BIT is set then that means there isn't a short circuit
|
||||
* and we just need to clear the IRQ to indicate that the device should
|
||||
* keep vibrating.
|
||||
*
|
||||
* Otherwise, it means a short circuit situation has occurred.
|
||||
*/
|
||||
static irqreturn_t spmi_haptics_sc_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct spmi_haptics *haptics = data;
|
||||
int ret;
|
||||
u8 val;
|
||||
s64 sc_delta_time_us;
|
||||
ktime_t temp;
|
||||
|
||||
ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
|
||||
if (ret < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (!(val & SC_FLAG_BIT)) {
|
||||
haptics->sc_count = 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
temp = ktime_get();
|
||||
sc_delta_time_us = ktime_us_delta(temp, haptics->last_sc_time);
|
||||
haptics->last_sc_time = temp;
|
||||
|
||||
if (sc_delta_time_us > SC_COUNT_RST_DELAY_US)
|
||||
haptics->sc_count = 0;
|
||||
else
|
||||
haptics->sc_count++;
|
||||
|
||||
// Clear the interrupt flag
|
||||
val = SC_CLR_BIT;
|
||||
ret = spmi_haptics_write(haptics, haptics->base + HAP_SC_CLR_REG, &val, 1);
|
||||
if (ret < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (haptics->sc_count > SC_MAX_COUNT) {
|
||||
dev_crit(haptics->dev, "Short circuit persists, disabling haptics\n");
|
||||
ret = spmi_haptics_module_enable(haptics, false);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error disabling module, rc=%d\n", ret);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* spmi_haptics_init() - Initialise haptics hardware for use
|
||||
* @haptics: haptics device
|
||||
* Returns: 0 on success, < 0 on error
|
||||
*/
|
||||
static int spmi_haptics_init(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
u8 val, mask;
|
||||
u16 play_rate;
|
||||
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG1_REG,
|
||||
HAP_ACT_TYPE_MASK, haptics->actuator_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Configure auto resonance
|
||||
* see spmi_haptics_lra_auto_res_config downstream
|
||||
* This is greatly simplified.
|
||||
*/
|
||||
val = FIELD_PREP(LRA_RES_CAL_MASK, ilog2(32 / HAP_RES_CAL_PERIOD_MIN)) |
|
||||
FIELD_PREP(LRA_AUTO_RES_MODE_MASK, HAP_AUTO_RES_ZXD_EOP) |
|
||||
FIELD_PREP(LRA_HIGH_Z_MASK, 1);
|
||||
|
||||
mask = LRA_AUTO_RES_MODE_MASK | LRA_HIGH_Z_MASK | LRA_RES_CAL_MASK;
|
||||
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_LRA_AUTO_RES_REG,
|
||||
mask, val);
|
||||
|
||||
/* Configure the PLAY MODE register */
|
||||
ret = spmi_haptics_write_play_mode(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = spmi_haptics_write_vmax(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure the ILIM register */
|
||||
ret = spmi_haptics_write_current_limit(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
// Configure the debounce for short-circuit detection.
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_SC_DEB_REG,
|
||||
HAP_SC_DEB_MASK, HAP_SC_DEB_CYCLES_MAX);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
// write the wave shape
|
||||
ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG2_REG,
|
||||
HAP_LRA_RES_TYPE_MASK, haptics->wave_shape);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
play_rate = haptics->play_wave_rate / HAP_RATE_CFG_STEP_US;
|
||||
|
||||
/*
|
||||
* Configure RATE_CFG1 and RATE_CFG2 registers.
|
||||
* Note: For ERM these registers act as play rate and
|
||||
* for LRA these represent resonance period
|
||||
*/
|
||||
ret = spmi_haptics_write_play_rate(haptics, play_rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = spmi_haptics_write_brake(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (haptics->play_mode == HAP_PLAY_BUFFER) {
|
||||
ret = spmi_haptics_write_wave_repeat(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = spmi_haptics_write_buffer_config(haptics);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (haptics->play_irq >= 0) {
|
||||
dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
|
||||
haptics->play_irq);
|
||||
ret = devm_request_threaded_irq(haptics->dev, haptics->play_irq,
|
||||
NULL, spmi_haptics_play_irq_handler, IRQF_ONESHOT,
|
||||
"haptics_play_irq", haptics);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Unable to request play IRQ ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* use play_irq only for buffer mode */
|
||||
if (haptics->play_mode != HAP_PLAY_BUFFER)
|
||||
disable_irq(haptics->play_irq);
|
||||
}
|
||||
|
||||
if (haptics->sc_irq >= 0) {
|
||||
dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
|
||||
haptics->play_irq);
|
||||
ret = devm_request_threaded_irq(haptics->dev, haptics->sc_irq,
|
||||
NULL, spmi_haptics_sc_irq_handler, IRQF_ONESHOT,
|
||||
"haptics_sc_irq", haptics);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Unable to request sc IRQ ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_enable - handler to start/stop vibration
|
||||
* @haptics: pointer to haptics struct
|
||||
* @enable: state to set
|
||||
* Returns: 0 on success, < 0 on failure
|
||||
*/
|
||||
static int spmi_haptics_enable(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&haptics->play_lock);
|
||||
if (haptics->sc_count > SC_MAX_COUNT) {
|
||||
dev_err(haptics->dev, "Can't play while in short circuit");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
ret = spmi_haptics_set_auto_res(haptics, false);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error disabling auto_res, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_module_enable(haptics, true);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error enabling module, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_write_play_control(haptics, HAP_PLAY);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error enabling play, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_set_auto_res(haptics, true);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error enabling auto_res, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&haptics->play_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_enable - handler to start/stop vibration
|
||||
* @haptics: pointer to haptics struct
|
||||
* @enable: state to set
|
||||
* Returns: 0 on success, < 0 on failure
|
||||
*/
|
||||
static int spmi_haptics_disable(struct spmi_haptics *haptics)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&haptics->play_lock);
|
||||
|
||||
ret = spmi_haptics_write_play_control(haptics, HAP_STOP);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error disabling play, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spmi_haptics_module_enable(haptics, false);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Error disabling module, ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&haptics->play_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Threaded function to update the haptics state.
|
||||
*/
|
||||
static void spmi_haptics_work(struct work_struct *work)
|
||||
{
|
||||
struct spmi_haptics *haptics = container_of(work, struct spmi_haptics, work);
|
||||
|
||||
int ret;
|
||||
bool enable;
|
||||
|
||||
enable = atomic_read(&haptics->active);
|
||||
dev_dbg(haptics->dev, "%s: state: %d\n", __func__, enable);
|
||||
|
||||
if (enable)
|
||||
ret = spmi_haptics_enable(haptics);
|
||||
else
|
||||
ret = spmi_haptics_disable(haptics);
|
||||
if (ret < 0)
|
||||
dev_err(haptics->dev, "Error setting haptics, ret=%d", ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_close - callback for input device close
|
||||
* @dev: input device pointer
|
||||
*
|
||||
* Turns off the vibrator.
|
||||
*/
|
||||
static void spmi_haptics_close(struct input_dev *dev)
|
||||
{
|
||||
struct spmi_haptics *haptics = input_get_drvdata(dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
if (atomic_read(&haptics->active)) {
|
||||
atomic_set(&haptics->active, 0);
|
||||
schedule_work(&haptics->work);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* spmi_haptics_play_effect - play haptics effects
|
||||
* @dev: input device pointer
|
||||
* @data: data of effect
|
||||
* @effect: effect to play
|
||||
*/
|
||||
static int spmi_haptics_play_effect(struct input_dev *dev, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct spmi_haptics *haptics = input_get_drvdata(dev);
|
||||
|
||||
dev_dbg(haptics->dev, "%s: Rumbling with strong: %d and weak: %d", __func__,
|
||||
effect->u.rumble.strong_magnitude, effect->u.rumble.weak_magnitude);
|
||||
|
||||
haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
|
||||
if (!haptics->magnitude)
|
||||
haptics->magnitude = effect->u.rumble.weak_magnitude >> 10;
|
||||
|
||||
if (!haptics->magnitude) {
|
||||
atomic_set(&haptics->active, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
atomic_set(&haptics->active, 1);
|
||||
|
||||
haptics->vmax = ((HAP_VMAX_MAX_MV - HAP_VMAX_MIN_MV) * haptics->magnitude) / 100 +
|
||||
HAP_VMAX_MIN_MV;
|
||||
|
||||
dev_dbg(haptics->dev, "%s: magnitude: %d, vmax: %d", __func__,
|
||||
haptics->magnitude, haptics->vmax);
|
||||
|
||||
spmi_haptics_write_vmax(haptics);
|
||||
|
||||
end:
|
||||
schedule_work(&haptics->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spmi_haptics_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spmi_haptics *haptics;
|
||||
struct device_node *node;
|
||||
struct input_dev *input_dev;
|
||||
int ret;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
|
||||
if (!haptics)
|
||||
return -ENOMEM;
|
||||
|
||||
haptics->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!haptics->regmap)
|
||||
return -ENODEV;
|
||||
|
||||
node = pdev->dev.of_node;
|
||||
|
||||
haptics->dev = &pdev->dev;
|
||||
|
||||
ret = of_property_read_u32(node, "reg", &haptics->base);
|
||||
if (ret < 0) {
|
||||
dev_err(haptics->dev, "Couldn't find reg in node = %s ret = %d\n",
|
||||
node->full_name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
haptics->play_irq = platform_get_irq_byname(pdev, "play");
|
||||
if (haptics->play_irq < 0) {
|
||||
dev_err(&pdev->dev, "Unable to get play irq\n");
|
||||
ret = haptics->play_irq;
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
haptics->sc_irq = platform_get_irq_byname(pdev, "short");
|
||||
if (haptics->sc_irq < 0) {
|
||||
dev_err(&pdev->dev, "Unable to get sc irq\n");
|
||||
ret = haptics->sc_irq;
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
// We only support LRAs for now
|
||||
haptics->actuator_type = HAP_TYPE_LRA;
|
||||
ret = of_property_read_u32(node, "qcom,actuator-type", &val);
|
||||
if (!ret) {
|
||||
if (val != HAP_TYPE_LRA) {
|
||||
dev_err(&pdev->dev, "qcom,actuator-type (%d) isn't supported\n", val);
|
||||
ret = -EINVAL;
|
||||
goto register_fail;
|
||||
}
|
||||
haptics->actuator_type = val;
|
||||
}
|
||||
|
||||
// Only buffer mode is currently supported
|
||||
haptics->play_mode = HAP_PLAY_BUFFER;
|
||||
ret = of_property_read_u32(node, "qcom,play-mode", &val);
|
||||
if (!ret) {
|
||||
if (val != HAP_PLAY_BUFFER) {
|
||||
dev_err(&pdev->dev, "qcom,play-mode (%d) isn't supported\n", val);
|
||||
ret = -EINVAL;
|
||||
goto register_fail;
|
||||
}
|
||||
haptics->play_mode = val;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "qcom,wave-play-rate-us", &val);
|
||||
if (!ret) {
|
||||
haptics->play_wave_rate = val;
|
||||
} else if (ret != -EINVAL) {
|
||||
dev_err(haptics->dev, "Unable to read play rate ret=%d\n", ret);
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
haptics->play_wave_rate =
|
||||
clamp_t(u32, haptics->play_wave_rate,
|
||||
HAP_WAVE_PLAY_RATE_MIN_US, HAP_WAVE_PLAY_RATE_MAX_US);
|
||||
|
||||
haptics->wave_shape = HAP_WAVE_SINE;
|
||||
ret = of_property_read_u32(node, "qcom,wave-shape", &val);
|
||||
if (!ret) {
|
||||
if (val != HAP_WAVE_SINE && val != HAP_WAVE_SQUARE) {
|
||||
dev_err(&pdev->dev, "qcom,wave-shape is invalid: %d\n", val);
|
||||
ret = -EINVAL;
|
||||
goto register_fail;
|
||||
}
|
||||
haptics->wave_shape = val;
|
||||
}
|
||||
|
||||
haptics->brake_pat[0] = 0x3;
|
||||
haptics->brake_pat[1] = 0x3;
|
||||
haptics->brake_pat[2] = 0x2;
|
||||
haptics->brake_pat[3] = 0x1;
|
||||
|
||||
ret = of_property_read_u8_array(node, "qcom,brake-pattern", haptics->brake_pat, 4);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
dev_err(&pdev->dev, "qcom,brake-pattern is invalid, ret = %d\n", ret);
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
haptics->current_limit = HAP_ILIM_400_MA;
|
||||
|
||||
for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
|
||||
haptics->wave_samp[i] = HAP_WF_SAMP_MAX;
|
||||
|
||||
ret = spmi_haptics_init(haptics);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Error initialising haptics, ret=%d\n",
|
||||
ret);
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, haptics);
|
||||
|
||||
input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_WORK(&haptics->work, spmi_haptics_work);
|
||||
haptics->haptics_input_dev = input_dev;
|
||||
|
||||
input_dev->name = "spmi_haptics";
|
||||
input_dev->id.version = 1;
|
||||
input_dev->close = spmi_haptics_close;
|
||||
input_set_drvdata(input_dev, haptics);
|
||||
// Figure out how to make this FF_PERIODIC
|
||||
input_set_capability(haptics->haptics_input_dev, EV_FF, FF_RUMBLE);
|
||||
|
||||
ret = input_ff_create_memless(input_dev, NULL,
|
||||
spmi_haptics_play_effect);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"couldn't register vibrator as FF device\n");
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
ret = input_register_device(input_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "couldn't register input device\n");
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
register_fail:
|
||||
cancel_work_sync(&haptics->work);
|
||||
mutex_destroy(&haptics->play_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused spmi_haptics_suspend(struct device *dev)
|
||||
{
|
||||
struct spmi_haptics *haptics = dev_get_drvdata(dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
spmi_haptics_disable(haptics);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(spmi_haptics_pm_ops, spmi_haptics_suspend, NULL);
|
||||
|
||||
static int spmi_haptics_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
mutex_destroy(&haptics->play_lock);
|
||||
input_unregister_device(haptics->haptics_input_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spmi_haptics_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
cancel_work_sync(&haptics->work);
|
||||
|
||||
spmi_haptics_disable(haptics);
|
||||
}
|
||||
|
||||
static const struct of_device_id spmi_haptics_match_table[] = {
|
||||
{ .compatible = "qcom,spmi-haptics" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, spmi_haptics_match_table);
|
||||
|
||||
static struct platform_driver spmi_haptics_driver = {
|
||||
.probe = spmi_haptics_probe,
|
||||
.remove = spmi_haptics_remove,
|
||||
.shutdown = spmi_haptics_shutdown,
|
||||
.driver = {
|
||||
.name = "spmi-haptics",
|
||||
.pm = &spmi_haptics_pm_ops,
|
||||
.of_match_table = spmi_haptics_match_table,
|
||||
},
|
||||
};
|
||||
module_platform_driver(spmi_haptics_driver);
|
||||
|
||||
MODULE_DESCRIPTION("spmi haptics driver using ff-memless framework");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue