Compare commits

...
Sign in to create a new pull request.

187 commits

Author SHA1 Message Date
Jami Kettunen
fbc5c9f735 arm64: dts: msm8998-oneplus-common: Cap GPU @ 414 MHz max
If it reaches any higher the device has a chance of freezing under high
load; use this as a temp hack until the GPU CPR regulator driver is up.
2021-12-22 01:14:36 +02:00
Jami Kettunen
4aa04cdc85 arm64: dts: msm8998-oneplus-common: Load a540_zap.mbn from qcom/msm8998/oneplus 2021-12-22 01:14:36 +02:00
Jami Kettunen
1667a23e49 module: demote invalid ELF header magic error message to pr_debug
This happens anytime busybox modprobe loads a compressed module and
looks especially ugly on postmarketOS for example (or basically any
initramfs); this error is rather pointless since the module is loaded
anyway afterwards.

Upstream (busybox) has no plans to do anything about this error getting
spammed:
https://www.mail-archive.com/busybox@busybox.net/msg27078.html
2021-12-22 01:14:36 +02:00
Jami Kettunen
eee0cdb08a Revert "media: venus: core: Add sdm660 DT compatible and resource struct"
57c3b9f55b ("media: venus: core: Add sdm660 DT compatible and resource struct")
is already upstream since 5.16-rc1.

This reverts commit c64948c3da241971a8f0b75c41edf6c0572a9a0c.
2021-12-22 01:14:36 +02:00
Jami Kettunen
1875708601 Revert "arm64: dts: qcom: pmi8998: Add node for WLED"
17d32c1 ("arm64: dts: qcom: pmi8998: Add node for WLED") is already
upstream since 5.16-rc1.

This reverts commit a16764a6fc243d9a4946c36b58774cab051a1e19.
2021-12-22 01:14:36 +02:00
Jami Kettunen
a1d8d9010e arm64: qcom: msm8998-oneplus-common: Enable NFC 2021-12-22 01:14:36 +02:00
Jami Kettunen
ef649e6c0c TEMP: oneplus5: disable all speaker amp stuff
We don't want to blow this up while messing around with audio stuff
early on...
2021-12-22 01:14:36 +02:00
Jami Kettunen
193a832101 arm64: dts: msm8998-oneplus-common: Add TFA9890 speaker amp bindings 2021-12-22 01:14:36 +02:00
Jami Kettunen
ad13089b85 ASoC: codecs: tfa989x: Add support for tfa9890
This speaker amp model appears to be rather popular on phones and is
used for example by the OnePlus 5/5T.
2021-12-22 01:14:36 +02:00
Jami Kettunen
b970f60955 arm64: dts: qcom: msm8998-oneplus-common: Enable PMI8998 LPG leds
Now the RGB notification LEDs can each be controlled individually :)
2021-12-22 01:14:36 +02:00
Jami Kettunen
13d175a285 msm8998-oneplus-common: Configure Adreno 540 GPU 2021-12-22 01:14:36 +02:00
Jami Kettunen
ce49449d4d arm64: dts: msm8998-oneplus-*: Configure S6E3FA5 & S6E3FC1 panels
These Samsung DSI panels are used on the OnePlus 5/5T respectively.
Additionally disable simplefb until a proper handoff solution can be
found to avoid conflicts between it and the MSM DRM driver.
2021-12-22 01:14:36 +02:00
Jami Kettunen
9646d2632d msm8998-oneplus-common: Configure IPA for cellular data 2021-12-22 01:14:36 +02:00
Jami Kettunen
f3ea966e53 msm8998-oneplus-common: Configure PMI8998 fuel gauge for battery info 2021-12-22 01:14:36 +02:00
Jami Kettunen
ab984a91b3 msm8998-oneplus-common: Configure CPUfreq scaling hardware 2021-12-22 01:14:36 +02:00
Jami Kettunen
f26c3ec996 arm64: dts: msm8998-oneplus-cheeseburger: Configure RMI4 F1A buttons
This allows the capacitive buttons below the touchscreen to be used on
e.g. Android normally :)
2021-12-22 01:14:36 +02:00
Jami Kettunen
b982d84491 msm8998-oneplus-common: Add remoteproc configuration & enable WLAN 2021-12-22 01:14:36 +02:00
Jami Kettunen
d9ada59a34 msm8998-oneplus-common: Configure blsp1_i2c5_sleep (TS) as no-pull 2021-12-22 01:14:35 +02:00
Jami Kettunen
61daf2df97 drm/panel: Add panel driver for Samsung S6E3FC1
The S6E3FC1 is 6" 1080x2160 MIPI DSI command mode AMOLED LCD display
found on OnePlus 5T (2017) smartphones.

The panel needs to be enabled from a device tree using the
"samsung,s6e3fc1" compatible.

This driver was generated using the following & includes some minor
cleanup (such as s/to_s6e3fc1/to_s6e3fc1_panel/g):
$ python3 lmdpdg.py dumpling.dtb -r vddio
2021-12-22 01:14:35 +02:00
Jami Kettunen
2bc6971f75 drm/panel: s6e3fa5: Read panel orientation
The panel is mounted upside down on the OnePlus 5, so we need to handle
this in the driver.
2021-12-22 01:14:35 +02:00
Jami Kettunen
1964438c0f drm/panel: Add panel driver for Samsung S6E3FA5
The S6E3FA5 is 5.5" 1080x1920 MIPI DSI command mode AMOLED LCD display
found on OnePlus 5 (2017) smartphones.

The panel needs to be enabled from a device tree using the
"samsung,s6e3fa5" compatible.

This driver was generated using the following & includes some minor
cleanup (such as s/to_s6e3fa5/to_s6e3fa5_panel/g):
$ python3 lmdpdg.py cheeseburger.dtb -r vddio

Signed-off-by: Jami Kettunen <jami.kettunen@protonmail.com>
2021-12-22 01:14:35 +02:00
Jami Kettunen
2fd1464c75 [ANNOTATION] Apply some F(x)tec Pro1 patches 2021-12-22 01:14:35 +02:00
Danct12
6fd559371f arm64: dts: msm8998-fxtec-pro1: Add remoteproc configuration 2021-12-22 01:14:35 +02:00
Danct12
e7f9be7519 arm64: dts: msm8998-fxtec-pro1: Enable PMI8998 haptics 2021-12-22 01:14:35 +02:00
Danct12
b9883abfa2 arm64: dts: msm8998-fxtec-pro1: Configure PMI8998 fuel gauge
This will account for battery statistics reporting on the Fxtec Pro1 (QX1000)
2021-12-22 01:14:35 +02:00
Jami Kettunen
a7f6d4f5d2 [ANNOTATION] Apply miscellaneous hacks and patches 2021-12-22 01:14:35 +02:00
Jami Kettunen
348b250d6e Input: synaptics-rmi4 - add support for F1A
RMI4 F1A supports the simple capacitive buttons function, it's used for
example on embedded devices such as smartphones for capacitive Android
back and recents buttons.
2021-12-22 01:14:35 +02:00
Jami Kettunen
9b07deab7d arm64: dts: qcom: msm8998: add IPA information
Add support for the MSM8998 SoC, which includes IPA version 3.1.
2021-12-22 01:14:35 +02:00
Jami Kettunen
2c6faaec9c power: supply: qcom_fg: Report online property 2021-12-22 01:14:35 +02:00
Jami Kettunen
af9bdebc7f drm/msm: Mention DSI 10nm PHY support for MSM8998 2021-12-22 01:14:35 +02:00
Jami Kettunen
09273e88c0 dt-bindings: Document bindings for all MSM8998 devices 2021-12-22 01:14:35 +02:00
Jami Kettunen
b6f6faadc7 [HACK] ath10k: Fake MSA ready event after event server arrival
This finally allowed me to get past the 2 ath10k_info()'s in qmi.c!

However, this doesn't fix everything; it seems you *have* to run
diag-router from https://github.com/andersson/diag to calm the firmware
down and stop constantly crashing; need to look into a way to get Wi-Fi
working later without needing this debug crap to be running.
2021-12-22 01:14:35 +02:00
Jami Kettunen
9648db56d6 [HACK] scripts: Stop appending "+" to localversion
This always gets added and doesn't look nice in the version string, so
it's purely for aesthetic reasons :p
2021-12-22 01:14:35 +02:00
Jami Kettunen
b8d0acc7b5 [ANNOTATION] Apply WIP "Qualcomm SPMI Fuel Gauge" patches
https://gitlab.com/sdm845-mainline/linux/-/commits/driver/pmi8998_fg/
2021-12-22 01:14:35 +02:00
Yassine Oudjana
e4454dd8a5 arm64: dts: qcom: pmi8994: Add fuel gauge 2021-12-22 01:14:35 +02:00
Yassine Oudjana
8214d51e39 power: pmi8998_fg: Rename to qcom_fg and add support for PMI8994/6
This adds support for accessing SRAM. That includes requesting and releasing
access to SRAM by setting some registers and handling the mem-avail IRQ,
configuring access, and reading from/writing to it.

Pre-gen3 fuel gauges require reading from SRAM to get voltage, current
and temperature data. Getting capacity is identical to gen3.

Tested on Xiaomi Mi Note 2 with PMI8996.
2021-12-22 01:14:35 +02:00
Yassine Oudjana
dbfc06bf9d power: pmi8998_fg: Remove some trailing spaces and tabs
This should be squashed.
2021-12-22 01:14:34 +02:00
Joel Selvaraj
c8e60b5904 arm64: dts: qcom: sdm845-oneplus: enable pmi8998 fuel guage
Enable the new pmi8998 fuel gauge

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-12-22 01:14:34 +02:00
Joel Selvaraj
631bacc3f5 fg: clean and read charge full and max voltage from dts 2021-12-22 01:14:34 +02:00
Joel Selvaraj
5fbad76da7 power: supply: add battery charging status feature 2021-12-22 01:14:34 +02:00
Joel Selvaraj
955846810e arm64: dts: qcom: pmi8998: Add nodes for pmi8998 fuel guage 2021-12-22 01:14:34 +02:00
Joel Selvaraj
b6b96f3272 power: supply: introduce pmi8998 fuel guage driver 2021-12-22 01:14:34 +02:00
Jami Kettunen
6fcf1fe1e2 [ANNOTATION] Apply "input: Introduce support for SPMI haptics found on Qcom PMICs" series
https://patchwork.kernel.org/project/linux-arm-msm/cover/20210816221931.1998187-1-caleb@connolly.tech/
2021-12-22 01:14:34 +02:00
Jami Kettunen
b698aaf4bb arm64: dts: qcom: msm8998-oneplus-common: Enable PMI8998 haptics
The OnePlus 5 and 5T both have a haptics engine connected to PMI8998.

Signed-off-by: Jami Kettunen <jami.kettunen@somainline.org>
Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-12-22 01:14:34 +02:00
Joel Selvaraj
45231a2944 arm64: dts: qcom: sdm845-xiaomi-beryllium: add haptics
Enable the pmi8998 SPMI haptics driver and configure the play rate for the
hardware.

Signed-off-by: Joel Selvaraj <jo@jsfamily.in>
Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-12-22 01:14:34 +02:00
Caleb Connolly
071cc8ce1d arm64: dts: qcom: sdm845-oneplus-common: add haptics
Enable the pmi8998 SPMI haptics driver and configure the play rate for the
hardware.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-12-22 01:14:34 +02:00
Caleb Connolly
6bbd2c88ed arm64: dts: qcom: pmi8998: introduce spmi haptics
Add bindings for Qualcomm SPMI haptics on platforms using pmi8998.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-12-22 01:14:34 +02:00
Caleb Connolly
f67fb30a22 input: add Qualcomm SPMI haptics driver
Add support for the haptics found in pmi8998 and related PMICs.
Based on the ff-memless interface. Currently this driver provides
a partial implementation of hardware features.

This driver only supports LRAs (Linear Resonant Actuators) in the "buffer"
mode with a single wave pattern.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-12-22 01:14:34 +02:00
Caleb Connolly
ec5ec8e50d dt-bindings: input: add Qualcomm SPMI haptics driver
Add bindings for qcom PMIC SPMI haptics driver.

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-12-22 01:14:34 +02:00
Jami Kettunen
ee88b5c713 [ANNOTATION] Various patches from SoMainline trees & LKML 2021-12-22 01:14:34 +02:00
Junak
7dba3ca921 drm: msm: mdp5: improve command-mode panel support 2021-12-22 01:14:34 +02:00
Jami Kettunen
ae137a585d [ANNOTATION] Base @ angelo/5.14-msm8998-audio-working
I also rebased this tree on the linus/v5.14 tag.
2021-12-22 01:14:34 +02:00
AngeloGioacchino Del Regno
8a93a26726 nt35950: partial marijn review 2021-12-22 01:14:34 +02:00
AngeloGioacchino Del Regno
6e8bad878e dt-bindings: display: Add bindings for Novatek NT35950
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.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:34 +02:00
AngeloGioacchino Del Regno
4edd7c9166 nt35950: final 2021-12-22 01:14:34 +02:00
AngeloGioacchino Del Regno
98572151bf soc: qcom: spm: Implement support for SAWv2.3, MSM8976 L2 PM
Implement the support for SAW v2.3, used in at least MSM8976, MSM8956
and APQ variants and, while at it, also add the configuration for the
MSM8976's little (a53) and big (a72) clusters cache power management.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:34 +02:00
AngeloGioacchino Del Regno
afc73d22c1 interconnect: qcom: Add MSM8976 interconnect provider driver
Introduce a driver for the Qualcomm interconnect busses found in
the MSM8976/8956 SoCs.
The topology consists of several NoCs that are controlled by a
remote processor that collects the aggregated bandwidth for each
master-slave pairs.
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
7f9ecef1b0 adreno 5xx: TTBR1 extravaganza on MSM8998
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:33 +02:00
Marijn Suijten
4ef6b40484 backlight: qcom-wled: Consistently use enabled-strings in set_brightness
According to the documentation any combination of LEDs can be used,
which is specified in the DT using qcom,enabled-strings as u32 array.
The numbers specified in this array represent indices of the led strings
that are to be enabled and disabled.

The value is appropriately used to enable string modules, but completely
disregarded in the set_brightness path which only iterates over "string
indices" 0<=i<num_strings.
This means that in order to have a custom set of strings enabled in the
DT, qcom,num-strings needs to be at least equal to the highest string
index plus one, even if that doesn't reflect the actual number of
strings used on the system.
In turn, gaps in the strings list need to be filled with duplicate
indices in order to prevent enabling other strings not listed in the
array (those are specified by the default for wled3 and 4, but not
overwritten when the array is read from the DT).

Take for example a situation where only string 1 is desired to be turned
on. Specifying an array of <1> will only overwrite the first entry of
enabled_strings, while the other numbers stick to their default. Unless
qcom,num-strings is adjusted to 1 too, other (unspecified) string
modules get enabled too.
However, this causes set_brightness to only write a brightness value to
the string at index 0.

This patch aims to simplify the case for custom string combinations by
using enabled_strings in set_brightness, as well as updating num_strings
with the length of the array when it is set.
It is assumed here that setting an array of enabled strings
TODO BETTER WORDS rules out
the use of autodetection, or at least only apply autodetection on the
specified LED modules.
TODO: THIS LATTER PART IS CURRENTLY NOT ACTUALLY THE CASE... WHAT DO WE
WANT?

Furthermore, in order to ensure the autodetection keeps working, the
default {0, 1, 2, 3} enabled_strings value has been adopted from wled3.
This is identical to iterating the indices from 0<=i<num_strings where
num_strings defaults to 4.
Keep in mind that wled4 did not have a sensible default, which would
cause only string 0 to be enabled in wled4_setup with autodetection
disabled, even when num_strings is 4.

TODO TODO TODO
SECOND FINALLY: There is another error. The default of qcom,num_strings
in case it's unset is 4. The cfg.num_strings = cfg.num_strings + 1;
causes writes to an unexisting or overlapping register in set_brightness
and other functions relying on num_strings.

TODO TODO TODO CLEAN UP WORD CONVENTION. Are we talking about strings,
modules, string modules, LED modules??? What's the unit here?
[mainline todo]: num-strings is not optional atm.

Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
2021-12-22 01:14:33 +02:00
Marijn Suijten
c9e5f0cb33 backlight: qcom-wled: Use cpu_to_le16 macro to perform conversion
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
2021-12-22 01:14:33 +02:00
Marijn Suijten
4733306ff3 backlight: qcom-wled: Pass number of elements to read to read_u32_array
of_property_read_u32_array takes the number of elements to read as last
argument. This does not always need to be 4 (sizeof(u32)) but should
instead be the size of the array in DT as read just above with
of_property_count_elems_of_size.

To not make such an error go unnoticed again the driver now bails
accordingly when of_property_read_u32_array returns an error.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
c215a02270 various tests 2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
5679eca4df iommu/arm-smmu-qcom: Add MSM8998 and SDM660 mss compatibles for identity
Add MSM8998 and SDM660's mss-pil compatibles to switch the default
iommu domain type to IDENTITY, as similarly required by SDM845 and
others.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
d1c3c3848a iommu/arm-smmu-qcom: Skip the TTBR1 quirk for MSM8998 and SDM630
Similarly to MSM8996 DragonBoard 820c, MSM8998 and SDM630 are equipped
with Adreno 5xx series, which doesn't have separate pagetables support
at the moment of writing.
Skip the TTBR1 quirk for these two SoCs as to get Adreno in a usable
state.
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
d8ae300293 AUDIO WORKS 2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
2cfcce2abf ASoC: codecs: wcd9335: Fix headphone jack commit for new upstream kernel 2021-12-22 01:14:33 +02:00
Srinivas Kandagatla
50f7a5edfd ASoC: wcd9335: add mbhc support
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
9e2a2c2452 Revert "wcd9335 garbage"
This reverts commit d1f50ba3a4b33c98162c4b202d4c154d4ab22689.
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
d95b982acc stuff 2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
64ec6966f9 wcd9335 garbage 2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
8eb0c6e2d6 arm64: dts: qcom: msm8998: Add disabled slimbus support
Add generic slimbus configuration to MSM8998 and keep it disabled.
It is expected that this will be enabled in board-specific device
trees when supported, along with the right audio codec.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:33 +02:00
Jami Kettunen
8641f9a558 ASoC: qcom: lpass-msm8998: Add platform driver for lpass audio
Add platform driver for configuring msm8998 lpass core I2S and
DMA configuration to support playback & capture to external codecs
connected over primary & secondary MI2S interfaces.

(driver originally split from 4d7e1ead3b ("fastmatrix yaml fix"))
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
ecd8875f2b ASoC: qcom: Add MSM8998 sound card support
Add MSM8998 sound support: this driver supports basic functionality
and headphone jack.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
dfec3843e5 arm64: dts: qcom: msm8998-xperia: Enable lpass smmu
To support audio dsp functionality, enable the lpass smmu.
The firmware distributed with the MSM8998 Sony Xperia smartphones
requires us to skip resetting CB12 of this SMMU and to use CB11
as a context bank to emulate bypass streams.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
5e4390d37a iommu-qcom: re-enable resetting contexts 2021-12-22 01:14:33 +02:00
AngeloGioacchino Del Regno
e122a6a4e1 dt-bindings: lpass clocks fix 2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
a0f3bcb6e9 arm64: dts: qcom: msm8998: Add APR services configuration
Add the standard APR Q6 services configuration for MSM8998, used by
boards supporting the audio dsp.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
6bfe7bc418 arm64: dts: qcom: msm8998: Define fastrpc ADSP compute context banks
If the target board supports ADSP, it is essential to have fastrpc
compute context banks defined. This commit adds the always usable
unsecured context banks only.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
90170977af arm64: dts: qcom: msm8998: Add disabled support for lpass iommu for q6
Add support for the LPASS (Q6) SMMU and keep it disabled as this is
used only when the audio DSP is present and used, which is not
mandatory to have.
It is expected for board-specific device-trees to enable this node
if supported.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
e4ee78136c clk: qcom: gcc-msm8998: Add LPASS adsp and core GDSCs
As a final step to entirely enable the required clock tree for the
lpass iommu and audio dsp, add the lpass core/adsp GDSCs.

As a side note, it was found out that disabling the lpass core GDSC
at any time would cause a system lockup (and reboot): disabling
this GDSC will leave the lpass iommu completely unclocked, losing
its state entirely - including the secure contexts that have been
previously set-up from the bootloader/TrustZone.
Losing this IOMMU configuration will trigger a hypervisor fault,
which will reboot the system; the only workaround for this issue
is to declare the lpass core gdsc as always-on.

It should also not be forgotten that this is all about firmware and
there may be a version of it that doesn't enable this GDSC at all
before booting Linux, which is the reason why this specific declaration
wasn't simply omitted.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
208744810b dt-bindings: clock: gcc-msm8998: Add LPASS adsp/core GDSCs definitions
Add the GDSC definitions for the LPASS_ADSP_GDSC and LPASS_CORE_GDSC
as a final step to enable the required clock tree for the lpass iommu
and for the audio dsp itself.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
3102e7aaf8 clk: qcom: gcc-msm8998: Add q6 bimc and lpass core, adsp SMMU clocks
Add the Q6 BIMC, LPASS core/adsp SMMU clocks to support audio related
functionality on MSM8998 and APQ variants. Please note that the Q6 and
the lpass iommu also need GDSCs to be enabled in order to initialize,
which are going to be added in a later commit.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
0ae04eda03 dt-bindings: clock: gcc-msm8998: Add Q6 and LPASS clocks definitions
Add definitions for the Q6 BIMC, LPASS core and adsp smmu clocks,
required to enable audio functionality on MSM8998.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
c72de016c3 arm64: dts: qcom: msm8998: Add imem pil-reloc-info for firmware loading
Firmware loading (mainly the modem) may require IMEM PIL relocation
informations: specify this imem region in dt for qcom_pil_info to
use it.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
61271d6273 adreno-smmu.... 2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
35c64148db yoshino: Fix too high overheating backlight, enable all wled strings maple 2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
cd95ecae4a working everything and touch ok - but with iommu hack 2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
bf0b7a1ffa drm/panel: Add driver for Novatek NT35950 DSI DriverIC panels
Add a driver for panels using the Novatek NT35950 Display Driver IC,
including support for the Sharp LS055D1SX04, found in some Sony Xperia
Z5 Premium and XZ Premium smartphones.
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
e7aa905ace fastmatrix yaml fix 2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
324fd2c448 drm/msm/dsi_phy_10nm: Fix bad VCO rate calculation 2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
9818ab7e2b clk: qcom: mmcc-msm8998: Set CLK_GET_RATE_NOCACHE to pixel/byte clks
The pixel and byte clocks rate should not be cached, as a VCO shutdown
may clear the frequency setup and this may not be set again due to the
cached rate being present.
This will also be useful when shadow clocks will be implemented in
the DSI PLL for seamless timing/resolution switch.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
ee4a0e73be clk: qcom: gcc-msm8998: Set MISC flags, mark hmss/gpu-ahb critical
It is being evaluated whether this commit is really needed.
DONOTUPSTREAM.

(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
ba708e4966 drm/msm/dpu1: Add DMA2, DMA3 clock control to enum
The enum dpu_clk_ctrl_type misses DPU_CLK_CTRL_DMA{2,3} even though
this driver does actually handle both, if present: add the two in
preparation for adding support for SoCs having them.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
64361667ec input: keyboard: Add Fast GPIO-driven keyboard/keypad matrix driver
This driver is a reimplementation of matrix_keyboard, on which it
is heavily based: the former was made back in 2009 and then
lightly updated in 2012 to add some support for device-tree / OF.

It turns out that this is not enough, nor OF is fully supported,
as the global (or "clustered") interrupt is never probed, nor it
made usage of the GPIOD API which, nowadays, really simplifies
the job - but not only: it also provides means to set GPIO arrays
for controllers that are supporting this.
The latter is very important when dealing with slow GPIOs such as
I2C and/or SPI expanders (and, again, not only); by using the new
APIs everything fits the new systems, from simplifications of the
probe/remove functions to opening possibility of using expanders
to drive key matrices with or without protection diodes.

But then, why wasn't the old matrix_keyboard driver modified
instead of creating a new one?
The problem there is that the old driver is made to support the
old platform_device style and it's currently still being used by
some PXA boards that are not (yet?) ported to device-tree, so it
would be impossible to modernize it for good, which means that to
support GPIOD (which is - really - required for the aforementioned
reasons) and to fully support DT it would be necessary to wrap the
old GPIO API around the new GPIOD one, creating overhead and also
probably unnecessary memory usage, other than a very big driver
which, at least on embedded devices (having limited resources),
would be simply bad. Leaving the fact that I haven't got any old
board so it's impossible for me to analyze and optimize for them.

Since 98% of the users of the old driver are infact platforms that
have been ported to (or are born with) DT, the introduction of a
new driver that's purely made for them seemed to be the best
choice, also because the expectations are (I think) that all of
the old ARM-based boards will be ported to DT anyway, which will
actually deprecate the good old matrix_keyboard driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:32 +02:00
AngeloGioacchino Del Regno
42b6c72903 dt-bindings: input: Add binding for gpio-fastmatrix-keyboard
Add documentation for the gpio-fastmatrix-keyboard driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
7d7936636f dt-bindings: display: Document BOE BF060Y8M-AJ0 panel compatible
Document the boe,bf060y8m-aj0 panel.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
2a3eeaa730 drm/panel: Add BOE BF060Y8M-AJ0 5.99" AMOLED panel driver
This adds support for the BOE BF060Y8M-AJ0 5.99" AMOLED module
that can be found in some F(x)Tec Pro1 and Elephone U1 devices.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
36e759dcab media: venus: core: Add sdm660 DT compatible and resource struct
Add the SDM660 DT compatible and its resource structure, also
including support for the Venus pmdomains, in order to support
the Venus block in SDM630, SDM636, SDM660 and SDA variants.

This SoC features Venus 4.4 (HFI3XX), with one vcodec used for
both encoding and decoding, switched on through two GDSCs.
The core clock for this Venus chip is powered by the RPM VDD_CX
power domain.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
5ccc15fc56 dt-bindings: pinctrl: Add bindings for Awinic AW9523/AW9523B
Add bindings for the Awinic AW9523/AW9523B I2C GPIO Expander driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
d805ce6ece pinctrl: Add driver for Awinic AW9523/B I2C GPIO Expander
The Awinic AW9523(B) is a multi-function I2C gpio expander in a
TQFN-24L package, featuring PWM (max 37mA per pin, or total max
power 3.2Watts) for LED driving capability.

It has two ports with 8 pins per port (for a total of 16 pins),
configurable as either PWM with 1/256 stepping or GPIO input/output,
1.8V logic input; each GPIO can be configured as input or output
independently from each other.

This IC also has an internal interrupt controller, which is capable
of generating an interrupt for each GPIO, depending on the
configuration, and will raise an interrupt on the INTN pin to
advertise this to an external interrupt controller.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
Konrad Dybcio
203c84bacb interconnect: qcom: Add MSM8998 interconnect provider driver
Introduce a driver for the Qualcomm interconnect busses found in
the MSM/APQ8998 SoCs.
The topology consists of several NoCs that are controlled by a
remote processor that collects the aggregated bandwidth for each
master-slave pairs.

On a note, these chips are managing the "bus QoS" in a "hybrid"
fashion: some of the paths in the topology are managed through
and by, of course) the RPM uC, while some others are "AP Owned",
meaning that the AP shall do direct writes to the appropriate
QoS registers for the specific paths and ports, instead of sending
an indication to the RPM and leaving the job to that one.

Co-authored-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
770ff64363 dt-bindings: interconnect: Add bindings for Qualcomm MSM8998 NoC
Add the bindings for the Qualcomm MSM8998 NoC interconnects.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
fb54cf55d4 dt-bindings: i2c: qcom,i2c-qup: Document noise rejection properties
Document the new noise rejection properties "qcom,noise-reject-sda"
and "qcom,noise-reject-scl".

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
9d4e49ab2c i2c: qup: Introduce SCL/SDA noise rejection
Some I2C devices may be glitchy due to electrical noise coming
from the device itself or because of possible board design issues.
To overcome this issue, the QUP's I2C in Qualcomm SoCs supports
a noise rejection setting for both SCL and SDA lines.

Introduce a setting for noise rejection through device properties,
"qcom,noise-reject-sda" and "qcom,noise-reject-scl", which will
be used to set the level of noise rejection sensitivity.
If the properties are not specified, noise rejection will not be
enabled.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
2d498601d7 dt-bindings: i2c: qcom,i2c-qup: Convert txt to YAML schema
Convert the qcom,i2c-qup binding to YAML schema.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
316da4338e dt-bindings: touchscreen: Add binding for Novatek NT36xxx series driver
Add binding for the Novatek NT36xxx series touchscreen driver.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
b2d9f95754 Input: Add Novatek NT36xxx touchscreen driver
This is a driver for the Novatek in-cell touch controller and
supports various chips from the NT36xxx family, currently
including NT36525, NT36672A, NT36676F, NT36772 and NT36870.

Functionality like wake gestures and firmware flashing is not
included: I am not aware of any of these DrIC+Touch combo
chips not including a non-volatile memory and it should be
highly unlikely to find one, since the touch firmware is
embedded into the DriverIC one, which is obviously necessary
to drive the display unit.

However, the necessary address for the firmware update
procedure was included into the address table in this driver
so, in the event that someone finds the need to implement it
for a reason or another, it will be pretty straightforward to.

This driver is lightly based on the downstream implementation [1].
[1] https://github.com/Rasenkai/caf-tsoft-Novatek-nt36xxx

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
298422843e dt-bindings: Add vendor prefix for Novatek Microelectronics Corp.
Add prefix for Novatek Microelectronics Corp.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
932b09a720 media: dt-bindings: media: i2c: Add IMX300 CMOS sensor binding
Add YAML device tree binding for IMX300 CMOS image sensor, and
the relevant MAINTAINERS entries.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
68fb74869b media: i2c: Add driver for the Sony Exmor-RS IMX300 camera sensor
This is a custom multi-aspect 25MegaPixels sensor from Sony,
found in many Sony Xperia smartphones from various eras.

The camera assembly for this sensor usually (at least in Xperia
phones) has a lens that does not cover the entire sensor area,
which means that the real corners are blind and that, in many
lighting conditions, some more pixels in the corners are very
getting obscured (as no decent amount of light can get in)...
so, the maximum resolution that can produce a good image is:
- In 4:3 aspect ratio, 5520x4160 (23.0MP)
- In 16:9 aspect ratio, 5984x3392 (20.3MP).

This sensor supports high frame rates (>=60FPS) when in binning
mode and both RAW8 and RAW10 output modes.
In this version of the driver, support has been provided for the
following resolutions:
    W x H     SZ   MAX_FPS  BINNING
- 5520x4160 23.0MP   23       No
- 5984x3392 20.3MP   26       No
- 2992x1696  3.8MP   60       Yes
- 1424x800   1.2MP   120      Yes

Note 1: The "standard" camera assy for IMX300 also contains an
actuator (to focus the image), but this driver only manages the
actual image sensor.

Note 2: The command tables for this sensor were reverse
engineered from a downstream "userspace driver" that has been
released in various versions on various Xperia smartphones.
Register layout seems to be only vaguely similar to IMX219,
which has a public datasheet from where some names for the
figured out registers were taken and added to the driver:
these names are probably not the right ones, but they surely
represent the intended thing.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:31 +02:00
AngeloGioacchino Del Regno
47babd6872 drm/msm/dpu1: Add MSM8998 to hw catalog
Bringup functionality for MSM8998 in the DPU, driver which is mostly
the same as SDM845 (just a few variations).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:31 +02:00
Konrad Dybcio
2f458a6272 clk: qcom: smd: Add missing MSM8998 RPM clocks
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
JAMI: fixed for a0384ecfe2 ("clk: qcom: smd-rpm: De-duplicate identical entries")
JAMI: fixed for 36354c32bd ("clk: qcom: smd-rpm: Add .recalc_rate hook for clk_smd_rpm_branch_ops")
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
c4e8ede8cf drm/msm/dpu: Fix timeout issues on command mode panels
In function dpu_encoder_phys_cmd_wait_for_commit_done we are always
checking if the relative CTL is started by waiting for an interrupt
to fire: it is fine to do that, but then sometimes we call this
function while the CTL is up and has never been put down, but that
interrupt gets raised only when the CTL gets a state change from
0 to 1 (disabled to enabled), so we're going to wait for something
that will never happen on its own.

Solving this while avoiding to restart the CTL is actually possible
and can be done by just checking if it is already up and running
when the wait_for_commit_done function is called: in this case, so,
if the CTL was already running, we can say that the commit is done
if the command transmission is complete (in other terms, if the
interface has been flushed).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
75d376a90e drm/msm/dpu: Add a function to retrieve the current CTL status
Add a function that returns whether the requested CTL is active or not:
this will be used in a later commit to fix command mode panel issues.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
7e3c8189f5 arm64: dts: qcom: pmi8998: Add node for WLED
The PMI8998 PMIC has a WLED backlight controller, which is used on
most MSM8998 and SDM845 based devices: add a base configuration for
it and keep it disabled.

This contains only the PMIC specific configuration that does not
change across boards; parameters like number of strings, OVP and
current limits are product specific and shall be specified in the
product DT in order to achieve functionality.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
c47e38e029 arm64: dts: msm8998: Add SAW, CPRh and CPUFREQ to enable CPU scaling
Add the SAW (SPM), CPR-Hardened, CPUFREQ-HW nodes and relative OPP
tables (and also assign them to the CPU nodes, as required) in order
to enable CPU scaling on the MSM8998 SoC.

The CPR-Hardened and CPUFREQ-HW nodes are disabled by default as to
not change the previous default behavior. Since the drivers are not
yet accounting for speed-binning, these OPPs are referred to the
most common binning for this chip, which I have found on six phones
from Sony and one from FxTec (silver bin0, perf bin2).

At least until speed-binning gets done in the cpufreq-hw and CPR
drivers, users should enable CPR-Hardened and CPUFREQ in their own
board DT.
This is done like that because these drivers are really big, so the
idea is to keep the "base" version easier (but perfectly working),
before adding speed-binning "complications", which may... or may not
be necessary.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
a326baf8f2 arm64: dts: msm8998: Wire up interconnects to MDP and GPU
Wire up the interconnects to both the MDP and the Adreno GPU in
order to get the right balance between performance and power
consumption of both devices.
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
008a5ed048 arm64: dts: qcom: Enable panel etc. on MSM8998 F(x)tec Pro1 QX1000
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:30 +02:00
Konrad Dybcio
c2e3861fd7 arm64: dts: qcom: pm8998: Add VREF_1P25 and REF_GND VADC channels
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
8b0d1f9c9c arm64: dts: msm8998: Wire up interconnects and OPPs to sdhci port 2
Wire up the OPP table and interconnects to the SDHCI port 2 to
improve performance and power consumption.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
44ec014f38 arm64: dts: msm8998: Add interconnect nodes
This SoC features Network-on-Chip (NoC) and Bus Integrated Memory
Controller (BIMC) interconnects: add the required nodes now that
the driver is present.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
f47f056002 arm64: dts: msm8998: Add disabled configuration for DPU1/DSI
This SoC supports both the MDP5 and DPU1 drivers, but the
latter was chosen as it's more feature-complete;

Configure the DPU1, DSI and related phy and pll in order to
achieve display functionality and keep it disabled.
Enabling it will be done on board specific DT when needed,
as not all boards have a usable display attached to them.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
f1ea33bf02 arm64: dts: qcom: Enable panel etc. on MSM8998 Sony Yoshino platform
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
7da5abe66e arm64: dts: sdm630: Assign 300MHz frequency to HMSS GPLL0 clock
At cpufreq_hw initialization, we need to assign a frequency of 300MHz
to the HMSS GPLL0 clock in order to achieve the recommended low sleep
frequency (and low voltage) for both the gold and silver clusters.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
ad3536fd33 dt-bindings: soc: qcom: cpr3: Add bindings for CPR3 driver
Add the bindings for the CPR3 driver to the documentation.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Reviewed-by: Rob Herring <robh@kernel.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
134e7d3c3f MAINTAINERS: Add entry for Qualcomm CPRv3/v4/Hardened driver
Add maintainers entry for the Qualcomm CPR3/CPR4/CPRh driver.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
4a8417d616 soc: qcom: Add support for Core Power Reduction v3, v4 and Hardened
This commit introduces a new driver, based on the one for cpr v1,
to enable support for the newer Qualcomm Core Power Reduction
hardware, known downstream as CPR3, CPR4 and CPRh, and support
for MSM8998 and SDM630 CPU power reduction.

In these new versions of the hardware, support for various new
features was introduced, including voltage reduction for the GPU,
security hardening and a new way of controlling CPU DVFS,
consisting in internal communication between microcontrollers,
specifically the CPR-Hardened and the Operating State Manager.

The CPR v3, v4 and CPRh are present in a broad range of SoCs,
from the mid-range to the high end ones including, but not limited
to, MSM8953/8996/8998, SDM630/636/660/845.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
44869d20db arm64: qcom: qcs404: Change CPR nvmem-names
The CPR driver's common functions were split and put in another
file in order to support newer CPR revisions: to simplify the
commonization, the expected names of the fuses had to be changed
in order for both new and old support to use the same fuse name
retrieval function and keeping the naming consistent.

The thread id was added to the fuse name and, since CPRv1 does
not support threads, it is expected to always read ID 0, which
means that the expected name here is now "cpr0_(fuse_name)"
instead of "cpr_(fuse_name)": luckily, QCS404 is the only user
so change it accordingly.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
6c2c879a78 dt-bindings: avs: cpr: Convert binding to YAML schema
Convert the qcom,cpr.txt document to YAML schema and place it in the
appropriate directory, since this driver was moved from power/avs
to soc/qcom, but forgets to move the documentation.

Fixes: a7305e684f ("PM: AVS: qcom-cpr: Move the driver to the qcom specific drivers")
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
f833e21372 soc: qcom: cpr: Move common functions to new file
In preparation for implementing a new driver that will be handling
CPRv3, CPRv4 and CPR-Hardened, format out common functions to a new
file.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
[Fixup for 5.15 by Jami]
2021-12-22 01:14:30 +02:00
AngeloGioacchino Del Regno
786993afff dt-bindings: cpufreq: qcom-hw: Make reg-names a required property
The property reg-names is required after the addition of the OSM
programming sequence, as that mandates specifying different register
domains; to avoid confusion and improve devicetree readability,
specifying the regions names was made mandatory.
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
6adc6091be dt-bindings: cpufreq: qcom-hw: Add bindings for 8998
The OSM programming addition has been done under the
qcom,cpufreq-hw-8998 compatible name: specify the requirement
of two additional register spaces for this functionality.
This implementation, with the same compatible, has been
tested on MSM8998 and SDM630.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
819bb21db6 cpufreq: qcom-hw: Allow getting the maximum transition latency for OPPs
In order to fine-tune the frequency scaling from various governors,
allow to set a maximum transition latency from OPPs, which may be
different depending on the SoC.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
[Fixup for 5.15 by Jami]
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
8a7b3d8b05 cpufreq: qcom-hw: Implement CPRh aware OSM programming
On new SoCs (SDM845 onwards) the Operating State Manager (OSM) is
being programmed in the bootloader and write-protected by the
hypervisor, leaving to the OS read-only access to some of its
registers (in order to read the Lookup Tables and also some
status registers) and write access to the p-state register, for
for the OS to request a specific performance state to trigger a
DVFS switch on the CPU through the OSM hardware.

On old SoCs though (MSM8998, SDM630/660 and variants), the
bootloader will *not* initialize the OSM (and the CPRh, as it
is a requirement for it) before booting the OS, making any
request to trigger a performance state change ineffective, as
the hardware doesn't have any Lookup Table, nor is storing any
parameter to trigger a DVFS switch. In this case, basically all
of the OSM registers are *not* write protected for the OS, even
though some are - but write access is granted through SCM calls.

This commit introduces support for OSM programming, which has to
be done on these old SoCs that were distributed (almost?) always
with a bootloader that does not do any CPRh nor OSM init before
booting the kernel.
In order to program the OSM on these SoCs, it is necessary to
fullfill a "special" requirement: the Core Power Reduction
Hardened (CPRh) hardware block must be initialized, as the OSM
is "talking" to it in order to perform the Voltage part of DVFS;
here, we are calling initialization of this through Linux generic
power domains, specifically by requesting a genpd attach from the
qcom-cpufreq-hw driver, which will give back voltages associated
to each CPU frequency that has been declared in the OPPs, scaled
and interpolated with the previous one, and will also give us
parameters for the Array Power Mux (APM) and mem-acc, in order
for this driver to be then able to generate the Lookup Tables
that will be finally programmed to the OSM hardware.

After writing the parameters to the OSM and enabling it, all the
programming work will never happen anymore until a OS reboot, so
all of the allocations and "the rest" will be disposed-of: this
is done mainly to leave the code that was referred only to the
new SoCs intact, as to also emphasize on the fact that the OSM
HW is, in the end, the exact same; apart some register offsets
that are slightly different, the entire logic is the same.

This also adds the parameters to support CPU scaling on SDM630
and MSM8998.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
[Fixup for 5.15 by Jami]
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
c05f3991a1 cpufreq: qcom-hw: Add kerneldoc to some functions
Some functions may not be very straightforward to understand:
add kerneldoc to some ones in order to improve readability.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
Manivannan Sadhasivam
0ef5eb8ae1 dt-bindings: cpufreq: cpufreq-qcom-hw: Convert to YAML bindings
Convert Qualcomm cpufreq devicetree binding to YAML.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
Manivannan Sadhasivam
040a951871 dt-bindings: arm: cpus: Document 'qcom,freq-domain' property
Add devicetree documentation for 'qcom,freq-domain' property specific
to Qualcomm CPUs. This property is used to reference the CPUFREQ node
along with Domain ID (0/1).

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
71718edee1 cpufreq: Add MSM8998 to cpufreq-dt-platdev blocklist
Add the MSM8998 to the blocklist since the CPU scaling is handled
out of this.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
d22af50489 cpufreq: Add SDM630/636/660 to cpufreq-dt-platdev blocklist
Add the SDM630, SDM636 and SDM660 to the blocklist since the CPU
scaling is handled out of this.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
d6a16a91e0 arm64: DT: sdm630: Configure CPRh and cpufreq-hw for CPU scaling
Now that the CPR v3/v4/Hardened is ready and the cpufreq-hw driver
got OSM programming, we can finally enable CPU scaling on both
of the clusters on SDM630.
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
af90a1ce6d arm64: dts: qcom: Introduce SDM660 Xiaomi Mi 8 Lite (platina)
Add support for the SDM660 Xiaomi Platina (Mi 8 Lite).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
76c4433782 arm64: dts: qcom: sdm630: Disallow disabling secured iommu context banks
Some IOMMU context banks are secured and any attempt to disable them
during arm-smmu initialization will result in a system crash.
To work around this issue, add a list of context banks that will never
be disabled, but only reconfigured, at initialization time.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
4159f402ee arm64: dts: sdm630: Override bypass emulation context for lpass, anoc2
On the LPASS and ANOC2 IOMMUs, we cannot use the last context to
emulate bypass streams: set the right context banks to avoid crashes.
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
b38dd2c5b9 iommu/arm-smmu-qcom: Don't modify sACR on hypervisor secured iommus
Avoid modifying the contents of the secure Auxiliary Control Register
on some Qualcomm SoCs: due to a hypervisor configuration on some
firmware versions, this would result in a system crash.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
0dcea98014 iommu/arm-smmu-qcom: Avoid disabling secured context banks
Some Qualcomm SoCs' TZ/hypervisor configuration is disallowing the
disablement of some context banks, being them used for tzapps and/or
remote processors; any attempt to disable such CBs will result in
triggering a fault and the system will freeze and/or reset.

For this reason, get a list of context banks that should never get
disabled during smmu initialization through a DT array property
`qcom,reset-nodisable-cbs`.
It was chosen to not hardcode the CBs as this is dependant on the
SoC's firmware, which may vary on different boards.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
8058f9b46a iommu/arm-smmu: Allow skipping context bank disable at reset time
On some SoCs some IOMMU context banks are actively used from TZ
during system boot, or some hypervisor configurations will trigger
a system reset upon disabling some protected/secured CBs.

Allow skipping the disablement of such contexts at IOMMU reset time
during initialization with a new implementation detail to work around
this quirk.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
AngeloGioacchino Del Regno
5d25ef59ae iommu/arm-smmu-qcom: Allow choosing a custom bypass emulation context
It cannot be taken for granted that the last IOMMU context is free
and available for us to use it to emulate bypass streams and, at least
on MSM8998's lpass iommu, using the last one will produce a crash;
please note that this may not be only dependant on the SoC, but also
on the firmware version.

To overcome to this issue, allow specifying a different context for
bypass emulation with the optional DT property "qcom,bypass-cbndx":
if this property is not found this means that we are either booting
with ACPI instead or that we don't want to specify a custom cb because
the default one (the last context bank) is fine.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-12-22 01:14:29 +02:00
Marijn Suijten
1406a16faf qcom-lpg: Review fixups! 2021-12-22 01:14:29 +02:00
Marijn Suijten
b2995ca65c leds: qcom-lpg: Add PM660L 2021-12-22 01:14:29 +02:00
Jami Kettunen
c3964aae1c arm64: sdm660_defconfig: Add
Combines all of the following from the op5/5.15 branch into a separate
file:

  4419531c3d defconfig: Leds, QCOM_LPG, and all the led triggers!
  4121e0bc1c android-recommended lies: AIO is needed for adb :|
  80d6ecc10a defconfig: Disco panel!
  e5b76990e8 arm64: defconfig: Disable legacy USB networking in favour of configfs
  4835b657d6 defconfig: a508 zap, a530 firmware
  be3b2acd0d defconfig: Interconnect
  f5bd27247f defconfig; MMCC and GPUCC 660
  8f263ba951 Android defconfig
  328f064e3a 660 defconfig
2021-12-22 01:14:28 +02:00
Marijn Suijten
623540b77d NILE/pm660l: LPG 2021-12-22 01:14:28 +02:00
Bjorn Andersson
6c9da9c1ab arm64: dts: qcom: db820c: Add user LEDs
The db820c has 4 "user LEDs", all connected to the PMI8994. The first
three are connected to the three current sinks provided by the TRILED
and the fourth is connected to MPP2.

By utilizing the DTEST bus the MPP is fed the control signal from the
fourth LPG block, providing a consistent interface to the user.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:28 +02:00
Bjorn Andersson
aa2fb3fd61 arm64: dts: qcom: pmi8994: Define MPP block
The pmi8994 has 4 multi-purpose-pins, add these to the definition.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-12-22 01:14:28 +02:00
Bjorn Andersson
ccf540041f arm64: dts: qcom: sdm845: Enable user LEDs on DB845c
The DB845c has 4 "user LEDs", the last one is already supported as it's
just wired to a gpio. Now that the LPG binding is in place we can wire
up the other 3 LEDs as well.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-12-22 01:14:28 +02:00
Bjorn Andersson
e8d3fd4633 arm64: dts: qcom: Add LPG to pm8916, pm8994, pmi8994 and pmi8998
Add PWM/LPG nodes to the PMICs currently supported by the binding.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:28 +02:00
Bjorn Andersson
fed6e27683 leds: Add driver for Qualcomm LPG
The Light Pulse Generator (LPG) is a PWM-block found in a wide range of
PMICs from Qualcomm. It can operate on fixed parameters or based on a
lookup-table, altering the duty cycle over time - which provides the
means for e.g. hardware assisted transitions of LED brightness.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-12-22 01:14:28 +02:00
Bjorn Andersson
e07ec64088 dt-bindings: leds: Add Qualcomm Light Pulse Generator binding
This adds the binding document describing the three hardware blocks
related to the Light Pulse Generator found in a wide range of Qualcomm
PMICs.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
2021-12-22 01:14:28 +02:00
Marijn Suijten
fdafc0019a leds: ledtrig-pattern: Use last_repeat when applying hw pattern
`last_repeat` holds the actual value requested by the user whereas
`repeat` is a software iteration variable that is unused in hardware
patterns.

Furthermore `last_repeat` is the field returned to the user when reading
the `repeat` sysfs property.  This field is initialized to `-1` which is
- together with `1` - the only valid value in the upcoming Qualcomm LPG
driver.  It is thus unexpected when `repeat` with an initialization
value of `0` is passed into the the driver, when the sysfs property
clearly presents a value of `-1`.

Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
2021-12-22 01:14:28 +02:00
Marijn Suijten
845ae94d37 FIXUP: simple-panel: add missing connector_type! 2021-12-22 01:14:28 +02:00
Marijn Suijten
7bd23d981f PANEL INNOLUX FIXUP!: Use set_tear_on for VBLANK instead of magic const 2021-12-22 01:14:28 +02:00
Marijn Suijten
d865ddef07 gpu go 700mhz 2021-12-22 01:14:28 +02:00
Marijn Suijten
b2d482ea0d sdm630: Add missing zap-shader! 2021-12-22 01:14:28 +02:00
Marijn Suijten
67da594956 nile: Turn on pm660l_wled to not -EPROBE_DEFER the panel 2021-12-22 01:14:28 +02:00
Marijn Suijten
4d86d0c5b4 DISCO PANELS?!?!? 2021-12-22 01:14:28 +02:00
Marijn Suijten
32e78e5c41 PANELS TODO FINISHME: use dev_err_probe in _probe! 2021-12-22 01:14:28 +02:00
Konrad Dybcio
f10637ebf1 arm64: dts: qcom: sdm63*-xperia: Add display panels
Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
2021-12-22 01:14:28 +02:00
Marijn Suijten
4ccb81c57b 630: Also system part, root fstab not found 2021-12-22 01:14:28 +02:00
Marijn Suijten
d2f323864d bye slotselect 2021-12-22 01:14:28 +02:00
Marijn Suijten
98751f8c78 Adreno firmware in .c file; vendor DT 2021-12-22 01:14:28 +02:00
Marijn Suijten
5d7ecb459b bye framebuffer and sdhc_2 2021-12-22 01:14:27 +02:00
Marijn Suijten
3a590afb1a nile: Enable gpucc 2021-12-22 01:14:27 +02:00
Konrad Dybcio
16bb0ee336 arm64: dts: qcom: sdm630: Enable SMMUs
Now that the quirks are in, SMMUs are fine to enable.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
64f6436594 remoteproc: Add support for SDM630/636/660 MSS remoteproc
This adds support for sdm630/636/660 modem subsystem
remote processor.

Currently an issue persists, where the remote processor will
restart itself every 40 seconds, but it seems to work otherwise.

Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:27 +02:00
AngeloGioacchino Del Regno
deeb3aa715 drm/msm/mdp5: Fix SDM630/660 MDP5 configuration
SDM630 has two usable layer mixers (LM0, LM2) and pingpongs (PP0, PP2),
with writeback located on LM2, has no RGB pipe and does not support
source split.

SDM660 has four usable layer mixers (LM0, LM1, LM2, LM5) and
three pingpongs (PP0, PP1, PP4), with writeback located on LM2,
has no RGB pipes and does support source split; also, the HDMI
is on INTF0.

As cherry on top, let's also write the correct flush_hw_mask for
both MDP configurations to stop flushing useless and unused pipes
for performance purposes.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
3e5b523e39 drm/panel-simple: Add nt36672a Tianma FHD+ panel
This adds support for nt36672a Tianma FHD+ (2520x1080)
video mode panel as found on Sony Xperia 10 Plus (mermaid)
devices.

Due to the nature of phone manufacturing, it is impossible
to retrieve the actual panel name, hence the replacement
one, detailing the device it's used on.

Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
bf0f4ab2ce drm/panel-simple: Add nt36672a Truly FHD+ panel
This adds support for nt36672a Truly FHD+ (2520x1080)
video mode panel as found on Sony Xperia 10 (kirin)
devices.

Due to the nature of phone manufacturing, it is impossible
to retrieve the actual panel name, hence the replacement
one, detailing the device it's used on.

Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
521b4dcb0c dt-bindings: display: panel: Document Sony Voyager TD4328 Tianma display panel
Add bindings for the newly added panel.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
38b61c0a4c drm/panel: Add support for Sony TD4328 Tianma FHD+ panel
This commit adds support for Sony TD4328 Truly
Full HD Plus command mode DSI panel, as found in Sony
Xperia XA2 Plus smartphones.

Due to the nature of phone manufacturing, it is impossible
to retrieve the actual panel name, hence the replacement
one, detailing the device it's used on.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
a592fe2d95 dt-bindings: display: panel: Document Sony Discovery TD4322 Innolux display panel
Add bindings for the newly added panel.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
dd1f6900f8 drm/panel: Add support for Sony TD4322 Innolux FHD panel
This commit adds support for Sony TD4322 Innolux
Full HD command mode DSI panel, as found in Sony
Xperia XA2 Ultra smartphones.

Due to the nature of phone manufacturing, it is impossible
to retrieve the actual panel name, hence the replacement
one, detailing the device it's used on.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
b10673b76c dt-bindings: display: panel: Document Sony Pioneer TD4322 Truly display panel
Add bindings for the newly added panel.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
2a63c83b72 drm/panel: Add support for Sony TD4322 Truly FHD panel
This commit adds support for Sony TD4322 Truly
Full HD command mode DSI panel, as found in Sony
Xperia XA2 smartphones.

Due to the nature of phone manufacturing, it is impossible
to retrieve the actual panel name, hence the replacement
one, detailing the device it's used on.

Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
2f5fb1d716 drivers: interconnect: qcom: sdm660: Adjust to v5.10 changes
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:27 +02:00
Konrad Dybcio
c5f2e76cb4 drivers: interconnect: sdm660: MASTER_CRYPTO_C0 isn't AP-Owned
Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
(JAMI: fixed up for v5.16-rc1)
2021-12-22 01:14:27 +02:00
AngeloGioacchino Del Regno
d582b78bb4 arm64: dts: qcom: sdm630-nile: Configure WCN3990 Bluetooth
Add a node for WCN3990 HCIUART Bluetooth.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
AngeloGioacchino Del Regno
a1583a5115 arm64: dts: qcom: sdm630-xperia-nile: Add all RPM and fixed regulators
Add all of the RPM PM660/PM660L regulators and the fixed ones,
defining the common electrical part of this platform.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-12-22 01:14:27 +02:00
Konrad Dybcio
73db495db2 arm64: dts: qcom: sdm630: Fix intc reg indentation
Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
2021-12-22 01:14:27 +02:00
151 changed files with 29918 additions and 962 deletions

View file

@ -305,6 +305,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: |

View file

@ -41,6 +41,7 @@ description: |
sa8155p
sc7180
sc7280
msm8998
sdm630
sdm660
sdm845
@ -207,6 +208,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

View file

@ -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>;
};
}

View 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>;
};
};
...

View file

@ -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>;
};
};

View file

@ -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>;
};
};
};
};
};
...

View file

@ -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

View file

@ -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>;
};
};

View file

@ -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>;
};
};

View file

@ -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>;
};
};

View file

@ -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>;
};

View 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>;
};

View file

@ -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>;
};

View 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>;
};
};

View file

@ -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>;
};
};
...

View 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>;
};

View 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>;
};
...

View 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>;
};
};
};
};
...

View file

@ -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;
};
};
};

View file

@ -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

View 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";
};
...

View 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";
};
...

View file

@ -828,6 +828,8 @@ patternProperties:
description: Nokia
"^nordic,.*":
description: Nordic Semiconductor
"^novatek,.*":
description: Novatek Microelectronics Corp.
"^novtech,.*":
description: NovTech, Inc.
"^nutsboard,.*":
@ -852,6 +854,8 @@ patternProperties:
description: OLIMEX Ltd.
"^olpc,.*":
description: One Laptop Per Child
"^oneplus,.*":
description: OnePlus Technology (Shenzhen) Co., Ltd.
"^onion,.*":
description: Onion Corporation
"^onnn,.*":

View file

@ -15740,9 +15740,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
@ -17758,6 +17764,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

View file

@ -84,6 +84,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

View file

@ -10,6 +10,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>
@ -671,6 +672,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>;

View file

@ -18,6 +18,15 @@
chassis-type = "handset";
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;
};
/*
* Until we hook up type-c detection, we
* have to stick with this. But it works.
@ -48,6 +57,8 @@
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_pins_extra>;
@ -100,6 +111,39 @@
};
};
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-keys {
compatible = "gpio-keys";
input-name = "side-buttons";
@ -180,6 +224,53 @@
};
};
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";
@ -192,8 +283,62 @@
};
};
&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 {
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";
@ -208,6 +353,120 @@
};
};
&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";
};
@ -216,7 +475,35 @@
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";
@ -270,6 +557,26 @@
bias-pull-up;
};
gpio_expander_int_n: gpio-exp-intn-def {
pins = "gpio50";
function = "gpio";
drive-strength = <2>;
input-enable;
};
gpio_expander_rst_n: gpio-exp-rst-def {
pins = "gpio51";
function = "gpio";
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";
function = "gpio";
@ -298,6 +605,13 @@
bias-disable;
drive-strength = <8>;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
};
&ufshc {

View file

@ -41,3 +41,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>;
};

View file

@ -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,145 @@
};
};
&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/msm8998/oneplus/a540_zap.mbn";
};
/*
* We are lacking support for the GPU regulator. Hence, disable higher
* frequencies for now to prevent the platform from hanging on high
* graphics loads. Perhaps the pm8005_s1 voltage below could be
* adjusted but I'd rather not touch it.
*/
opp-table {
/delete-node/ opp-710000097;
/delete-node/ opp-670000048;
/delete-node/ opp-596000097;
/delete-node/ opp-515000097;
};
};
&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 +700,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 {
@ -502,7 +755,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>;

View file

@ -24,3 +24,8 @@
&rmi4_f12 {
touchscreen-y-mm = <137>;
};
/* Display */
&panel {
compatible = "samsung,s6e3fc1";
};

View file

@ -25,6 +25,11 @@
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>;

View file

@ -26,6 +26,28 @@
};
};
&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>;
@ -37,6 +59,32 @@
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";
@ -53,3 +101,17 @@
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";
};

View file

@ -25,6 +25,11 @@
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>;

View file

@ -20,6 +20,10 @@
qcom,msm-id = <0x124 0x20000>, <0x124 0x20001>; /* 8998v2, v2.1 */
qcom,board-id = <8 0>;
chosen {
bootargs = "clk_ignore_unused root=/dev/mmcblk0p1";
};
clocks {
compatible = "simple-bus";
@ -84,6 +88,15 @@
pinctrl-0 = <&ts_vddio_en>;
};
/* The gpio-vibrator driver enforces requiring a regulator */
vib_vreg: vib-regulator {
compatible = "regulator-fixed";
regulator-name = "vib";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
vph_pwr: vph-pwr-regulator {
compatible = "regulator-fixed";
regulator-name = "vph_pwr";
@ -186,11 +199,28 @@
vibrator {
compatible = "gpio-vibrator";
enable-gpios = <&pmi8998_gpio 5 GPIO_ACTIVE_HIGH>;
vcc-supply = <&vib_vreg>;
pinctrl-names = "default";
pinctrl-0 = <&vib_default>;
};
};
&adreno_gpu {
status = "ok";
zap-shader {
memory-region = <&zap_shader_region>;
};
};
&adreno_smmu {
status = "ok";
};
&apc_cprh {
status = "ok";
};
&blsp1_i2c5 {
status = "okay";
clock-frequency = <355000>;
@ -243,10 +273,79 @@
};
};
&blsp2_i2c1 {
tof-sensor@29 {
compatible = "st,vl53l0x";
reg = <0x29>;
interrupt-parent = <&tlmm>;
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
#io-channel-cells = <1>;
label = "back_camera_tof";
pinctrl-names = "default";
pinctrl-0 = <&tof_int_n &tof_rst_n>;
};
};
&blsp2_uart1 {
status = "okay";
};
&cpufreq_hw {
status = "ok";
};
&dsi0 {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
vdd-supply = <&vreg_l1a_0p875>;
vdda-supply = <&vreg_l2a_1p2>;
panel: panel@0 {
reg = <0>;
backlight = <&pmi8998_wled>;
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>;
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
avdd-supply = <&lab>;
avee-supply = <&ibb>;
vddio-supply = <&vreg_l14a_1p85>;
tavdd-supply = <&vreg_l28_3p0>;
tvddio-supply = <&touch_vddio_vreg>;
pinctrl-names = "default";
pinctrl-0 = <&panel_reset_n &mdp_vsync_n>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
panel_in0: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
};
&dsi0_out {
remote-endpoint = <&panel_in0>;
data-lanes = <0 1 2 3>;
};
&dsi0_phy {
status = "okay";
vdds-supply = <&vreg_l1a_0p875>;
};
&gpucc {
status = "ok";
};
&ibb {
regulator-min-microamp = <800000>;
regulator-max-microamp = <800000>;
@ -272,6 +371,25 @@
regulator-soft-start;
};
&lpass_q6_smmu {
qcom,bypass-cbndx = /bits/ 8 <11>;
qcom,reset-nodisable-cbs = /bits/ 8 <12>;
status = "ok";
};
&mmcc {
status = "ok";
};
&mmss_smmu {
status = "ok";
};
&mdss {
status = "okay";
};
&mmcc {
status = "ok";
};
@ -288,7 +406,12 @@
/* VDD_GFX supply */
pm8005_s1: s1 {
regulator-min-microvolt = <524000>;
/*
* HACK: Set enough voltage for max GPU frequency
* and set the regulator always on until the
* GPU Core Power Reduction gets available
*/
regulator-min-microvolt = <988000>;
regulator-max-microvolt = <1088000>;
regulator-enable-ramp-delay = <500>;
regulator-always-on;
@ -326,6 +449,13 @@
function = "func2";
power-source = <0>;
};
nfc_clk_req_pin: nfc-clk-req-active {
pins = "gpio21";
function = PMIC_GPIO_FUNC_NORMAL;
input-enable;
power-source = <1>;
};
};
&pmi8998_gpio {
@ -360,6 +490,37 @@
};
};
&pmi8998_wled {
status = "okay";
default-brightness = <800>;
qcom,switching-freq = <800>;
qcom,ovp-millivolt = <29600>;
qcom,current-boost-limit = <970>;
qcom,current-limit-microamp = <25000>;
qcom,num-strings = <2>;
qcom,enabled-strings = <0 1>;
};
&q6asmdai {
dai@0 {
reg = <0>;
};
dai@1 {
reg = <1>;
};
dai@2 {
reg = <2>;
};
dai@3 {
reg = <3>;
// direction = <2>;
// is-compress-dai;
};
};
&qusb2phy {
status = "okay";
@ -367,6 +528,19 @@
vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
};
&remoteproc_adsp {
firmware-name = "adsp.mdt";
status = "okay";
};
&remoteproc_mss {
status = "disabled";
};
&remoteproc_slpi {
firmware-name = "slpi.mdt";
};
&rpm_requests {
pm8998-regulators {
compatible = "qcom,rpm-pm8998-regulators";
@ -555,6 +729,371 @@
pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
};
/* EAR-EN is NXP NX5L2750C */
/* Downstream example
&snd_9335 {
qcom,msm-mbhc-hphl-swh = <1>;
/delete-property/ qcom,hph-en1-gpio;
/delete-property/ qcom,hph-en0-gpio;
/delete-property/ qcom,us-euro-gpios;
qcom,ear-en-gpios = <&pm8005_gpios 1 0>;
qcom,audio-routing =
"AIF4 VI", "MCLK",
"RX_BIAS", "MCLK",
"MADINPUT", "MCLK",
"AMIC2", "MIC BIAS2",
"MIC BIAS2", "Headset Mic",
"MIC BIAS2", "ANCRight Headset Mic",
"AMIC3", "MIC BIAS3",
"MIC BIAS3", "ANCLeft Headset Mic",
"DMIC0", "MIC BIAS1",
"MIC BIAS1", "Digital Mic0",
"DMIC3", "MIC BIAS4",
"MIC BIAS4", "Digital Mic3",
"SpkrLeft IN", "SPK1 OUT",
"SpkrRight IN", "SPK2 OUT";
};
*/
&slimbam {
status = "okay";
};
&slim {
status = "okay";
};
&slim_ngd {
tasha_ifd: tas-ifd {
compatible = "slim217,1a0";
reg = <0 0>;
};
wcd9335: codec@1{
compatible = "slim217,1a0";
reg = <1 0>;
clock-names = "mclk", "slimbus";
clocks = <&div1_mclk>,
<&rpmcc RPM_SMD_LN_BB_CLK1>;
#clock-cells = <0>;
interrupt-parent = <&tlmm>;
interrupts = <54 IRQ_TYPE_LEVEL_HIGH>,
<53 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr1", "intr2";
interrupt-controller;
#interrupt-cells = <1>;
reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
slim-ifc-dev = <&tasha_ifd>;
vdd-buck-supply = <&vreg_s4a_1p8>;
vdd-buck-sido-supply = <&vreg_s4a_1p8>;
vdd-tx-supply = <&vreg_s4a_1p8>;
vdd-rx-supply = <&vreg_s4a_1p8>;
vdd-io-supply = <&vreg_s4a_1p8>;
qcom,mbhc-vthreshold = <1700>;
/* On SoMC Yoshino, HPHL is normally open, GND normally closed */
qcom,hphl-jack-type-normally-open;
//qcom,gnd-jack-type-normally-open;
#address-cells = <1>;
#size-cells = <1>;
#sound-dai-cells = <1>;
swm: swm@c85 {
compatible = "qcom,soundwire-v1.3.0";
reg = <0xc85 0x40>;
interrupts-extended = <&wcd9335 13>;
qcom,dout-ports = <6>;
qcom,din-ports = <2>;
qcom,ports-sinterval-low =/bits/ 8 <0x07 0x1F 0x3F 0x7 0x1F 0x3F 0x0F 0x0F>;
qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0C 0x6 0x12 0x0D 0x07 0x0A >;
qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x1F 0x00 0x00 0x1F 0x00 0x00>;
/*downstream is <0xFF 0x00 0x1F 0xFF 0x00 0x1F 0x00 0x00>;*/
qcom,ports-block-pack-mode = /bits/ 8 <0xFF 0xFF 0x01 0xFF 0xFF 0x01 0xFF 0xFF>;
clocks = <&xo>;
clock-names = "iface";
#address-cells = <2>;
#size-cells = <0>;
#sound-dai-cells = <1>;
left_spkr: wsa8810-left {
compatible = "sdw10217201000";
reg = <0 1>;
powerdown-gpios = <&tlmm 65 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&wsa_leftspk_pwr_n>;
pinctrl-names = "default";
#thermal-sensor-cells = <0>;
sound-name-prefix = "SpkrRight";
#sound-dai-cells = <0>;
};
right_spkr: wsa8810-right {
compatible = "sdw10217201000";
powerdown-gpios = <&tlmm 66 GPIO_ACTIVE_HIGH>;
reg = <0 2>;
pinctrl-0 = <&wsa_rightspk_pwr_n>;
pinctrl-names = "default";
#thermal-sensor-cells = <0>;
sound-name-prefix = "SpkrLeft";
#sound-dai-cells = <0>;
};
};
};
};
/* NOTES */
/*
# This is Dragonboard 820C
EnableSequence [
cset "name='SLIM RX0 MUX' ZERO"
cset "name='SLIM RX1 MUX' ZERO"
cset "name='SLIM RX2 MUX' ZERO"
cset "name='SLIM RX3 MUX' ZERO"
cset "name='SLIM RX4 MUX' ZERO"
cset "name='SLIM RX5 MUX' AIF4_PB"
cset "name='SLIM RX6 MUX' AIF4_PB"
cset "name='SLIM RX7 MUX' ZERO"
cset "name='RX INT1_2 MUX' RX5"
cset "name='RX INT2_2 MUX' RX6"
## gain to 0dB
cset "name='RX5 Digital Volume' 68"
## gain to 0dB
cset "name='RX6 Digital Volume' 68"
cset "name='SLIMBUS_6_RX Audio Mixer MultiMedia2' 1"
cset "name='RX INT1 DEM MUX' CLSH_DSM_OUT"
cset "name='RX INT2 DEM MUX' CLSH_DSM_OUT"
]
######### WORKS!!!!!! SHE SPEEEEEAKS!!!!!!! #########
tinymix set "SLIM RX2 MUX" ZERO
tinymix set "SLIM RX3 MUX" ZERO
tinymix set "SLIM RX4 MUX" ZERO
tinymix set "SLIM RX5 MUX" ZERO
tinymix set "SLIM RX6 MUX" ZERO
tinymix set "SLIM RX7 MUX" ZERO
tinymix set "SLIM RX0 MUX" AIF1_PB
tinymix set "SLIM RX1 MUX" AIF1_PB
tinymix set "RX INT1_2 MUX" RX0
tinymix set "RX INT2_2 MUX" RX1
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT2_1 MIX1 INP0" RX1
tinymix set "SLIMBUS_0_RX Audio Mixer MultiMedia1" 1
tinymix set "RX INT1 DEM MUX" CLSH_DSM_OUT
tinymix set "RX INT2 DEM MUX" CLSH_DSM_OUT
tinymix set "SLIM TX0 MUX" DEC0
tinymix set "AIF1_CAP Mixer SLIM TX0" 1
tinymix set "RX INT2_1 MIX1 INP0" RX1
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT1_1 MIX1 INP0" RX2
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT1_1 MIX1 INP0" RX2
tinymix set "RX INT2_1 MIX1 INP0" RX2
tinymix set "RX INT2_1 MIX1 INP0" RX1
tinymix set "RX INT1_1 MIX1 INP0" RX0
tinymix set "RX INT0_1 MIX1 INP0" RX0
tinymix set "RX INT0_1 MIX1 INP0" RX1
tinymix set "RX INT0_1 MIX1 INP0" RX2
tinymix set "RX INT0_1 MIX1 INP0" RX0
tinymix set "RX INT3_1 MIX1 INP0" RX0
tinymix set "RX INT4_1 MIX1 INP0" RX0
tinymix set "RX INT5_1 MIX1 INP0" RX0
tinymix set "RX INT6_1 MIX1 INP0" RX1
tinymix set "RX INT7_1 MIX1 INP0" RX1
tinymix set "RX INT7_1 MIX1 INP0" RX1
tinymix set "RX INT8_1 MIX1 INP0" RX1
tinymix set "RX INT0_1 MIX1 INP1" RX0
tinymix set "RX INT0_1 MIX1 INP1" RX2
tinymix set "RX INT0_1 MIX1 INP1" RX0
tinymix set "RX INT1_1 MIX1 INP1" RX0
tinymix set "RX INT2_1 MIX1 INP1" RX0
tinymix set "RX INT3_1 MIX1 INP1" RX0
tinymix set "RX INT4_1 MIX1 INP1" RX0
tinymix set "RX INT5_1 MIX1 INP1" RX0
tinymix set "RX INT6_1 MIX1 INP1" RX0
tinymix set "RX INT7_1 MIX1 INP1" RX0
tinymix set "RX INT8_1 MIX1 INP1" RX0
tinymix set "RX INT0_1 MIX1 INP2" RX1
tinymix set "RX INT1_1 MIX1 INP2" RX1
tinymix set "RX INT2_1 MIX1 INP2" RX1
tinymix set "RX INT3_1 MIX1 INP2" RX1
tinymix set "RX INT4_1 MIX1 INP2" RX1
tinymix set "RX INT5_1 MIX1 INP2" RX1
tinymix set "RX INT6_1 MIX1 INP2" RX1
tinymix set "RX INT7_1 MIX1 INP2" RX1
tinymix set "RX INT8_1 MIX1 INP2" RX1
tinymix set "RX INT8_1 MIX1 INP2" RX0
tinymix set "RX INT7_1 MIX1 INP2" RX0
tinymix set "RX INT6_1 MIX1 INP2" RX0
tinymix set "RX0 Digital Volume" 80
tinymix set "RX1 Digital Volume" 80
tinymix set "RX2 Digital Volume" 80
*/
&sound {
compatible = "qcom,msm8998-sndcard";
model = "Sony-Xperia-Yoshino";
/* Audio routing including WSA amp speakers */
/* audio-routing = "RX_BIAS", "MCLK",
"AMIC2", "MIC BIAS2",
"AMIC3", "MIC BIAS3",
"DMIC0", "MIC BIAS1",
"DMIC4", "MIC BIAS4",
"SpkrLeft IN", "SPK1 OUT",
"SpkrRight IN", "SPK2 OUT",
"MM_DL1", "MultiMedia1 Playback",
"MM_DL2", "MultiMedia2 Playback",
"MultiMedia3 Capture", "MM_UL3";
*/
/* Basic routing, 3.5mm jack only */
audio-routing = "RX_BIAS", "MCLK",
"AMIC2", "MIC BIAS2",
"AMIC3", "MIC BIAS3",
"DMIC0", "MIC BIAS1",
"DMIC4", "MIC BIAS4",
"MM_DL1", "MultiMedia1 Playback",
"MM_DL2", "MultiMedia2 Playback",
"MultiMedia3 Capture", "MM_UL3";
/*
<path name="voicemmode1-call headphones">
<ctl name="SLIM_0_RX_Voice Mixer VoiceMMode1" value="1" />
<ctl name="VoiceMMode1_Tx Mixer SLIM_0_TX_MMode1" value="1" />
</path>
<path name="sidetone-headphones">
<path name="sidetone-iir" />
<!-- 45 % of 124 (range 0 - 124) Register: 0x340 -->
<ctl name="IIR0 INP0 Volume" value="44" />
<ctl name="RX INT1 MIX2 INP" value="SRC0" />
<ctl name="RX INT2 MIX2 INP" value="SRC0" />
</path>
<path name="speaker-and-headphones">
<path name="speaker" />
<ctl name="RX INT1_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX1 Digital Volume" value="55" />
<ctl name="RX2 Digital Volume" value="55" />
<path name="headphones-hpf" />
<ctl name="Set Custom Stereo" value="Mix" />
</path>
<path name="headphones">
<ctl name="SLIM RX0 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM RX1 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM_0_RX Channels" value="Two" />
<ctl name="RX INT1_1 MIX1 INP0" value="RX0" />
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX1 Digital Volume" value="80" />
<ctl name="RX2 Digital Volume" value="80" />
</path>
<path name="headphones-hpf">
<ctl name="RX INT1_1 HPF cut off" value="CF_NEG_3DB_150HZ" />
<ctl name="RX INT2_1 HPF cut off" value="CF_NEG_3DB_150HZ" />
</path>
<path name="anc-off-headphone">
<ctl name="SLIM RX0 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM RX1 MUX" value="AIF_MIX1_PB" />
<ctl name="SLIM_0_RX Channels" value="Two" />
<ctl name="RX INT1_1 MIX1 INP0" value="RX0" />
<ctl name="RX INT2_1 MIX1 INP0" value="RX1" />
<ctl name="RX INT1 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="RX INT2 DEM MUX" value="CLSH_DSM_OUT" />
<ctl name="COMP1 Switch" value="0" />
<ctl name="COMP2 Switch" value="0" />
<ctl name="HPHL Volume" value="20" />
<ctl name="HPHR Volume" value="20" />
<ctl name="RX1 Digital Volume" value="77" />
<ctl name="RX2 Digital Volume" value="77" />
</path>
<path name="audio-record">
<ctl name="MultiMedia1 Mixer SLIM_0_TX" value="1" />
</path>
<path name="deep-buffer-playback">
<ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia1" value="1" />
</path>
*/
mm1-dai-link {
/* Deep Buffer playback for SLIM{0,7}, BT, USBAUDIO, AFE, DP, HDMI */
link-name = "MultiMedia1";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
mm2-dai-link {
/* Multichannel playback for HDMI and DP */
link-name = "MultiMedia2";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
};
};
mm3-dai-link {
/* Ultra Low Latency playback for SLIM0, HDMI, and DP */
link-name = "MultiMedia3";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
};
};
slim-dai-link {
link-name = "SLIM Playback";
cpu {
sound-dai = <&q6afedai SLIMBUS_0_RX>;
};
platform {
sound-dai = <&q6routing>;
};
codec {
/* Support only sound through 3.5mm for now: soundwire is currently unavailable */
//sound-dai = <&left_spkr>, <&right_spkr>, <&swm 0>, <&wcd9335 0>;
sound-dai = <&wcd9335 0>;
};
};
slimcap-dai-link {
link-name = "SLIM Capture";
cpu {
sound-dai = <&q6afedai SLIMBUS_0_TX>;
};
platform {
sound-dai = <&q6routing>;
};
codec {
sound-dai = <&wcd9335 1>;
};
};
};
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
@ -608,6 +1147,14 @@
drive-strength = <2>;
};
tof_int_n: tof-int-n {
pins = "gpio22";
function = "gpio";
bias-pull-up;
drive-strength = <2>;
input-enable;
};
cam1_vdig_default: cam1-vdig-default {
pins = "gpio25";
function = "gpio";
@ -615,6 +1162,74 @@
drive-strength = <2>;
};
tof_rst_n: tof-rst-n {
pins = "gpio27";
function = "gpio";
bias-disable;
drive-strength = <2>;
output-low;
};
cam1_rst_default: cam1-rst-n {
pins = "gpio28";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
cam0_rst_default: cam0-rst-n {
pins = "gpio30";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
wcd_int_n: wcd-int-n {
pins = "gpio54";
function = "gpio";
bias-pull-down;
drive-strength = <2>;
input-enable;
};
cdc_reset_n: cdc-reset-n {
pins = "gpio64";
function = "gpio";
bias-pull-down;
drive-strength = <16>;
output-high;
};
wsa_leftspk_pwr_n: wsa-leftspk-pwr-n {
pins = "gpio65";
function = "gpio";
bias-disable;
drive-strength = <2>;
output-low;
};
wsa_rightspk_pwr_n: wsa-rightspk-pwr-n {
pins = "gpio66";
function = "gpio";
bias-disable;
drive-strength = <2>;
output-low;
};
ts_reset_n: ts-reset-n {
pins = "gpio89";
function = "gpio";
bias-pull-up;
drive-strength = <8>;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
hall_sensor0_default: acc-cover-open {
pins = "gpio124";
function = "gpio";

File diff suppressed because it is too large Load diff

View file

@ -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>;

View file

@ -125,6 +125,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>;

View file

@ -135,6 +135,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";
};

View file

@ -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";

View file

@ -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>;

View file

@ -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 {
@ -53,5 +65,29 @@
status = "disabled";
};
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";
};
};
};

View file

@ -1173,19 +1173,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 {

View file

@ -23,4 +23,9 @@
/* Ganges devices feature a Novatek touchscreen instead. */
/delete-node/ &touchscreen;
&panel {
compatible = "sony,kirin-nt36672a-truly";
};
/delete-node/ &vreg_l18a_1v8;

View file

@ -13,3 +13,7 @@
compatible = "sony,discovery-row", "qcom,sdm630";
chassis-type = "handset";
};
&panel {
compatible = "sony,discovery-td4322-innolux";
};

View file

@ -13,3 +13,7 @@
compatible = "sony,pioneer-row", "qcom,sdm630";
chassis-type = "handset";
};
&panel {
compatible = "sony,pioneer-td4322-truly";
};

View file

@ -20,3 +20,7 @@
};
};
};
&panel {
compatible = "sony,voyager-td4328-tianma";
};

View file

@ -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_2p95>;
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>;
};
};

View file

@ -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";
};
sram@290000 {
@ -2117,8 +2660,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 {
@ -2280,8 +2821,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>;

View file

@ -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>;

View 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>;
};

View file

@ -595,6 +595,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 {

View file

@ -450,6 +450,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";
};
@ -619,7 +632,7 @@
pins = "gpio6", "gpio25", "gpio26";
function = "gpio";
drive-strength = <8>;
bias-disable = <0>;
bias-disable;
};
};

View file

@ -13,6 +13,10 @@
chassis-type = "handset";
};
&pmi8998_fg {
qcom,battery-capacity-ua = <3300000>;
};
&display_panel {
status = "okay";

View file

@ -19,6 +19,10 @@
compatible = "samsung,s6e3fc2x01";
};
&pmi8998_fg {
qcom,battery-capacity-ua = <3700000>;
};
&rmi4_f12 {
touchscreen-y-mm = <148>;
};

View file

@ -334,6 +334,11 @@
};
};
&pmi8998_haptics {
status = "okay";
qcom,wave-play-rate-us = <4878>;
};
&qupv3_id_0 {
status = "okay";
};

View file

@ -0,0 +1,631 @@
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
CONFIG_CGROUP_DEBUG=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BOOT_CONFIG=y
# CONFIG_FHANDLE is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_ARCH_QCOM=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=4
CONFIG_HZ_100=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_ARM64_SW_TTBR0_PAN=y
CONFIG_COMPAT=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
CONFIG_RANDOMIZE_BASE=y
# CONFIG_EFI is not set
CONFIG_HIBERNATION=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_DEBUG=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_CPU_IDLE=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
CONFIG_ARM_QCOM_CPUFREQ_HW=y
CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64_CE=y
CONFIG_CRYPTO_SHA3_ARM64=y
CONFIG_CRYPTO_SM3_ARM64_CE=y
CONFIG_CRYPTO_SM4_ARM64_CE=y
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_POLY1305_NEON=y
CONFIG_CRYPTO_NHPOLY1305_NEON=y
CONFIG_CRYPTO_AES_ARM64_BS=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_FRONTSWAP=y
CONFIG_CMA=y
CONFIG_ZSMALLOC=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_ESP=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_IP6_NF_NAT=y
CONFIG_IP6_NF_TARGET_MASQUERADE=y
CONFIG_BRIDGE=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=y
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
CONFIG_QRTR=y
CONFIG_QRTR_SMD=y
CONFIG_QRTR_TUN=y
CONFIG_BT=y
CONFIG_BT_HIDP=y
CONFIG_BT_LEDS=y
CONFIG_BT_HCIBTUSB=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_QCA=y
CONFIG_BT_QCOMSMD=y
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_MAC80211_LEDS=y
CONFIG_RFKILL=y
CONFIG_NFC=y
CONFIG_NFC_NCI=y
CONFIG_NFC_NXP_NCI=y
CONFIG_NFC_NXP_NCI_I2C=y
CONFIG_NFC_S3FWRN5_I2C=y
CONFIG_PCI=y
CONFIG_PCIE_QCOM=y
CONFIG_UEVENT_HELPER=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_EXTRA_FIRMWARE="qcom/a508_zap.b00 qcom/a508_zap.b01 qcom/a508_zap.b02 qcom/a508_zap.elf qcom/a508_zap.mdt qcom/a530_gpmu.fw2 qcom/a530_pfp.fw qcom/a530_pm4.fw"
CONFIG_EXTRA_FIRMWARE_DIR="../firmware/"
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_FW_LOADER_COMPRESS=y
# CONFIG_QCOM_EBI2 is not set
CONFIG_OF_OVERLAY=y
CONFIG_ZRAM=y
CONFIG_ZRAM_WRITEBACK=y
CONFIG_ZRAM_MEMORY_TRACKING=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QCOM_COINCELL=y
CONFIG_QCOM_FASTRPC=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_MACVLAN=y
CONFIG_MACVTAP=y
CONFIG_VXLAN=y
CONFIG_TUN=y
CONFIG_VETH=y
CONFIG_QCOM_IPA=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
CONFIG_PPP_ASYNC=y
CONFIG_USB_USBNET=y
CONFIG_ATH10K=y
CONFIG_ATH10K_SNOC=y
CONFIG_WCN36XX=y
CONFIG_INPUT_MATRIXKMAP=y
CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_TM2_TOUCHKEY=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_TOUCHSCREEN_MMS114=y
CONFIG_TOUCHSCREEN_EDT_FT5X06=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PM8941_PWRKEY=y
CONFIG_INPUT_PM8XXX_VIBRATOR=y
CONFIG_INPUT_GPIO_VIBRA=y
CONFIG_INPUT_UINPUT=y
CONFIG_RMI4_CORE=y
CONFIG_RMI4_I2C=y
CONFIG_RMI4_F11=y
CONFIG_RMI4_F12=y
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_HW_RANDOM=y
# CONFIG_DEVMEM is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_GPIO=y
CONFIG_I2C_QCOM_CCI=y
CONFIG_I2C_QUP=y
CONFIG_I2C_SLAVE=y
CONFIG_SPI=y
CONFIG_SPI_MEM=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=y
CONFIG_SPMI=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MSM=y
CONFIG_PINCTRL_MSM8976=y
CONFIG_PINCTRL_MSM8996=y
CONFIG_PINCTRL_MSM8998=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_SDM660=y
CONFIG_GPIO_WCD934X=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_QCOM_PON=y
CONFIG_THERMAL=y
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_QCOM_TSENS=y
CONFIG_QCOM_SPMI_TEMP_ALARM=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_RT5033=y
CONFIG_MFD_WCD934X=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
CONFIG_REGULATOR_USERSPACE_CONSUMER=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_VCTRL=y
CONFIG_REGULATOR_QCOM_LABIBB=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_VIDEO_QCOM_CAMSS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_MEM2MEM_DEINTERLACE=y
CONFIG_VIDEO_QCOM_VENUS=y
CONFIG_VIDEO_IMX219=y
CONFIG_DRM=y
CONFIG_DRM_MSM=y
# CONFIG_DRM_MSM_DSI_20NM_PHY is not set
# CONFIG_DRM_MSM_DSI_28NM_8960_PHY is not set
# CONFIG_DRM_MSM_DSI_7NM_PHY is not set
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_SONY_DISCOVERY_TD4322_INNOLUX=y
CONFIG_DRM_LEGACY=y
CONFIG_FB=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_PLATFORM=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y
CONFIG_BACKLIGHT_QCOM_WLED=y
CONFIG_BACKLIGHT_GPIO=y
CONFIG_BACKLIGHT_LED=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_QCOM=y
CONFIG_SND_SOC_APQ8016_SBC=y
CONFIG_SND_SOC_MSM8996=y
CONFIG_SND_SOC_MSM8916_WCD_ANALOG=y
CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=y
CONFIG_SND_SOC_WCD9335=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_HOLTEK=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTRIG=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_ZEROPLUS=y
CONFIG_HID_ZYDACRON=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_LED_TRIG=y
CONFIG_USB_CONN_GPIO=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_OTG=y
CONFIG_USB_OTG_FSM=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_ULPI=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_GPIO_VBUS=y
CONFIG_USB_ULPI=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_U_SERIAL_CONSOLE=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=64
CONFIG_MMC_DEBUG=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_LEDS_CLASS_MULTICOLOR=y
CONFIG_LEDS_QCOM_LPG=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_ACTIVITY=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_LEDS_TRIGGER_CAMERA=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_LEDS_TRIGGER_PATTERN=y
CONFIG_LEDS_TRIGGER_AUDIO=y
CONFIG_LEDS_TRIGGER_TTY=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PM8XXX=y
CONFIG_DMADEVICES=y
CONFIG_QCOM_BAM_DMA=y
CONFIG_QCOM_HIDMA_MGMT=y
CONFIG_QCOM_HIDMA=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_CLK_APCC_MSM8996=y
CONFIG_QCOM_CLK_RPM=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_MSM_MMCC_8996=y
CONFIG_MSM_GPUCC_8998=y
CONFIG_MSM_MMCC_8998=y
CONFIG_SDM_MMCC_660=y
CONFIG_SDM_GPUCC_660=y
CONFIG_SPMI_PMIC_CLKDIV=y
CONFIG_QCOM_HFPLL=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_MAILBOX=y
CONFIG_QCOM_APCS_IPC=y
CONFIG_QCOM_IPCC=y
CONFIG_ARM_SMMU=y
CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS=y
CONFIG_QCOM_IOMMU=y
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_QCOM_Q6V5_ADSP=y
CONFIG_QCOM_Q6V5_MSS=y
CONFIG_QCOM_Q6V5_PAS=y
CONFIG_QCOM_Q6V5_WCSS=y
CONFIG_QCOM_SYSMON=y
CONFIG_QCOM_WCNSS_PIL=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=y
CONFIG_RPMSG_QCOM_SMD=y
CONFIG_SOUNDWIRE=y
CONFIG_SOUNDWIRE_QCOM=y
CONFIG_QCOM_AOSS_QMP=y
CONFIG_QCOM_CPR=y
CONFIG_QCOM_GSBI=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_OCMEM=y
CONFIG_QCOM_RMTFS_MEM=y
CONFIG_QCOM_RPMPD=y
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD_RPM=y
CONFIG_QCOM_SMP2P=y
CONFIG_QCOM_SMSM=y
CONFIG_QCOM_SOCINFO=y
CONFIG_QCOM_WCNSS_CTRL=y
CONFIG_QCOM_APR=y
CONFIG_PM_DEVFREQ=y
CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
CONFIG_EXTCON_ADC_JACK=y
CONFIG_EXTCON_GPIO=y
CONFIG_EXTCON_QCOM_SPMI_MISC=y
CONFIG_EXTCON_SM5502=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_BMA180=y
CONFIG_BMC150_ACCEL=y
CONFIG_QCOM_SPMI_IADC=y
CONFIG_QCOM_SPMI_VADC=y
CONFIG_QCOM_SPMI_ADC5=y
CONFIG_BMG160=y
CONFIG_INV_MPU6050_SPI=y
CONFIG_IIO_ST_LSM6DSX=y
CONFIG_LTR501=y
CONFIG_AK09911=y
CONFIG_BMC150_MAGN_I2C=y
CONFIG_PWM=y
CONFIG_QCOM_PDC=y
CONFIG_PHY_QCOM_PCIE2=y
CONFIG_PHY_QCOM_QMP=y
CONFIG_PHY_QCOM_QUSB2=y
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_QCOM_USB_HSIC=y
CONFIG_PHY_QCOM_USB_HS_28NM=y
CONFIG_POWERCAP=y
CONFIG_IDLE_INJECT=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_QCOM_QFPROM=y
CONFIG_NVMEM_SPMI_SDAM=y
CONFIG_SLIM_QCOM_CTRL=y
CONFIG_SLIM_QCOM_NGD_CTRL=y
CONFIG_INTERCONNECT=y
CONFIG_INTERCONNECT_QCOM=y
CONFIG_INTERCONNECT_QCOM_SDM660=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_COMPRESSION=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_QFMT_V1=y
CONFIG_QFMT_V2=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_OVERLAY_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_EXFAT_FS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_PSTORE=y
# CONFIG_PSTORE_DEFLATE_COMPRESS is not set
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
CONFIG_LSM="selinux"
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_842=y
CONFIG_CRYPTO_LZ4=y
CONFIG_CRYPTO_LZ4HC=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_DEV_QCOM_RNG=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_PANIC_TIMEOUT=5
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set

View file

@ -820,15 +820,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, 19200000);
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, 19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, 3, 19200000);
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, 19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6, 19200000);
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,
@ -841,12 +846,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,
@ -859,10 +874,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,
};
@ -872,14 +891,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, 19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, ln_bb_clk3_pin_a, 3, 19200000);
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,
@ -906,16 +920,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 = {
@ -924,8 +938,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,
@ -946,8 +960,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,
@ -995,8 +1009,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,
@ -1017,8 +1031,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,
@ -1038,8 +1052,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,
@ -1090,8 +1104,8 @@ DEFINE_CLK_SMD_RPM(qcm2290, bimc_gpu_clk, bimc_gpu_a_clk,
QCOM_SMD_RPM_MEM_CLK, 2);
static struct clk_smd_rpm *qcm2290_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,

View file

@ -2080,6 +2080,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,
},
},
@ -2220,6 +2221,7 @@ static struct clk_rcg2 hmss_gpll0_clk_src = {
.name = "hmss_gpll0_clk_src",
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.flags = CLK_IS_CRITICAL,
.ops = &clk_rcg2_ops,
},
};
@ -2833,6 +2835,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,
@ -2863,6 +2902,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,
@ -3036,12 +3095,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[] = {
@ -3191,6 +3255,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);
}

View file

@ -511,7 +511,7 @@ static struct clk_rcg2 byte0_clk_src = {
.parent_data = mmss_xo_dsibyte,
.num_parents = ARRAY_SIZE(mmss_xo_dsibyte),
.ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};
@ -524,7 +524,7 @@ static struct clk_rcg2 byte1_clk_src = {
.parent_data = mmss_xo_dsibyte,
.num_parents = ARRAY_SIZE(mmss_xo_dsibyte),
.ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};
@ -1075,7 +1075,7 @@ static struct clk_rcg2 pclk0_clk_src = {
.parent_data = mmss_xo_dsi0pll_dsi1pll,
.num_parents = ARRAY_SIZE(mmss_xo_dsi0pll_dsi1pll),
.ops = &clk_pixel_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};
@ -1089,7 +1089,7 @@ static struct clk_rcg2 pclk1_clk_src = {
.parent_data = mmss_xo_dsi0pll_dsi1pll,
.num_parents = ARRAY_SIZE(mmss_xo_dsi0pll_dsi1pll),
.ops = &clk_pixel_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};

View file

@ -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

View file

@ -111,7 +111,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

View file

@ -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,

View file

@ -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];

View file

@ -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");

View file

@ -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);
}

View file

@ -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,42 @@ 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,
.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,
@ -1106,6 +1383,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.
@ -1256,6 +1561,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},

View file

@ -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,

View file

@ -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;

View file

@ -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

View file

@ -1286,6 +1286,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", },

View file

@ -1038,13 +1038,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,
@ -1057,16 +1056,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 },
@ -1086,13 +1075,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,
@ -1108,8 +1096,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,
@ -1137,11 +1125,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 |
@ -1150,16 +1138,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 },
@ -1179,19 +1157,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,
@ -1206,7 +1184,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 = {
@ -1220,10 +1198,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,

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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
@ -272,6 +283,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
@ -416,6 +438,36 @@ config DRM_PANEL_SAMSUNG_S6D27A1
This panel can be found in Samsung Galaxy Ace 2
GT-I8160 mobile phone.
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
@ -580,6 +632,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

View file

@ -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
@ -25,6 +26,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
@ -41,6 +43,8 @@ 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_S6D27A1) += panel-samsung-s6d27a1.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
@ -59,6 +63,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

View 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");

View 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");

View 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");

View 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");

View file

@ -4187,6 +4187,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",
@ -4209,6 +4271,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 */
}

View 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");

View 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");

View 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");

View file

@ -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).

View file

@ -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

View file

@ -23,6 +23,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

View 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");

View file

@ -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

View file

@ -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

View 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>");

View file

@ -82,6 +82,14 @@ config RMI4_F12
touchpads. For sensors that support relative pointing, F12 also
provides mouse input.
config RMI4_F1A
bool "RMI4 Function 1A (Simple capacitive buttons)"
depends on OF
help
Say Y here if you want to add support for RMI4 function 1A.
Function 1A provides GPIO capacitive button support for RMI4 devices.
config RMI4_F30
bool "RMI4 Function 30 (GPIO LED)"
help

View file

@ -8,6 +8,7 @@ rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
rmi_core-$(CONFIG_RMI4_F1A) += rmi_f1a.o
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
rmi_core-$(CONFIG_RMI4_F3A) += rmi_f3a.o

View file

@ -360,6 +360,9 @@ static struct rmi_function_handler *fn_handlers[] = {
#ifdef CONFIG_RMI4_F12
&rmi_f12_handler,
#endif
#ifdef CONFIG_RMI4_F1A
&rmi_f1a_handler,
#endif
#ifdef CONFIG_RMI4_F30
&rmi_f30_handler,
#endif

View file

@ -133,6 +133,7 @@ extern struct rmi_function_handler rmi_f01_handler;
extern struct rmi_function_handler rmi_f03_handler;
extern struct rmi_function_handler rmi_f11_handler;
extern struct rmi_function_handler rmi_f12_handler;
extern struct rmi_function_handler rmi_f1a_handler;
extern struct rmi_function_handler rmi_f30_handler;
extern struct rmi_function_handler rmi_f34_handler;
extern struct rmi_function_handler rmi_f3a_handler;

View file

@ -0,0 +1,180 @@
// FIXME: Too much stuff is hardcoded in currently!
#include <linux/input.h>
#include <linux/rmi.h>
#include <linux/of.h>
#include "rmi_driver.h"
/* Query 1 */
//#define F1A_BUTTONS_COUNT 0b00011111 /* BIT(1) */
#define MAX_NAME_LEN 256
#define F1A_MAX_BUTTONS 8
struct f1a_data {
struct rmi_function *fn;
unsigned char button_count;
u32 button_map[F1A_MAX_BUTTONS];
struct input_dev *input;
char input_name[MAX_NAME_LEN];
char input_phys[MAX_NAME_LEN];
u8 button_data_buffer;
};
static int rmi_f1a_initialize(struct f1a_data *f1a)
{
struct rmi_function *fn = f1a->fn;
struct device *dev = &fn->dev;
//u8 query[2];
int error;
/*error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr, query, 2);
if (error) {
dev_err(dev, "Failed to read query register (%d).\n", error);
return error;
}
printk("%s: query0: 0x%x, query1: 0x%x\n", __func__, query[0], query[1]);*/
error = of_property_read_variable_u32_array(dev_of_node(dev),
"syna,codes", f1a->button_map, 1, F1A_MAX_BUTTONS);
if (error < 0) {
dev_err(dev, "Failed to parse syna,codes from OF device tree (%d).\n", error);
return error;
}
// FIXME: button_count = query[1] & F1A_BUTTONS_COUNT;
f1a->button_count = 0;
for (f1a->button_count = 0; f1a->button_count < F1A_MAX_BUTTONS; f1a->button_count++)
if (f1a->button_map[f1a->button_count] == 0)
break;
rmi_dbg(RMI_DEBUG_FN, dev, "%s: %d button codes defined\n", __func__, f1a->button_count);
return 0;
}
static int rmi_f1a_register_device(struct f1a_data *f1a)
{
struct rmi_function *fn = f1a->fn;
struct device *dev = &fn->dev;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct input_dev *input_dev;
int i, rc;
input_dev = input_allocate_device();
if (!input_dev) {
dev_err(dev, "Failed to allocate input device.\n");
return -ENOMEM;
}
f1a->input = input_dev;
snprintf(f1a->input_name, MAX_NAME_LEN, "%s.fn%02x",
dev_name(&rmi_dev->dev), fn->fd.function_number);
input_dev->name = f1a->input_name;
snprintf(f1a->input_phys, MAX_NAME_LEN, "%s/input0", input_dev->name);
input_dev->phys = f1a->input_phys;
input_dev->dev.parent = &rmi_dev->dev;
input_set_drvdata(input_dev, f1a);
/* set up any input events */
set_bit(EV_SYN, input_dev->evbit);
set_bit(EV_KEY, input_dev->evbit);
/* manage button map using input subsystem */
input_dev->keycode = f1a->button_map;
input_dev->keycodesize = sizeof(f1a->button_map); /* f1a->button_count */
input_dev->keycodemax = f1a->button_count;
/* set bits for each button */
for (i = 0; i < f1a->button_count; i++) {
set_bit(f1a->button_map[i], input_dev->keybit);
input_set_capability(input_dev, EV_KEY, f1a->button_map[i]);
}
rc = input_register_device(input_dev);
if (rc < 0) {
dev_err(dev, "Failed to register input device.\n");
goto error_free_device;
}
return 0;
error_free_device:
input_free_device(input_dev);
return rc;
}
static int rmi_f1a_probe(struct rmi_function *fn)
{
struct device *dev = &fn->dev;
struct f1a_data *f1a;
int error;
rmi_dbg(RMI_DEBUG_FN, dev, "%s\n", __func__);
f1a = devm_kzalloc(dev, sizeof(struct f1a_data), GFP_KERNEL);
if (!f1a)
return -ENOMEM;
f1a->fn = fn;
error = rmi_f1a_initialize(f1a);
if (error < 0)
return error;
error = rmi_f1a_register_device(f1a);
if (error < 0)
return error;
dev_set_drvdata(dev, f1a);
return 0;
}
static int rmi_f1a_config(struct rmi_function *fn)
{
fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
return 0;
}
static irqreturn_t rmi_f1a_attention(int irq, void *ctx)
{
struct rmi_function *fn = ctx;
struct device *dev = &fn->dev;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct f1a_data *f1a = dev_get_drvdata(dev);
int error, button;
// TODO: use rmi_read_block() to accomodate up to 8 buttons?
error = rmi_read(rmi_dev, fn->fd.data_base_addr, &(f1a->button_data_buffer));
if (error < 0) {
dev_err(dev, "Failed to read button data registers (%d).\n", error);
return error;
}
/*rmi_dbg(RMI_DEBUG_FN, dev, "%s: button_data=0x%x\n", __func__, f1a->button_data_buffer);*/
/* generate events for buttons that change state */
// TODO: Implement button_data_buffer as array + button_reg = button / 8
for (button = 0; button < f1a->button_count; button++) {
int button_shift;
bool button_status;
/* bit shift to get button's status */
button_shift = button % 8;
button_status = ((f1a->button_data_buffer >> button_shift) & 0x01) != 0;
rmi_dbg(RMI_DEBUG_FN, dev, "button %d (code %d) -> %d\n",
button, f1a->button_map[button], button_status);
/* generate an event here */
input_report_key(f1a->input, f1a->button_map[button], button_status);
}
input_sync(f1a->input); /* sync after groups of events */
return IRQ_HANDLED;
}
struct rmi_function_handler rmi_f1a_handler = {
.driver = {
.name = "rmi4_f1a",
},
.func = 0x1a,
.probe = rmi_f1a_probe,
.config = rmi_f1a_config,
.attention = rmi_f1a_attention,
};

View file

@ -638,6 +638,18 @@ config TOUCHSCREEN_MTOUCH
To compile this driver as a module, choose M here: the
module will be called mtouch.
config TOUCHSCREEN_NT36XXX
tristate "Novatek NT36XXX In-Cell I2C touchscreen controller"
depends on I2C
help
Say Y here if you have a Novatek NT36xxx series In-Cell
touchscreen connected to your system over I2C.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called nt36xxx.
config TOUCHSCREEN_IMX6UL_TSC
tristate "Freescale i.MX6UL touchscreen controller"
depends on ((OF && GPIOLIB) || COMPILE_TEST) && HAS_IOMEM

View file

@ -64,6 +64,7 @@ obj-$(CONFIG_TOUCHSCREEN_MMS114) += mms114.o
obj-$(CONFIG_TOUCHSCREEN_MSG2638) += msg2638.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
obj-$(CONFIG_TOUCHSCREEN_NT36XXX) += nt36xxx.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO) += ipaq-micro-ts.o

Some files were not shown because too many files have changed in this diff Show more