Compare commits

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

212 commits

Author SHA1 Message Date
Jami Kettunen
e9c309610d arm64: qcom: msm8998-oneplus-common: Drop unussed NFC suspend pinctrl 2021-11-09 14:45:47 +02:00
Jami Kettunen
aa0dfa5d16 arm64: qcom: msm8998-oneplus-common: Enable NFC 2021-11-01 06:13:48 +02:00
Jami Kettunen
d8db54ed3b module: demote ELF structure 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-11-01 06:13:48 +02:00
Stephen Boyd
85135b6dd5 ath10k: Don't always treat modem stop events as crashes
When rebooting on sc7180 Trogdor devices I see the following crash from
the wifi driver.

 ath10k_snoc 18800000.wifi: firmware crashed! (guid 83493570-29a2-4e98-a83e-70048c47669c)

This is because a modem stop event looks just like a firmware crash to
the driver, the qmi connection is closed in both cases. Use the qcom ssr
notifier block to stop treating the qmi connection close event as a
firmware crash signal when the modem hasn't actually crashed. See
ath10k_qmi_event_server_exit() for more details.

This silences the crash message seen during every reboot.

Fixes: 3f14b73c38 ("ath10k: Enable MSA region dump support for WCN3990")
Cc: Govind Singh <govinds@codeaurora.org>
Cc: Youghandhar Chintala <youghand@codeaurora.org>
Cc: Abhishek Kumar <kuabhs@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Tested-By: Steev Klimaszewski <steev@kali.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
2021-11-01 06:13:48 +02:00
Jami Kettunen
39294c71d0 arm64: oneplus5_defconfig: Enable rest of LED triggers 2021-11-01 06:13:47 +02:00
Jami Kettunen
8948f5c05d TEMP: oneplus5: disable all speaker amp stuff
We don't want to blow this up while messing around with audio stuff
early on...
2021-11-01 06:13:47 +02:00
Jami Kettunen
ee15712244 arm64: dts: msm8998-oneplus-common: Add TFA9890 speaker amp bindings 2021-11-01 06:13:47 +02:00
Jami Kettunen
68a902fe55 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-11-01 06:13:47 +02:00
Jami Kettunen
76e224dc98 arm64: (msm8998|oneplus5)_defconfig: Enable SND_SOC_MSM8998 2021-11-01 06:13:47 +02:00
Jami Kettunen
6517d9007b FIXUP: oneplus5_defconfig: update for 5.14 2021-11-01 06:13:47 +02:00
Jami Kettunen
1b236d1075 arm64: msm8998_defconfig: Enable OnePlus 5/5T panels 2021-11-01 06:13:47 +02:00
Jami Kettunen
5de8b284f8 arm64: oneplus5_defconfig: Add from .config 2021-11-01 06:13:47 +02:00
Jami Kettunen
7646d0f7f1 arm64: dts: qcom: msm8998-oneplus-common: Enable PMI8998 LPG leds
Now the RGB notification LEDs can each be controlled individually :)
2021-11-01 06:13:47 +02:00
Jami Kettunen
a924a833d0 msm8998-oneplus-common: Configure Adreno 540 GPU 2021-11-01 06:13:47 +02:00
Jami Kettunen
5d5c508d47 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-11-01 06:13:47 +02:00
Jami Kettunen
8a0a87c923 msm8998-oneplus-common: Configure IPA for cellular data 2021-11-01 06:13:47 +02:00
Jami Kettunen
393cd16f3a msm8998-oneplus-common: Configure PMI8998 fuel gauge for battery info 2021-11-01 06:13:47 +02:00
Jami Kettunen
e1033dcc0e msm8998-oneplus-common: Configure CPUfreq scaling hardware 2021-11-01 06:13:47 +02:00
Jami Kettunen
b6ee419de4 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-11-01 06:13:47 +02:00
Jami Kettunen
f548d786a8 msm8998-oneplus-common: Add remoteproc configuration & enable WLAN 2021-11-01 06:13:47 +02:00
Jami Kettunen
332ec26e7b msm8998-oneplus-common: Configure blsp1_i2c5_sleep (TS) as no-pull 2021-11-01 06:13:47 +02:00
Jami Kettunen
9f4ffb9a9c 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-11-01 06:13:47 +02:00
Jami Kettunen
ed101b0949 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-11-01 06:13:46 +02:00
Jami Kettunen
fa8171e920 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-11-01 06:13:46 +02:00
Jami Kettunen
122ab67613 [ANNOTATION] Apply some F(x)tec Pro1 patches 2021-11-01 06:13:46 +02:00
Jami Kettunen
945e0f5efc FIXUP: msm8998_defconfig: update for 5.14 2021-11-01 06:13:46 +02:00
Jami Kettunen
6fca65ccb0 arm64: msm8998_defconfig: Add from .config
This is meant to be a more generic MSM8998 defconfig compared to the
OnePlus 5 one which also drops e.g. MMC support and such which aren't
present on the device.
2021-11-01 06:13:46 +02:00
Danct12
859a1ae388 arm64: dts: msm8998-fxtec-pro1: Add remoteproc configuration 2021-11-01 06:13:46 +02:00
Danct12
41179d35fb arm64: dts: msm8998-fxtec-pro1: Enable PMI8998 haptics 2021-11-01 06:13:46 +02:00
Danct12
57c7528f8c arm64: dts: msm8998-fxtec-pro1: Configure PMI8998 fuel gauge
This will account for battery statistics reporting on the Fxtec Pro1 (QX1000)
2021-11-01 06:13:46 +02:00
Danct12
23a6de947e FIXUP: arm64: dts: msm8998-fxtec-pro1: Fix volume down button compatible 2021-11-01 06:13:46 +02:00
Jami Kettunen
ac057abd31 [ANNOTATION] Apply miscellaneous hacks and patches 2021-11-01 06:13:46 +02:00
Jami Kettunen
694be6adcd 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-11-01 06:13:46 +02:00
Jami Kettunen
ea6b8af19e arm64: dts: qcom: msm8998: add IPA information
Add support for the MSM8998 SoC, which includes IPA version 3.1.
2021-11-01 06:13:46 +02:00
Jami Kettunen
42b3371dfa power: supply: qcom_fg: Report online property 2021-11-01 06:13:46 +02:00
Jami Kettunen
986190113f drm/msm: Mention DSI 10nm PHY support for MSM8998 2021-11-01 06:13:46 +02:00
Jami Kettunen
d2e6912f20 dt-bindings: Document bindings for all MSM8998 devices 2021-11-01 06:13:46 +02:00
Jami Kettunen
054ad80080 [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-11-01 06:13:46 +02:00
Jami Kettunen
c70f833efa [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-11-01 06:13:46 +02:00
Jami Kettunen
b608dfd547 [ANNOTATION] Apply WIP "Qualcomm SPMI Fuel Gauge" patches
https://gitlab.com/sdm845-mainline/linux/-/commits/driver/pmi8998_fg/
2021-11-01 06:13:46 +02:00
Yassine Oudjana
dffa02cc2a arm64: dts: qcom: pmi8994: Add fuel gauge 2021-11-01 06:13:46 +02:00
Yassine Oudjana
a33fd4351b 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-11-01 06:13:46 +02:00
Yassine Oudjana
0953d76319 power: pmi8998_fg: Remove some trailing spaces and tabs
This should be squashed.
2021-11-01 06:13:45 +02:00
Joel Selvaraj
804dea4ce6 arm64: dts: qcom: sdm845-oneplus: enable pmi8998 fuel guage
Enable the new pmi8998 fuel gauge

Signed-off-by: Caleb Connolly <caleb@connolly.tech>
2021-11-01 06:13:45 +02:00
Joel Selvaraj
68229c25b8 fg: clean and read charge full and max voltage from dts 2021-11-01 06:13:45 +02:00
Joel Selvaraj
bed14a3bb9 power: supply: add battery charging status feature 2021-11-01 06:13:45 +02:00
Joel Selvaraj
41531113f2 arm64: dts: qcom: pmi8998: Add nodes for pmi8998 fuel guage 2021-11-01 06:13:45 +02:00
Joel Selvaraj
ea5b58fcdf power: supply: introduce pmi8998 fuel guage driver 2021-11-01 06:13:45 +02:00
Jami Kettunen
ae78fc1d7e [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-11-01 06:13:45 +02:00
Jami Kettunen
b48f513acf 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-11-01 06:13:45 +02:00
Joel Selvaraj
b6492e810e 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-11-01 06:13:45 +02:00
Caleb Connolly
25f251ea49 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-11-01 06:13:45 +02:00
Caleb Connolly
600576bd13 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-11-01 06:13:45 +02:00
Caleb Connolly
9040d9932a 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-11-01 06:13:45 +02:00
Caleb Connolly
80280ab41e 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-11-01 06:13:45 +02:00
Jami Kettunen
ca7ae55c48 [ANNOTATION] Various patches from SoMainline trees & LKML 2021-11-01 06:13:45 +02:00
Junak
0d15a5ef69 drm: msm: mdp5: improve command-mode panel support 2021-11-01 06:13:45 +02:00
Jami Kettunen
5200e0ea04 [ANNOTATION] Base @ angelo/5.14-msm8998-audio-working
I also rebased this tree on the linus/v5.14 tag.
2021-11-01 06:13:45 +02:00
AngeloGioacchino Del Regno
103686b10c nt35950: partial marijn review 2021-11-01 06:13:45 +02:00
AngeloGioacchino Del Regno
cba6ccd255 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-11-01 06:13:45 +02:00
AngeloGioacchino Del Regno
5f9d2ce95d nt35950: final 2021-11-01 06:13:45 +02:00
AngeloGioacchino Del Regno
09588133d4 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>
2021-11-01 06:13:45 +02:00
AngeloGioacchino Del Regno
10df41f3a6 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-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
04285e416b adreno 5xx: TTBR1 extravaganza on MSM8998 2021-11-01 06:13:44 +02:00
Marijn Suijten
5b142a5515 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-11-01 06:13:44 +02:00
Marijn Suijten
8ed17fc2f4 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-11-01 06:13:44 +02:00
Marijn Suijten
af4b70fff2 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-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
aaa397f95a various tests 2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
ac4ea80c8c 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-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
a6d0e33c3f 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-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
74eacc6b50 AUDIO WORKS 2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
055b21d3cf ASoC: codecs: wcd9335: Fix headphone jack commit for new upstream kernel 2021-11-01 06:13:44 +02:00
Srinivas Kandagatla
8388111622 ASoC: wcd9335: add mbhc support
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
989cb3490b Revert "wcd9335 garbage"
This reverts commit d1f50ba3a4b33c98162c4b202d4c154d4ab22689.
2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
eb54959b93 stuff 2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
99098ac658 wcd9335 garbage 2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
7b4567cebc 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-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
672fd7d815 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-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
6453ef9313 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>
2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
63f8961563 iommu-qcom: re-enable resetting contexts 2021-11-01 06:13:44 +02:00
AngeloGioacchino Del Regno
c106837527 dt-bindings: lpass clocks fix 2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
925130181f 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
776cec534a 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
d906a0bdc2 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
b6059252cb 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
bd5d3e1fb4 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
9caf508f3a 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
29aeb2c98f 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
61412ac5b5 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
5dc7c1e48d adreno-smmu.... 2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
b67ca04aa0 yoshino: Fix too high overheating backlight, enable all wled strings maple 2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
7de41ec0b9 working everything and touch ok - but with iommu hack 2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
7dc94830d3 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
c5c1c3eb35 dpu fixup 2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
4d7e1ead3b fastmatrix yaml fix 2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
839d50f0a1 drm/msm/dsi_phy_10nm: Fix bad VCO rate calculation 2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
4f0d4b7061 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-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
dc02fca014 clk: qcom: gcc-msm8998: Set MISC flags, mark hmss/gpu-ahb critical
It is being evaluated whether this commit is really needed.
DONOTUPSTREAM.
2021-11-01 06:13:43 +02:00
AngeloGioacchino Del Regno
df2301f33e 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
2eb5e6adb5 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
f2689a3ccc 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
49185f9466 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
e82d3a0bb1 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
6f697fc063 media: dt-bindings: media: venus: Add sdm660 DT schema
Add new qcom,sdm660-venus DT binding schema.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
ecfb13285d 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
4ad208b26f 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
b74746724f 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-11-01 06:13:42 +02:00
Konrad Dybcio
c0287eb905 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
77aec8f806 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
2c1bb0a77e 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
153366a6f5 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
75eb1f0a6b 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
50f5ca35f9 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
f7eba7b59e 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
dc3e650ce1 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-11-01 06:13:42 +02:00
AngeloGioacchino Del Regno
632174d48a 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
3b3668af63 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
22227d74fd 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>
2021-11-01 06:13:41 +02:00
Konrad Dybcio
3fbf48ec45 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")
2021-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
8580c66f3c 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
0e156db800 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
fe7b8b61c6 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
ed5d4496d7 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
eec3b9f699 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
02524dfa62 arm64: dts: qcom: Add support for MSM8998 F(x)tec Pro1 QX1000
Add device tree support for the F(x)tec Pro 1 (QX1000) smartphone.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
76fb26265f arm64: dts: msm8998: Configure Adreno GPU and related IOMMU
The MSM8998 SoC includes an Adreno 540.1 GPU, with a maximum frequency
of 710MHz. This GPU may or may not accept a ZAP shader, depending on
platform configuration, so adding a zap-shader node is left to the
board DT.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:41 +02:00
Konrad Dybcio
5abec5d77e arm64: dts: qcom: pm8998: Add VREF_1P25 and REF_GND VADC channels
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
3851b91c8f 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
bf8ab5ac8d 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
309939ed8a arm64: dts: msm8998: Move qfprom iospace to calibrated values
The QFPROM iospace was (erroneously, I believe) set to the uncalibrated
fuse start address, but every driver only needs - and will always only
need - only calibrated values.

Move the iospace forward to the calibrated values start to avoid
offsetting every fuse definition.
Obviously, the only defined fuse (qusb2_hstx_trim) was also fixed to
remove the offset, in order to comply with this change.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
40e0553a6d arm64: dts: msm8998: Fix CPU/L2 idle state latency and residency
The entry/exit latency and minimum residency in state for the idle
states of MSM8998 were ..bad: first of all, for all of them the
timings were written for CPU sleep but the min-residency-us param
was miscalculated (supposedly, while porting this from downstream);
Then, the power collapse states are setting PC on both the CPU
cluster *and* the L2 cache, which have different timings: in the
specific case of L2 the times are higher so these ones should be
taken into account instead of the CPU ones.

This parameter misconfiguration was not giving particular issues
because on MSM8998 there was no CPU scaling at all, so cluster/L2
power collapse was rarely (if ever) hit.
When CPU scaling is enabled, though, the wrong timings will produce
SoC unstability shown to the user as random, apparently error-less,
sudden reboots and/or lockups.

This set of parameters are stabilizing the SoC when CPU scaling is
ON and when power collapse is frequently hit.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
497945318d 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-11-01 06:13:41 +02:00
AngeloGioacchino Del Regno
b92c738248 arm64: dts: msm8998: Configure the multimedia subsystem iommu
In preparation for enabling various components of the multimedia
subsystem, write configuration for its related IOMMU.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
673461e76a arm64: dts: msm8998: Configure the MultiMedia Clock Controller (MMCC)
The MSM8998 MMCC is supported and has a driver: configure it as a
preparation for a later enablement of multimedia nodes (mdp, venus
and others).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
85a24731ff arm64: dts: qcom: Introduce support for MSM8998 Sony Yoshino platform
This commit introduces support for the Sony Yoshino platform, using
the MSM8998 SoC, including:
- Sony Xperia XZ1 (codename Poplar),
- Sony Xperia XZ1 Compact (codename Lilac),
- Sony Xperia XZ Premium (codename Maple).

All of the three aforementioned smartphones are sharing a 99%
equal board configuration, with very small differences between
each other, which is the reason for the introduction of a common
msm8998-sony-xperia-yoshino DT.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
636e73b34e 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
0670a85109 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
acf7cceaf4 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
b845614d93 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
e9fe4aa5da 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
54cffae709 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
3cf0279920 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
f67d486afc 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
5691e1fe7d 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
01a24161e1 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
804f95c769 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-11-01 06:13:40 +02:00
AngeloGioacchino Del Regno
1199c5a501 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-11-01 06:13:40 +02:00
Manivannan Sadhasivam
2bc4ab0787 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-11-01 06:13:40 +02:00
Manivannan Sadhasivam
f5514fdd59 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
0b5e268a0d 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
567ae59295 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
848a1bbf75 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
f7add98021 dt-bindings: soc: qcom: spm: Document SDM660 and MSM8998 compatibles
The driver was updated to add SAW2 v4.1 support for new SoCs: document
the new compatibles.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
441ab88ea6 soc: qcom: spm: Add compatible for MSM8998 SAWv4.1 L2
Add the SAWv4.1 parameters for MSM8998's Gold and Silver clusters.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Reviewed-by: Stephan Gerhold <stephan@gerhold.net>
2021-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
f4d9f13eb7 soc: qcom: spm: Implement support for SAWv4.1, SDM630/660 L2 AVS
Implement the support for SAW v4.1, used in at least MSM8998,
SDM630, SDM660 and APQ variants and, while at it, also add the
configuration for the SDM630/660 Silver and Gold cluster L2
Adaptive Voltage Scaler: this is also one of the prerequisites
to allow the OSM controller to perform DCVS.

Please note that despite there are various "versions" of these
values downstream, these are the only ones that are perfectly
stable on the entire set of tested devices.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Reviewed-by: Stephan Gerhold <stephan@gerhold.net>
2021-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
8d6b6e3078 dt-bindings: soc: qcom: Add devicetree binding for QCOM SPM
Add devicetree binding for Qualcomm Subsystem Power Manager (SPM).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
2021-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
e113e17634 cpuidle: qcom_spm: Detach state machine from main SPM handling
In commit a871be6b8e ("cpuidle: Convert Qualcomm SPM driver to a generic
CPUidle driver") the SPM driver has been converted to a
generic CPUidle driver: that was mainly made to simplify the
driver and that was a great accomplishment;
Though, at that time, this driver was only applicable to ARM 32-bit SoCs,
lacking logic about the handling of newer generation SAW.

In preparation for the enablement of SPM features on AArch64/ARM64,
split the cpuidle-qcom-spm driver in two: the CPUIdle related
state machine (currently used only on ARM SoCs) stays there, while
the SPM communication handling lands back in soc/qcom/spm.c and
also making sure to not discard the simplifications that were
introduced in the aforementioned commit.

Since now the "two drivers" are split, the SCM dependency in the
main SPM handling is gone and for this reason it was also possible
to move the SPM initialization early: this will also make sure that
whenever the SAW CPUIdle driver is getting initialized, the SPM
driver will be ready to do the job.

Please note that the anticipation of the SPM initialization was
also done to optimize the boot times on platforms that have their
CPU/L2 idle states managed by other means (such as PSCI), while
needing SAW initialization for other purposes, like AVS control.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Reviewed-by: Stephan Gerhold <stephan@gerhold.net>
Tested-by: Stephan Gerhold <stephan@gerhold.net>
2021-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
534226dd92 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
1b3bf3b1ce 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
59598b642c 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
44fde9148e 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
b766d992cd 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
76330e01e0 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-11-01 06:13:39 +02:00
AngeloGioacchino Del Regno
b3bad314cd 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-11-01 06:13:39 +02:00
Marijn Suijten
28337278f5 qcom-lpg: Review fixups! 2021-11-01 06:13:39 +02:00
Marijn Suijten
86f859fc4b leds: qcom-lpg: Add PM660L 2021-11-01 06:13:39 +02:00
Marijn Suijten
9a151a1e8d NILE/pm660l: LPG 2021-11-01 06:13:38 +02:00
Marijn Suijten
4419531c3d defconfig: Leds, QCOM_LPG, and all the led triggers! 2021-11-01 06:13:38 +02:00
Bjorn Andersson
4ddfcc0a10 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>
2021-11-01 06:13:38 +02:00
Bjorn Andersson
2b7bfae14a 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-11-01 06:13:38 +02:00
Bjorn Andersson
1bdbb50dd5 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-11-01 06:13:38 +02:00
Bjorn Andersson
3a24655b15 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>
2021-11-01 06:13:38 +02:00
Bjorn Andersson
25281c8b70 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-11-01 06:13:38 +02:00
Bjorn Andersson
0b099e0d7e 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-11-01 06:13:38 +02:00
Marijn Suijten
e6dc461e83 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-11-01 06:13:38 +02:00
Marijn Suijten
b2a234e861 FIXUP: simple-panel: add missing connector_type! 2021-11-01 06:13:38 +02:00
Marijn Suijten
4121e0bc1c android-recommended lies: AIO is needed for adb :| 2021-11-01 06:13:38 +02:00
Marijn Suijten
645c2d229c PANEL INNOLUX FIXUP!: Use set_tear_on for VBLANK instead of magic const 2021-11-01 06:13:38 +02:00
Marijn Suijten
3b2ed60056 gpu go 700mhz 2021-11-01 06:13:38 +02:00
Marijn Suijten
3f134d4eab sdm630: Add missing zap-shader! 2021-11-01 06:13:38 +02:00
Marijn Suijten
ad3c1d83ab nile: Turn on pm660l_wled to not -EPROBE_DEFER the panel 2021-11-01 06:13:38 +02:00
Marijn Suijten
80d6ecc10a defconfig: Disco panel! 2021-11-01 06:13:38 +02:00
Marijn Suijten
345e2402f9 DISCO PANELS?!?!? 2021-11-01 06:13:38 +02:00
Marijn Suijten
9deca0ad10 PANELS TODO FINISHME: use dev_err_probe in _probe! 2021-11-01 06:13:38 +02:00
Konrad Dybcio
7ed205734a arm64: dts: qcom: sdm63*-xperia: Add display panels
Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
2021-11-01 06:13:37 +02:00
Marijn Suijten
e5b76990e8 arm64: defconfig: Disable legacy USB networking in favour of configfs
Otherwise adb cannot get itself up
2021-11-01 06:13:37 +02:00
Marijn Suijten
84f338c4d3 630: Also system part, root fstab not found 2021-11-01 06:13:37 +02:00
Marijn Suijten
c6fea63d41 bye slotselect 2021-11-01 06:13:37 +02:00
Marijn Suijten
4835b657d6 defconfig: a508 zap, a530 firmware 2021-11-01 06:13:37 +02:00
Marijn Suijten
d492687bfa Adreno firmware in .c file; vendor DT 2021-11-01 06:13:37 +02:00
Marijn Suijten
0b8a882b92 bye framebuffer and sdhc_2 2021-11-01 06:13:37 +02:00
Marijn Suijten
be3b2acd0d defconfig: Interconnect 2021-11-01 06:13:37 +02:00
Marijn Suijten
93af1dbe3e nile: Enable gpucc 2021-11-01 06:13:37 +02:00
Marijn Suijten
f5bd27247f defconfig; MMCC and GPUCC 660 2021-11-01 06:13:37 +02:00
Marijn Suijten
8f263ba951 Android defconfig
cat
    ../../configs/r/android-5.4/android-{base,recommended,recommended-arm64}.config
    >> arch/arm64/configs/defconfig
2021-11-01 06:13:37 +02:00
Marijn Suijten
328f064e3a 660 defconfig
[Fixed up for 5.15 by Jami]
2021-11-01 06:13:37 +02:00
Konrad Dybcio
f71ea3441b 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-11-01 06:13:37 +02:00
Konrad Dybcio
1e696c47d1 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>
2021-11-01 06:13:37 +02:00
AngeloGioacchino Del Regno
0fde91e372 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-11-01 06:13:37 +02:00
Konrad Dybcio
e7523b153d 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-11-01 06:13:37 +02:00
Konrad Dybcio
b4e0021277 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-11-01 06:13:37 +02:00
Konrad Dybcio
914ee6b355 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-11-01 06:13:37 +02:00
Konrad Dybcio
8796032540 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-11-01 06:13:37 +02:00
Konrad Dybcio
f286ad3039 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-11-01 06:13:36 +02:00
Konrad Dybcio
c783b6740a 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-11-01 06:13:36 +02:00
Konrad Dybcio
ffdad2e91a 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-11-01 06:13:36 +02:00
Konrad Dybcio
95faea9235 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-11-01 06:13:36 +02:00
Konrad Dybcio
95d7ebbcf1 drivers: interconnect: qcom: sdm660: Adjust to v5.10 changes
Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org>
2021-11-01 06:13:36 +02:00
Konrad Dybcio
ee785e6e99 drivers: interconnect: sdm660: MASTER_CRYPTO_C0 isn't AP-Owned
Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
2021-11-01 06:13:36 +02:00
AngeloGioacchino Del Regno
3e6dad1592 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-11-01 06:13:36 +02:00
AngeloGioacchino Del Regno
6ee5bcdadf 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-11-01 06:13:36 +02:00
Konrad Dybcio
ab59ed04c6 arm64: dts: qcom: sdm630: Fix intc reg indentation
Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
2021-11-01 06:13:36 +02:00
161 changed files with 49167 additions and 2236 deletions

5768
CONF Normal file

File diff suppressed because it is too large Load diff

View file

@ -297,6 +297,12 @@ properties:
* arm/msm/qcom,kpss-acc.txt
qcom,freq-domain:
$ref: '/schemas/types.yaml#/definitions/phandle-array'
description: |
CPUs supporting freq-domain must set their "qcom,freq-domain" property
with phandle to a cpufreq_hw node followed by the Domain ID(0/1).
rockchip,pmu:
$ref: '/schemas/types.yaml#/definitions/phandle'
description: |

View file

@ -40,6 +40,7 @@ description: |
sa8155p
sc7180
sc7280
msm8998
sdm630
sdm660
sdm845
@ -194,6 +195,16 @@ properties:
- google,senor
- const: qcom,sc7280
- items:
- enum:
- asus,novago-tp370ql
- hp,envy-x2
- lenovo,miix-630
- oneplus,cheeseburger
- oneplus,dumpling
- qcom,msm8998-mtp
- const: qcom,msm8998
- items:
- enum:
- xiaomi,lavender

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,164 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Venus video encode and decode accelerators
maintainers:
- Stanimir Varbanov <stanimir.varbanov@linaro.org>
description: |
The Venus IP is a video encode and decode accelerator present
on Qualcomm platforms
properties:
compatible:
const: qcom,sdm660-venus
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 5
clock-names:
items:
- const: core
- const: iface
- const: bus
- const: bus_throttle
- const: vcodec0_core
interconnects:
maxItems: 2
interconnect-names:
items:
- const: video-mem
- const: cpu-cfg
iommus:
maxItems: 20
memory-region:
maxItems: 1
power-domains:
minItems: 3
power-domain-names:
items:
- const: cx
- const: vcodec0
- const: venus
video-decoder:
type: object
properties:
compatible:
const: venus-decoder
required:
- compatible
additionalProperties: false
video-encoder:
type: object
properties:
compatible:
const: venus-encoder
required:
- compatible
additionalProperties: false
video-firmware:
type: object
description: |
Firmware subnode is needed when the platform does not
have TrustZone.
properties:
iommus:
maxItems: 2
required:
- iommus
required:
- compatible
- reg
- interrupts
- power-domains
- power-domain-names
- clocks
- clock-names
- iommus
- memory-region
- video-decoder
- video-encoder
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,mmcc-sdm660.h>
#include <dt-bindings/power/qcom-rpmpd.h>
video-codec@cc00000 {
compatible = "qcom,sdm660-venus";
reg = <0x0cc00000 0xff000>;
interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&rpmpd SDM660_VDDCX>,
<&mmcc VENUS_CORE0_GDSC>,
<&mmcc VENUS_GDSC>;
power-domain-names = "cx", "vcodec0", "venus";
clocks = <&mmcc VIDEO_CORE_CLK>,
<&mmcc VIDEO_AHB_CLK>,
<&mmcc VIDEO_AXI_CLK>,
<&mmcc THROTTLE_VIDEO_AXI_CLK>,
<&mmcc VIDEO_SUBCORE0_CLK>;
clock-names = "core", "iface", "bus", "bus_throttle",
"vcodec0_core";
iommus = <&mmss_smmu 0x400>,
<&mmss_smmu 0x401>,
<&mmss_smmu 0x40a>,
<&mmss_smmu 0x407>,
<&mmss_smmu 0x40e>,
<&mmss_smmu 0x40f>,
<&mmss_smmu 0x408>,
<&mmss_smmu 0x409>,
<&mmss_smmu 0x40b>,
<&mmss_smmu 0x40c>,
<&mmss_smmu 0x40d>,
<&mmss_smmu 0x410>,
<&mmss_smmu 0x421>,
<&mmss_smmu 0x428>,
<&mmss_smmu 0x429>,
<&mmss_smmu 0x42b>,
<&mmss_smmu 0x42c>,
<&mmss_smmu 0x42d>,
<&mmss_smmu 0x411>,
<&mmss_smmu 0x431>;
memory-region = <&venus_region>;
video-decoder {
compatible = "venus-decoder";
};
video-encoder {
compatible = "venus-encoder";
};
};

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

@ -0,0 +1,80 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/soc/qcom/qcom,spm.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Subsystem Power Manager binding
maintainers:
- Andy Gross <agross@kernel.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
This binding describes the Qualcomm Subsystem Power Manager, used to control
the peripheral logic surrounding the application cores in Qualcomm platforms.
properties:
compatible:
items:
- enum:
- qcom,sdm660-gold-saw2-v4.1-l2
- qcom,sdm660-silver-saw2-v4.1-l2
- qcom,msm8998-gold-saw2-v4.1-l2
- qcom,msm8998-silver-saw2-v4.1-l2
- qcom,msm8226-saw2-v2.1-cpu
- qcom,msm8974-saw2-v2.1-cpu
- qcom,apq8084-saw2-v2.1-cpu
- qcom,apq8064-saw2-v1.1-cpu
- const: qcom,saw2
reg:
description: Base address and size of the SPM register region
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
/* Example 1: SoC using SAW2 and kpss-acc-v2 CPUIdle */
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "qcom,kryo";
device_type = "cpu";
enable-method = "qcom,kpss-acc-v2";
qcom,saw = <&saw0>;
reg = <0x0>;
operating-points-v2 = <&cpu_opp_table>;
};
};
saw0: power-manager@f9089000 {
compatible = "qcom,msm8974-saw2-v2.1-cpu", "qcom,saw2";
reg = <0xf9089000 0x1000>;
};
- |
/*
* Example 2: New-gen multi cluster SoC using SAW only for L2;
* This does not require any cpuidle driver, nor any cpu phandle.
*/
power-manager@17812000 {
compatible = "qcom,msm8998-gold-saw2-v4.1-l2", "qcom,saw2";
reg = <0x17812000 0x1000>;
};
power-manager@17912000 {
compatible = "qcom,msm8998-silver-saw2-v4.1-l2", "qcom,saw2";
reg = <0x17912000 0x1000>;
};
...

View file

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

View file

@ -15490,9 +15490,15 @@ M: Niklas Cassel <nks@flawful.org>
L: linux-pm@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr.yaml
F: drivers/soc/qcom/cpr.c
QUALCOMM CORE POWER REDUCTION v3/v4/Hardened AVS DRIVER
M: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
S: Maintained
F: Documentation/devicetree/bindings/soc/qcom/qcom,cpr3.yaml
F: drivers/soc/qcom/cpr3.c
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
M: Ilia Lin <ilia.lin@kernel.org>
L: linux-pm@vger.kernel.org
@ -17458,6 +17464,13 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/imx290.txt
F: drivers/media/i2c/imx290.c
SONY IMX300 SENSOR DRIVER
M: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/sony,imx300.yaml
F: drivers/media/i2c/imx300.c
SONY IMX319 SENSOR DRIVER
M: Bingbu Cao <bingbu.cao@intel.com>
L: linux-media@vger.kernel.org

View file

@ -34,11 +34,15 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-dora.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-kagura.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-keyaki.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-asus-novago-tp370ql.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-fxtec-pro1.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-hp-envy-x2.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-lenovo-miix-630.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-oneplus-cheeseburger.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-oneplus-dumpling.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-lilac.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-maple.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb
@ -74,6 +78,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-pioneer.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-voyager.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm636-sony-xperia-ganges-mermaid.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm660-xiaomi-lavender.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm660-xiaomi-platina.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r3.dtb

View file

@ -8,6 +8,7 @@
#include "pmi8994.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
@ -695,6 +696,54 @@
};
};
&pmi8994_lpg {
qcom,power-source = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmi8994_mpp2_userled4>;
qcom,dtest = <0 0
0 0
0 0
4 1>;
status = "okay";
led@1 {
reg = <1>;
label = "green:user1";
linux,default-trigger = "heartbeat";
default-state = "on";
};
led@2 {
reg = <2>;
label = "green:user0";
default-state = "on";
};
led@3 {
reg = <3>;
label = "green:user2";
};
led@4 {
reg = <4>;
label = "green:user3";
};
};
&pmi8994_mpps {
pmi8994_mpp2_userled4: mpp2-userled4-state {
pins = "mpp2";
function = "sink";
output-low;
qcom,dtest = <4>;
};
};
&pmi8994_spmi_regulators {
vdd_gfx: s2@1700 {
reg = <0x1700 0x100>;

View file

@ -0,0 +1,682 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2021, AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
*/
/dts-v1/;
#include "msm8998-mtp.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
/ {
model = "F(x)tec Pro1 (QX1000)";
compatible = "fxtec,pro1", "qcom,msm8998";
qcom,board-id = <0x02000b 0x10>;
/* This part enables graphical output via bootloader-enabled display */
chosen {
bootargs = "earlycon=tty0 console=tty0 clk_ignore_unused";
#address-cells = <2>;
#size-cells = <2>;
ranges;
};
reserved-memory {
cont_splash_mem: cont-splash-region@9d400000 {
reg = <0x0 0x9d400000 0x0 0x2000000>;
no-map;
};
zap_shader_region: gpu@f6400000 {
compatible = "shared-dma-pool";
reg = <0x0 0xf6400000 0x0 0x2000>;
no-map;
};
ramoops@ffc00000 {
compatible = "ramoops";
reg = <0x0 0xffc00000 0x0 0x100000>;
record-size = <0x10000>;
console-size = <0x60000>;
ftrace-size = <0x10000>;
pmsg-size = <0x20000>;
ecc-size = <16>;
status = "okay";
};
};
keyboard-leds {
compatible = "gpio-leds";
backlight {
color = <LED_COLOR_ID_WHITE>;
default-state = "off";
function = LED_FUNCTION_KBD_BACKLIGHT;
gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>;
label = "white:kbd_backlight";
retain-state-suspended;
};
caps-lock {
color = <LED_COLOR_ID_YELLOW>;
default-state = "off";
function = LED_FUNCTION_CAPSLOCK;
gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>;
label = "yellow:capslock";
linux,default-trigger = "kbd-capslock";
};
};
gpio_keyboard: gpio-keyboard {
compatible = "gpio-fastmatrix-keyboard";
label = "F(x)Tec Pro1 Hardware Keyboard";
row-gpios =
<&gpioext0 0 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 1 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 2 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 3 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 4 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 5 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 6 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>,
<&gpioext0 7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
col-gpios =
<&gpioext0 8 GPIO_ACTIVE_LOW>,
<&gpioext0 9 GPIO_ACTIVE_LOW>,
<&gpioext0 10 GPIO_ACTIVE_LOW>,
<&gpioext0 11 GPIO_ACTIVE_LOW>,
<&gpioext0 12 GPIO_ACTIVE_LOW>,
<&gpioext0 13 GPIO_ACTIVE_LOW>,
<&gpioext0 14 GPIO_ACTIVE_LOW>,
<&gpioext0 15 GPIO_ACTIVE_LOW>;
keypad,num-rows = <8>;
keypad,num-columns = <8>;
pinctrl-names = "default";
pinctrl-0 = <&keyboard_pins_col>, <&keyboard_pins_row>;
autorescan-ms = <5>;
debounce-delay-ms = <1>;
col-scan-delay-us = <1500>;
};
gpio_kb_extra_keys {
compatible = "gpio-keys";
input-name = "extra-kb-keys";
label = "Keyboard extra keys";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&gpio_kb_extra_active>;
home {
label = "Home";
gpios = <&tlmm 21 GPIO_ACTIVE_LOW>;
linux,code = <172>;
debounce-interval = <15>;
linux,can-disable;
};
super_l {
label = "Super Left";
gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
linux,code = <KEY_FN>;
debounce-interval = <15>;
linux,can-disable;
};
super_r {
label = "Super Right";
gpios = <&tlmm 33 GPIO_ACTIVE_LOW>;
linux,code = <KEY_FN>;
debounce-interval = <15>;
linux,can-disable;
};
shift {
label = "Shift";
gpios = <&tlmm 114 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RIGHTSHIFT>;
debounce-interval = <15>;
linux,can-disable;
};
ctrl {
label = "Ctrl";
gpios = <&tlmm 128 GPIO_ACTIVE_LOW>;
linux,code = <KEY_LEFTCTRL>;
debounce-interval = <15>;
linux,can-disable;
};
alt {
label = "Alt";
gpios = <&tlmm 129 GPIO_ACTIVE_LOW>;
linux,code = <56>;
debounce-interval = <15>;
linux,can-disable;
};
};
gpio_hall_sensors {
compatible = "gpio-keys";
input-name = "hall-sensors";
label = "Hall sensors";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&hall_sensor0_default>, <&hall_sensor1_default>;
/*
hall_sensor0 {
label = "Cover Hall Sensor";
gpios = <&tlmm 82 GPIO_ACTIVE_HIGH>;
linux,input-type = <EV_SW>;
linux,code = <SW_LID>;
gpio-key,wakeup;
debounce-interval = <15>;
};
*/
hall_sensor1 {
label = "Keyboard Hall Sensor";
gpios = <&tlmm 124 GPIO_ACTIVE_HIGH>;
linux,input-type = <EV_SW>;
linux,code = <SW_KEYPAD_SLIDE>;
gpio-key,wakeup;
debounce-interval = <15>;
};
};
gpio_keys {
compatible = "gpio-keys";
input-name = "side-buttons";
label = "Side buttons";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&vol_up_pin_a>, <&cam_focus_pin_a>,
<&cam_snapshot_pin_a>;
vol_up {
label = "Volume Up";
gpios = <&pm8998_gpio 6 GPIO_ACTIVE_LOW>;
linux,input-type = <1>;
linux,code = <KEY_VOLUMEUP>;
gpio-key,wakeup;
debounce-interval = <15>;
};
camera_snapshot {
label = "Camera Snapshot";
gpios = <&pm8998_gpio 7 GPIO_ACTIVE_LOW>;
linux,input-type = <1>;
linux,code = <KEY_CAMERA>;
debounce-interval = <15>;
};
camera_focus {
label = "Camera Focus";
gpios = <&pm8998_gpio 8 GPIO_ACTIVE_LOW>;
linux,input-type = <1>;
linux,code = <KEY_CAMERA_FOCUS>;
debounce-interval = <15>;
};
};
disp_vcc_vreg: disp-vcc-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_vcc";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
disp_vddio_vreg: disp-vddio-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_vddio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
regulator-allow-set-load;
};
disp_vci_vreg: disp-vci-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_vci";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-boot-on;
regulator-always-on;
regulator-allow-set-load;
};
disp_elvdd_vreg: disp-elvdd-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_elvdd";
regulator-min-microvolt = <4600000>;
regulator-max-microvolt = <4600000>;
regulator-boot-on;
regulator-always-on;
};
disp_elvss_vreg: disp-elvss-regulator {
compatible = "regulator-fixed";
regulator-name = "disp_elvss";
regulator-min-microvolt = <2400000>;
regulator-max-microvolt = <2400000>;
regulator-boot-on;
regulator-always-on;
};
ts_vio_vreg: ts-vio-vreg {
compatible = "regulator-fixed";
regulator-name = "ts_vio_reg";
startup-delay-us = <2>;
enable-active-high;
gpio = <&tlmm 81 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&ts_vio_default>;
regulator-always-on;
};
/*
* Until we hook up type-c detection, we
* have to stick with this. But it works.
*/
extcon_usb: extcon-usb {
compatible = "linux,extcon-usb-gpio";
id-gpio = <&tlmm 38 GPIO_ACTIVE_HIGH>;
};
};
&adreno_gpu {
status = "ok";
zap-shader {
memory-region = <&zap_shader_region>;
firmware-name = "qcom/a540_zap.mbn";
};
};
&adreno_smmu {
status = "ok";
};
&apc_cprh {
status = "ok";
};
&blsp1_i2c6 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c6_default>;
pinctrl-1 = <&i2c6_sleep>;
dmas = <&blsp1_dma 16>, <&blsp1_dma 17>;
dma-names = "tx", "rx";
status = "ok";
gpioext0: gpio-expander@58 {
compatible = "awinic,aw9523-pinctrl";
reg = <0x58>;
interrupt-parent = <&tlmm>;
interrupts = <50 IRQ_TYPE_EDGE_FALLING>;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&gpioext0 0 0 16>;
interrupt-controller;
#interrupt-cells = <2>;
pinctrl-0 = <&gpio_expander_int_n>, <&gpio_expander_rst_n>;
pinctrl-names = "default";
reset-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>;
keyboard_pins_col: keyboard-matrix-col-pins {
pins = "gpio8", "gpio9", "gpio10", "gpio11",
"gpio12", "gpio13", "gpio14", "gpio15";
function = "gpio";
output-low;
};
keyboard_pins_row: keyboard-matrix-row-pins {
pins = "gpio0", "gpio1", "gpio2", "gpio3",
"gpio4", "gpio5", "gpio6", "gpio7";
function = "gpio";
drive-open-drain;
input-enable;
};
};
};
&blsp2_i2c1 {
status = "ok";
qcom,noise-reject-scl = <3>;
qcom,noise-reject-sda = <3>;
touchscreen@14 {
compatible = "goodix,gt9286";
reg = <0x14>;
interrupt-parent = <&tlmm>;
interrupts = <125 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&tlmm 89 GPIO_ACTIVE_HIGH>;
AVDD28-supply = <&vreg_l28_3p0>;
VDDIO-supply = <&ts_vio_vreg>;
pinctrl-names = "active", "sleep";
pinctrl-0 = <&ts_active>;
pinctrl-1 = <&ts_sleep>;
};
};
&cpufreq_hw {
status = "ok";
};
&dsi0 {
#address-cells = <1>;
#size-cells = <0>;
status = "ok";
vdd-supply = <&vreg_l1a_0p875>;
vdda-supply = <&vreg_l2a_1p2>;
panel: panel@0 {
compatible = "boe,bf060y8m-aj0";
reg = <0>;
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
disp-te-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
no-hpd;
vcc-supply = <&disp_vcc_vreg>;
vddio-supply = <&disp_vddio_vreg>;
vci-supply = <&disp_vci_vreg>;
elvdd-supply = <&disp_elvdd_vreg>;
elvss-supply = <&disp_elvss_vreg>;
pinctrl-names = "default";
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&dsi0_phy {
status = "ok";
};
&dsi0_out {
remote-endpoint = <&panel_in>;
data-lanes = <0 1 2 3>;
};
&gcc {
status = "ok";
};
&gpucc {
status = "ok";
};
&gpio_keyboard {
linux,keymap = <
MATRIX_KEY(0, 0, KEY_F1) MATRIX_KEY(1, 0, KEY_H)
MATRIX_KEY(2, 0, KEY_B) MATRIX_KEY(3, 0, KEY_7)
MATRIX_KEY(4, 0, KEY_UP) MATRIX_KEY(5, 0, KEY_ENTER)
MATRIX_KEY(6, 0, KEY_Y) MATRIX_KEY(7, 0, KEY_COMMA)
MATRIX_KEY(0, 1, KEY_3) MATRIX_KEY(1, 1, KEY_S)
MATRIX_KEY(2, 1, KEY_Z) MATRIX_KEY(3, 1, KEY_M)
MATRIX_KEY(4, 1, KEY_I) MATRIX_KEY(5, 1, KEY_9)
MATRIX_KEY(6, 1, KEY_W) MATRIX_KEY(7, 1, KEY_J)
MATRIX_KEY(0, 2, KEY_LEFT) MATRIX_KEY(1, 2, KEY_G)
MATRIX_KEY(2, 2, KEY_V) MATRIX_KEY(3, 2, KEY_6)
MATRIX_KEY(4, 2, KEY_RIGHT) MATRIX_KEY(5, 2, KEY_DELETE)
MATRIX_KEY(6, 2, KEY_T) MATRIX_KEY(7, 2, KEY_DOT)
MATRIX_KEY(0, 3, KEY_SLASH) MATRIX_KEY(1, 3, KEY_A)
MATRIX_KEY(2, 3, KEY_RIGHTBRACE) MATRIX_KEY(3, 3, KEY_HOMEPAGE)
MATRIX_KEY(4, 3, KEY_P) MATRIX_KEY(5, 3, KEY_MINUS)
MATRIX_KEY(6, 3, KEY_Q) MATRIX_KEY(7, 3, KEY_L)
MATRIX_KEY(0, 4, KEY_BACKSPACE) MATRIX_KEY(1, 4, KEY_D)
MATRIX_KEY(2, 4, KEY_X) MATRIX_KEY(3, 4, KEY_K)
MATRIX_KEY(4, 4, KEY_SEMICOLON) MATRIX_KEY(5, 4, KEY_EQUAL)
MATRIX_KEY(6, 4, KEY_E) MATRIX_KEY(7, 4, KEY_APOSTROPHE)
MATRIX_KEY(0, 5, KEY_CAPSLOCK) MATRIX_KEY(1, 5, KEY_BACKSLASH)
MATRIX_KEY(2, 5, KEY_LEFTBRACE) MATRIX_KEY(3, 5, KEY_DOWN)
MATRIX_KEY(4, 5, KEY_O) MATRIX_KEY(5, 5, KEY_0)
MATRIX_KEY(6, 5, KEY_GRAVE) MATRIX_KEY(7, 5, KEY_K)
MATRIX_KEY(0, 6, KEY_SPACE) MATRIX_KEY(1, 6, KEY_F)
MATRIX_KEY(2, 6, KEY_C) MATRIX_KEY(3, 6, KEY_N)
MATRIX_KEY(4, 6, KEY_U) MATRIX_KEY(5, 6, KEY_8)
MATRIX_KEY(6, 6, KEY_R) MATRIX_KEY(7, 6, KEY_5)
MATRIX_KEY(0, 7, KEY_ESC) MATRIX_KEY(1, 7, KEY_1)
MATRIX_KEY(2, 7, KEY_RESERVED) MATRIX_KEY(3, 7, KEY_RESERVED)
MATRIX_KEY(4, 7, KEY_2) MATRIX_KEY(5, 7, KEY_4)
MATRIX_KEY(6, 7, KEY_TAB) MATRIX_KEY(7, 7, KEY_RESERVED)
>;
};
&mdss {
status = "ok";
};
&mdss_mdp {
status = "ok";
};
&remoteproc_adsp {
status = "okay";
firmware-name = "qcom/msm8998/fxtec/adsp.mbn";
};
&remoteproc_mss {
firmware-name = "qcom/msm8998/fxtec/mba.mbn", "qcom/msm8998/fxtec/modem.mbn";
};
&remoteproc_slpi {
status = "okay";
firmware-name = "qcom/msm8998/fxtec/slpi_v2.mbn";
};
&mmcc {
status = "ok";
};
&mmss_smmu {
status = "ok";
};
&pmi8998_haptics {
status = "okay";
qcom,wave-play-rate-us = <5000>;
};
/* HACK! Push GPU voltage high until GPU CPR is hooked up */
&pm8005_s1 {
regulator-min-microvolt = <988000>;
regulator-max-microvolt = <1100000>;
};
&pmi8998_fg {
status = "okay";
qcom,max-voltage-uv = <4400000>;
qcom,min-voltage-uv = <3700000>;
qcom,battery-capacity-ua = <3150000>;
};
&pm8998_gpio {
unknown_pin_a: unk-active {
pins = "gpio5";
function = "normal";
input-enable;
bias-pull-up;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
};
vol_up_pin_a: vol-up-active {
pins = "gpio6";
function = "normal";
input-enable;
bias-pull-up;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
};
cam_focus_pin_a: cam-focus-btn-active {
pins = "gpio7";
function = "normal";
input-enable;
bias-pull-up;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
};
cam_snapshot_pin_a: cam-snapshot-btn-active {
pins = "gpio8";
function = "normal";
input-enable;
bias-pull-up;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
};
};
&pm8998_pon {
resin {
compatible = "qcom,pm8941-resin";
interrupts = <GIC_SPI 0x8 1 IRQ_TYPE_EDGE_BOTH>;
debounce = <15625>;
bias-pull-up;
linux,code = <KEY_VOLUMEDOWN>;
};
};
&tlmm {
gpio-reserved-ranges = <0 4>;
mdp_vsync_n: mdp-vsync-n {
pins = "gpio10";
function = "mdp_vsync_a";
drive-strength = <2>;
bias-pull-down;
};
i2c6_default: i2c6-default {
pins = "gpio43", "gpio44";
function = "blsp_i2c6";
drive-strength = <2>;
bias-disable;
};
i2c6_sleep: i2c6-sleep {
pins = "gpio43", "gpio44";
function = "blsp_i2c6";
drive-strength = <2>;
bias-pull-up;
};
gpio_kb_extra_active: gpio-kb-extra-active {
pins = "gpio21", "gpio32", "gpio33", "gpio114",
"gpio128", "gpio129";
function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
gpio_expander_int_n: gpio-exp-intn-def {
pins = "gpio50";
drive-strength = <2>;
input-enable;
};
gpio_expander_rst_n: gpio-exp-rst-def {
pins = "gpio51";
drive-strength = <8>;
};
disp_en_default: disp-en {
pins = "gpio62";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
ts_vio_default: ts-vio-def {
pins = "gpio81";
drive-strength = <2>;
bias-disable;
};
hall_sensor0_default: hall-sensor0-def {
pins = "gpio82";
drive-strength = <2>;
bias-disable;
input-enable;
};
hall_sensor1_default: hall-sensor1-def {
pins = "gpio124";
drive-strength = <2>;
bias-disable;
input-enable;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
ts_active: ts-active {
ts-rst-n {
pins = "gpio89";
drive-strength = <8>;
bias-pull-up;
};
ts-intr-n {
pins = "gpio125";
drive-strength = <8>;
bias-disable;
};
};
ts_sleep: ts-sleep {
ts-rst-n {
pins = "gpio89";
drive-strength = <2>;
bias-disable;
};
ts-intr-n {
pins = "gpio125";
drive-strength = <2>;
bias-pull-down;
};
};
};
&ufshc {
status = "ok";
};
&ufsphy {
status = "ok";
};
&usb3_dwc3 {
dr_mode = "peripheral";
extcon = <&extcon_usb>;
};
/* GT9286 analog supply */
&vreg_l28_3p0 {
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
};

View file

@ -40,3 +40,19 @@
};
};
};
/* Capacitive keypad buttons */
&rmi4_i2c {
rmi4-f1a@1a {
reg = <0x1a>;
syna,codes = <KEY_BACK KEY_APPSELECT>;
};
};
/* Display */
&panel {
compatible = "samsung,s6e3fa5";
/* The panel is mounted upside down on the OnePlus 5 */
rotation = <180>;
};

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,132 @@
};
};
&remoteproc_adsp {
status = "okay";
firmware-name = "qcom/msm8998/oneplus/adsp.mbn";
};
&remoteproc_mss {
status = "okay";
firmware-name = "qcom/msm8998/oneplus/mba.mbn", "qcom/msm8998/oneplus/modem.mbn";
};
&remoteproc_slpi {
status = "okay";
firmware-name = "qcom/msm8998/oneplus/slpi_v2.mbn";
};
&mmcc {
status = "okay";
};
&mmss_smmu {
status = "okay";
};
&mdss {
status = "okay";
};
&mdss_mdp {
status = "okay";
};
&dsi0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
vdd-supply = <&vreg_l1a_0p875>;
vdda-supply = <&vreg_l2a_1p2>;
panel: panel@0 {
reg = <0>;
reset-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
disp-te-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>;
vddio-supply = <&vreg_l14a_1p88>; // TODO: Could this be moved under dsi0?
pinctrl-names = "default";
pinctrl-0 = <&panel_reset_n &disp_en_default &mdp_vsync_n>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&dsi0_phy {
status = "okay";
vdds-supply = <&vreg_l1a_0p875>;
};
&dsi0_out {
remote-endpoint = <&panel_in>;
data-lanes = <0 1 2 3>;
};
/* Adreno 540 GPU */
&gpucc {
status = "ok";
};
&gpu_mem {
compatible = "shared-dma-pool";
};
&adreno_gpu {
status = "ok";
zap-shader {
memory-region = <&zap_shader_region>; // gpu_mem?
firmware-name = "qcom/a540_zap.mbn";
};
};
&adreno_smmu {
status = "ok";
};
/*
* HACK: Shoot GPU voltage high to stabilize Adreno 540 at high frequencies
* until the GPU CPR is brought up.
*/
&pm8005_s1 {
regulator-min-microvolt = <988000>; /* 0,524V -> 0,988V */
//regulator-max-microvolt = <1100000>;
};
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
disp_en_default: disp-en {
pins = "gpio62";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
panel_reset_n: panel-rst-n {
pins = "gpio94";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
mdp_vsync_n: mdp-vsync-n {
pins = "gpio11";
function = "mdp_vsync_a";
drive-strength = <2>;
bias-pull-down;
};
hall_sensor_default: hall-sensor-default {
pins = "gpio124";
function = "gpio";
@ -461,6 +687,20 @@
drive-strength = <8>;
bias-pull-up;
};
nfc_int_active: nfc_int_active {
pins = "gpio92";
function = "gpio";
drive-strength = <6>;
bias-pull-up;
};
nfc_enable_active: nfc_enable_active {
pins = "gpio12", "gpio116";
function = "gpio";
drive-strength = <6>;
bias-pull-up;
};
};
&ufshc {
@ -506,7 +746,7 @@
};
&wifi {
/* Leave disabled until MSS is functional */
status = "okay";
vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;

View file

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

View file

@ -0,0 +1,35 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2021, AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
*/
/dts-v1/;
#include "msm8998-sony-xperia-yoshino.dtsi"
/ {
model = "Sony Xperia XZ1 Compact";
compatible = "sony,xperia-lilac", "qcom,msm8998";
};
&ibb {
regulator-min-microvolt = <5500000>;
regulator-max-microvolt = <5500000>;
};
&lab {
regulator-min-microvolt = <5500000>;
regulator-max-microvolt = <5500000>;
qcom,soft-start-us = <800>;
};
&wcd9335 {
pinctrl-0 = <&cdc_reset_n &wcd_int_n>;
pinctrl-names = "default";
};
&vreg_l22a_2p85 {
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
};

View file

@ -0,0 +1,116 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2021, AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
*/
/dts-v1/;
#include "msm8998-sony-xperia-yoshino.dtsi"
/ {
model = "Sony Xperia XZ Premium";
compatible = "sony,xperia-maple", "qcom,msm8998";
disp_dvdd_vreg: disp-dvdd-vreg {
compatible = "regulator-fixed";
regulator-name = "disp_dvdd_en";
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
startup-delay-us = <0>;
enable-active-high;
gpio = <&pmi8998_gpio 10 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&disp_dvdd_en>;
};
};
&dsi0 {
qcom,dual-dsi-mode;
qcom,master-dsi;
};
&dsi1 {
vdd-supply = <&vreg_l1a_0p875>;
vdda-supply = <&vreg_l2a_1p2>;
qcom,dual-dsi-mode;
status = "ok";
};
&dsi1_out {
remote-endpoint = <&panel_in1>;
data-lanes = <0 1 2 3>;
};
&dsi1_phy {
vdds-supply = <&vreg_l1a_0p875>;
status = "ok";
};
&ibb {
regulator-min-microvolt = <5600000>;
regulator-max-microvolt = <5600000>;
};
&lab {
regulator-min-microvolt = <5800000>;
regulator-max-microvolt = <5800000>;
qcom,soft-start-us = <200>;
};
&panel {
compatible = "sharp,ls055d1sx04";
dvdd-supply = <&disp_dvdd_vreg>;
ports {
port@1 {
reg = <1>;
panel_in1: endpoint {
remote-endpoint = <&dsi1_out>;
};
};
};
};
&pm8005_gpio {
ear_en_default: ear-en-active {
pins = "gpio1";
function = "normal";
bias-disable;
drive-push-pull;
output-high;
power-source = <1>; /* 1.8V */
qcom,drive-strength = <1>;
};
};
&pmi8998_gpio {
disp_dvdd_en: disp-dvdd-en-active {
pins = "gpio10";
function = PMIC_GPIO_FUNC_NORMAL;
drive-push-pull;
bias-disable;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
power-source = <0>;
output-high;
};
};
&vreg_l22a_2p85 {
regulator-min-microvolt = <2704000>;
regulator-max-microvolt = <2704000>;
};
&pmi8998_wled {
status = "okay";
//qcom,auto-string-detection;
qcom,num-strings = <3>;
qcom,enabled-strings = <0 1 2>;
};
&wcd9335 {
pinctrl-0 = <&cdc_reset_n &wcd_int_n &ear_en_default>;
pinctrl-names = "default";
};

View file

@ -0,0 +1,40 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2021, AngeloGioacchino Del Regno
* <angelogioacchino.delregno@somainline.org>
*/
/dts-v1/;
#include "msm8998-sony-xperia-yoshino.dtsi"
/ {
model = "Sony Xperia XZ1";
compatible = "sony,xperia-poplar", "qcom,msm8998";
};
&ibb {
regulator-min-microvolt = <5600000>;
regulator-max-microvolt = <5600000>;
};
&lab {
regulator-min-microvolt = <5600000>;
regulator-max-microvolt = <5600000>;
qcom,soft-start-us = <800>;
};
&wcd9335 {
pinctrl-0 = <&cdc_reset_n &wcd_int_n>;
pinctrl-names = "default";
};
&vreg_l18a_2p85 {
regulator-min-microvolt = <2850000>;
regulator-max-microvolt = <2850000>;
};
&vreg_l22a_2p85 {
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <2700000>;
};

File diff suppressed because it is too large Load diff

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

@ -119,6 +119,14 @@
#address-cells = <1>;
#size-cells = <0>;
pm8916_pwm: pwm {
compatible = "qcom,pm8916-pwm";
#pwm-cells = <2>;
status = "disabled";
};
pm8916_vib: vibrator@c000 {
compatible = "qcom,pm8916-vib";
reg = <0xc000>;

View file

@ -140,6 +140,16 @@
#address-cells = <1>;
#size-cells = <0>;
pm8994_lpg: lpg {
compatible = "qcom,pm8994-lpg";
#address-cells = <1>;
#size-cells = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pm8994_spmi_regulators: regulators {
compatible = "qcom,pm8994-regulators";
};

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 {
@ -41,5 +53,41 @@
interrupt-names = "sc-err", "ocp";
};
};
pmi8998_lpg: lpg {
compatible = "qcom,pmi8998-lpg";
#address-cells = <1>;
#size-cells = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pmi8998_haptics: haptics@c000 {
compatible = "qcom,pmi8998-haptics", "qcom,spmi-haptics";
reg = <0xc000>;
interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
<0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "short", "play";
qcom,wave-shape = <HAP_WAVE_SINE>;
qcom,play-mode = <HAP_PLAY_BUFFER>;
qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
status = "disabled";
};
pmi8998_wled: leds@d800 {
compatible = "qcom,pm660l-wled";
reg = <0xd800 0xd900>;
interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>,
<0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "ovp", "short";
label = "backlight";
status = "disabled";
};
};
};

View file

@ -1168,19 +1168,19 @@
<&cpr_efuse_ring2>,
<&cpr_efuse_ring3>,
<&cpr_efuse_revision>;
nvmem-cell-names = "cpr_quotient_offset1",
"cpr_quotient_offset2",
"cpr_quotient_offset3",
"cpr_init_voltage1",
"cpr_init_voltage2",
"cpr_init_voltage3",
"cpr_quotient1",
"cpr_quotient2",
"cpr_quotient3",
"cpr_ring_osc1",
"cpr_ring_osc2",
"cpr_ring_osc3",
"cpr_fuse_revision";
nvmem-cell-names = "cpr0_quotient_offset1",
"cpr0_quotient_offset2",
"cpr0_quotient_offset3",
"cpr0_init_voltage1",
"cpr0_init_voltage2",
"cpr0_init_voltage3",
"cpr0_quotient1",
"cpr0_quotient2",
"cpr0_quotient3",
"cpr0_ring_osc1",
"cpr0_ring_osc2",
"cpr0_ring_osc3",
"cpr0_fuse_revision";
};
timer@b120000 {

View file

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

View file

@ -12,3 +12,7 @@
model = "Sony Xperia XA2 Ultra";
compatible = "sony,discovery-row", "qcom,sdm630";
};
&panel {
compatible = "sony,discovery-td4322-innolux";
};

View file

@ -12,3 +12,7 @@
model = "Sony Xperia XA2";
compatible = "sony,pioneer-row", "qcom,sdm630";
};
&panel {
compatible = "sony,pioneer-td4322-truly";
};

View file

@ -19,3 +19,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_29p5>;
vqmmc-supply = <&vreg_l2b_2p95>;
@ -605,6 +691,20 @@
bias-disable;
drive-strength = <2>;
};
panel_reset_n: panel-rst-n {
pins = "gpio53";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
mdp_vsync_n: mdp-vsync-n {
pins = "gpio59";
function = "mdp_vsync";
drive-strength = <2>;
bias-pull-down;
};
};
&usb3 {
@ -615,3 +715,345 @@
dr_mode = "peripheral";
extcon = <&extcon_usb>;
};
&rpm_requests {
pm660l-regulators {
compatible = "qcom,rpm-pm660l-regulators";
vdd_s1-supply = <&vph_pwr>;
vdd_s2-supply = <&vph_pwr>;
vdd_s3_s4-supply = <&vph_pwr>;
vdd_s5-supply = <&vph_pwr>;
vdd_s6-supply = <&vph_pwr>;
vdd_l1_l9_l10-supply = <&vreg_s2b_1p05>;
vdd_l2-supply = <&vreg_bob>;
vdd_l3_l5_l7_l8-supply = <&vreg_bob>;
vdd_l4_l6-supply = <&vreg_bob>;
vdd_bob-supply = <&vph_pwr>;
vreg_s1b_1p125: s1 {
regulator-min-microvolt = <1125000>;
regulator-max-microvolt = <1125000>;
regulator-enable-ramp-delay = <200>;
regulator-ramp-delay = <0>;
};
vreg_s2b_1p05: s2 {
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-enable-ramp-delay = <200>;
regulator-ramp-delay = <0>;
};
/*
* At least on Nile's configuration, S3B/S4B (VDD_CX) and
* S5B (VDD_MX) are managed only through RPM Power Domains.
* Trying to set a voltage on the main supply will create
* havoc and freeze the SoC.
* In any case, reference voltages for these regulators are:
* S3B/S4B: 0.870V
* S5B: 0.915V
*/
/* LDOs */
vreg_l1b_0p925: l1 {
regulator-min-microvolt = <920000>;
regulator-max-microvolt = <928000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-allow-set-load;
};
vreg_l2b_2p95: l2 {
/*
* This regulator supports 1.648 - 3.104V on this board
* but we set a max voltage of anything less than 2.7V
* to satisfy a condition in sdhci.c that will disable
* 3.3V SDHCI signaling, which happens to be not really
* supported on the Xperia Nile/Ganges platform.
*/
regulator-min-microvolt = <1648000>;
regulator-max-microvolt = <2696000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-allow-set-load;
};
vreg_l3b_3p0: l3 {
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-min-microamp = <200>;
regulator-max-microamp = <600000>;
regulator-system-load = <100000>;
regulator-allow-set-load;
};
vreg_l4b_29p5: l4 {
regulator-min-microvolt = <2944000>;
regulator-max-microvolt = <2952000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-min-microamp = <200>;
regulator-max-microamp = <600000>;
regulator-system-load = <570000>;
regulator-allow-set-load;
};
/*
* Downstream specifies a range of 1721-3600mV,
* but the only assigned consumers are SDHCI2 VMMC
* and Coresight QPDI that both request pinned 2.95V.
* Tighten the range to 1.8-3.328 (closest to 3.3) to
* make the mmc driver happy.
*/
vreg_l5b_29p5: l5 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3328000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-allow-set-load;
};
vreg_l6b_3p3: l6 {
regulator-min-microvolt = <1704000>;
regulator-max-microvolt = <3312000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l7b_3p125: l7 {
regulator-min-microvolt = <2704000>;
regulator-max-microvolt = <3128000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l8b_3p3: l8 {
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <3400000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
/* L9B (870mV) is currently unused */
/* L10B (915mV) is currently unused */
vreg_bob: bob {
regulator-min-microvolt = <3304000>;
regulator-max-microvolt = <3624000>;
regulator-enable-ramp-delay = <500>;
regulator-ramp-delay = <0>;
};
};
pm660-regulators {
compatible = "qcom,rpm-pm660-regulators";
vdd_s1-supply = <&vph_pwr>;
vdd_s2-supply = <&vph_pwr>;
vdd_s3-supply = <&vph_pwr>;
vdd_s4-supply = <&vph_pwr>;
vdd_s5-supply = <&vph_pwr>;
vdd_s6-supply = <&vph_pwr>;
vdd_l1_l6_l7-supply = <&vreg_s5a_1p35>;
vdd_l2_l3-supply = <&vreg_s2b_1p05>;
vdd_l5-supply = <&vreg_s2b_1p05>;
vdd_l8_l9_l10_l11_l12_l13_l14-supply = <&vreg_s4a_2p04>;
vdd_l15_l16_l17_l18_l19-supply = <&vreg_bob>;
/*
* S1A (FTAPC0), S2A (FTAPC1), S3A (HFAPC1) are managed
* by the Core Power Reduction hardened (CPRh) and the
* Operating State Manager (OSM) HW automatically.
*/
vreg_s4a_2p04: s4 {
regulator-min-microvolt = <2040000>;
regulator-max-microvolt = <2040000>;
regulator-enable-ramp-delay = <200>;
regulator-ramp-delay = <0>;
regulator-always-on;
};
vreg_s5a_1p35: s5 {
regulator-min-microvolt = <1224000>;
regulator-max-microvolt = <1350000>;
regulator-enable-ramp-delay = <200>;
regulator-ramp-delay = <0>;
};
vreg_s6a_0p87: s6 {
regulator-min-microvolt = <504000>;
regulator-max-microvolt = <992000>;
regulator-enable-ramp-delay = <150>;
regulator-ramp-delay = <0>;
};
/* LDOs */
vreg_l1a_1p225: l1 {
regulator-min-microvolt = <1226000>;
regulator-max-microvolt = <1250000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-allow-set-load;
};
vreg_l2a_1p0: l2 {
regulator-min-microvolt = <944000>;
regulator-max-microvolt = <1008000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l3a_1p0: l3 {
regulator-min-microvolt = <944000>;
regulator-max-microvolt = <1008000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l5a_0p848: l5 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <952000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l6a_1p3: l6 {
regulator-min-microvolt = <1304000>;
regulator-max-microvolt = <1368000>;
regulator-allow-set-load;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l7a_1p2: l7 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l8a_1p8: l8 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-system-load = <325000>;
regulator-allow-set-load;
};
vreg_l9a_1p8: l9 {
regulator-min-microvolt = <1804000>;
regulator-max-microvolt = <1896000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-allow-set-load;
};
vreg_l10a_1p8: l10 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1944000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-allow-set-load;
};
vreg_l11a_1p8: l11 {
regulator-min-microvolt = <1784000>;
regulator-max-microvolt = <1944000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l12a_1p8: l12 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1944000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
/* This gives power to the LPDDR4: never turn it off! */
vreg_l13a_1p8: l13 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1944000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-boot-on;
regulator-always-on;
};
vreg_l14a_1p8: l14 {
regulator-min-microvolt = <1710000>;
regulator-max-microvolt = <1904000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l15a_1p8: l15 {
regulator-min-microvolt = <1648000>;
regulator-max-microvolt = <2952000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
/* L16A (2.70V) is unused */
vreg_l17a_1p8: l17 {
regulator-min-microvolt = <1648000>;
regulator-max-microvolt = <2952000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
};
vreg_l18a_1v8: l18 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <10>;
regulator-min-microamp = <200>;
regulator-max-microamp = <50000>;
regulator-system-load = <10000>;
regulator-allow-set-load;
};
vreg_l19a_3p3: l19 {
regulator-min-microvolt = <3312000>;
regulator-max-microvolt = <3400000>;
regulator-enable-ramp-delay = <250>;
regulator-ramp-delay = <0>;
regulator-allow-set-load;
};
};
};
&tlmm {
gpio-reserved-ranges = <8 4>;
imx300_vana_default: imx300-vana-default {
pins = "gpio50";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
imx219_vana_default: imx219-vana-default {
pins = "gpio51";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
cam_vdig_default: cam-vdig-default {
pins = "gpio52";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
};

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";
};
spmi_bus: spmi@800f000 {
@ -2061,8 +2604,6 @@
<GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
adsp_pil: remoteproc@15700000 {
@ -2224,8 +2765,8 @@
intc: interrupt-controller@17a00000 {
compatible = "arm,gic-v3";
reg = <0x17a00000 0x10000>, /* GICD */
<0x17b00000 0x100000>; /* GICR * 8 */
reg = <0x17a00000 0x10000>, /* GICD */
<0x17b00000 0x100000>; /* GICR * 8 */
#interrupt-cells = <3>;
#address-cells = <1>;
#size-cells = <1>;

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

@ -593,6 +593,30 @@
};
};
&pmi8998_lpg {
status = "okay";
qcom,power-source = <1>;
led@3 {
reg = <3>;
label = "green:user3";
linux,default-trigger = "heartbeat";
default-state = "on";
};
led@4 {
reg = <4>;
label = "green:user2";
};
led@5 {
reg = <5>;
label = "green:user1";
};
};
/* QUAT I2S Uses 4 I2S SD Lines for audio on LT9611 HDMI Bridge */
&q6afedai {
qi2s@22 {

View file

@ -447,6 +447,19 @@
};
};
&pmi8998_fg {
status = "okay";
qcom,max-voltage-uv = <4400000>;
qcom,min-voltage-uv = <3700000>;
};
&pmi8998_haptics {
status = "okay";
qcom,wave-play-rate-us = <4255>;
};
&qupv3_id_1 {
status = "okay";
};
@ -616,7 +629,7 @@
pins = "gpio6", "gpio25", "gpio26";
function = "gpio";
drive-strength = <8>;
bias-disable = <0>;
bias-disable;
};
};

View file

@ -12,6 +12,10 @@
compatible = "oneplus,enchilada", "qcom,sdm845";
};
&pmi8998_fg {
qcom,battery-capacity-ua = <3300000>;
};
&display_panel {
status = "okay";

View file

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

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -810,15 +810,20 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = {
.num_clks = ARRAY_SIZE(qcs404_clks),
};
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin,
3);
DEFINE_CLK_SMD_RPM_BRANCH(msm8998, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk3, ln_bb_clk3_a, 3);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, 3);
DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk,
QCOM_SMD_RPM_AGGR_CLK, 1);
DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk,
QCOM_SMD_RPM_AGGR_CLK, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6);
static struct clk_smd_rpm *msm8998_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
[RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
@ -831,12 +836,22 @@ static struct clk_smd_rpm *msm8998_clks[] = {
[RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk,
[RPM_SMD_DIV_CLK1] = &msm8974_div_clk1,
[RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1,
[RPM_SMD_DIV_CLK2] = &msm8974_div_clk2,
[RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2,
[RPM_SMD_DIV_CLK3] = &msm8992_div_clk3,
[RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a,
[RPM_SMD_IPA_CLK] = &msm8976_ipa_clk,
[RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk,
[RPM_SMD_LN_BB_CLK1] = &msm8916_bb_clk1,
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
[RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk,
@ -849,10 +864,14 @@ static struct clk_smd_rpm *msm8998_clks[] = {
[RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,
[RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,
[RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
[RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
[RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
[RPM_SMD_RF_CLK3] = &msm8998_rf_clk3,
[RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a,
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
[RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
[RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin,
[RPM_SMD_RF_CLK3_A_PIN] = &msm8998_rf_clk3_a_pin,
};
@ -862,14 +881,9 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = {
.num_clks = ARRAY_SIZE(msm8998_clks),
};
DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0,
19200000);
DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, ln_bb_clk3_pin_a, 3);
static struct clk_smd_rpm *sdm660_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk,
[RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk,
@ -896,16 +910,16 @@ static struct clk_smd_rpm *sdm660_clks[] = {
[RPM_SMD_LN_BB_A_CLK] = &msm8916_bb_clk1_a,
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
[RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
[RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
[RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
[RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
[RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
[RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin,
[RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a,
[RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
[RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
};
static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
@ -914,8 +928,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
};
static struct clk_smd_rpm *mdm9607_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
@ -936,8 +950,8 @@ static const struct rpm_smd_clk_desc rpm_clk_mdm9607 = {
};
static struct clk_smd_rpm *msm8953_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
[RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
[RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
@ -985,8 +999,8 @@ DEFINE_CLK_SMD_RPM(sm6125, snoc_lpass_clk, snoc_lpass_a_clk,
QCOM_SMD_RPM_BUS_CLK, 5);
static struct clk_smd_rpm *sm6125_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
@ -1007,8 +1021,8 @@ static struct clk_smd_rpm *sm6125_clks[] = {
[RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
[RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
[RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
[RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
[RPM_SMD_LN_BB_CLK3] = &msm8998_ln_bb_clk3,
[RPM_SMD_LN_BB_CLK3_A] = &msm8998_ln_bb_clk3_a,
[RPM_SMD_QUP_CLK] = &sm6125_qup_clk,
[RPM_SMD_QUP_A_CLK] = &sm6125_qup_a_clk,
[RPM_SMD_MMRT_CLK] = &sm6125_mmrt_clk,
@ -1028,8 +1042,8 @@ static const struct rpm_smd_clk_desc rpm_clk_sm6125 = {
/* SM6115 */
static struct clk_smd_rpm *sm6115_clks[] = {
[RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
[RPM_SMD_XO_CLK_SRC] = &msm8998_bi_tcxo,
[RPM_SMD_XO_A_CLK_SRC] = &msm8998_bi_tcxo_a,
[RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,

View file

@ -122,7 +122,7 @@ static struct clk_fixed_factor xo = {
.div = 1,
.hw.init = &(struct clk_init_data){
.name = "xo",
.parent_names = (const char *[]){ "xo_board" },
.parent_names = (const char *[]){ "bi_tcxo" },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
},
@ -2041,6 +2041,7 @@ static struct clk_branch gcc_bimc_gfx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_bimc_gfx_clk",
.flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@ -2181,6 +2182,7 @@ static struct clk_rcg2 hmss_gpll0_clk_src = {
.name = "hmss_gpll0_clk_src",
.parent_names = gcc_parent_names_1,
.num_parents = ARRAY_SIZE(gcc_parent_names_1),
.flags = CLK_IS_CRITICAL,
.ops = &clk_rcg2_ops,
},
};
@ -2784,6 +2786,43 @@ static struct clk_branch gcc_rx1_usb2_clkref_clk = {
},
};
static struct clk_branch hlos1_vote_lpass_core_smmu_clk = {
.halt_reg = 0x7D010,
.clkr = {
.enable_reg = 0x7D010,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data) {
.name = "hlos1_vote_lpass_core_smmu_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch hlos1_vote_lpass_adsp_smmu_clk = {
.halt_reg = 0x7D014,
.clkr = {
.enable_reg = 0x7D014,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data) {
.name = "hlos1_vote_lpass_adsp_smmu_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
.halt_reg = 0x8A040,
.clkr = {
.enable_reg = 0x8A040,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data) {
.name = "gcc_mss_q6_bimc_axi_clk",
.flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
};
static struct gdsc pcie_0_gdsc = {
.gdscr = 0x6b004,
.gds_hw_ctrl = 0x0,
@ -2814,6 +2853,26 @@ static struct gdsc usb_30_gdsc = {
.flags = VOTABLE,
};
static struct gdsc hlos1_vote_lpass_adsp = {
.gdscr = 0x7d034,
.gds_hw_ctrl = 0x0,
.pd = {
.name = "lpass_adsp_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
static struct gdsc hlos1_vote_lpass_core = {
.gdscr = 0x7d038,
.gds_hw_ctrl = 0x0,
.pd = {
.name = "lpass_core_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = ALWAYS_ON,
};
static struct clk_regmap *gcc_msm8998_clocks[] = {
[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
@ -2987,12 +3046,17 @@ static struct clk_regmap *gcc_msm8998_clocks[] = {
[GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
[GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
[HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
[GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
[HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = &hlos1_vote_lpass_core_smmu_clk.clkr,
[HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &hlos1_vote_lpass_adsp_smmu_clk.clkr,
};
static struct gdsc *gcc_msm8998_gdscs[] = {
[PCIE_0_GDSC] = &pcie_0_gdsc,
[UFS_GDSC] = &ufs_gdsc,
[USB_30_GDSC] = &usb_30_gdsc,
[LPASS_ADSP_GDSC] = &hlos1_vote_lpass_adsp,
[LPASS_CORE_GDSC] = &hlos1_vote_lpass_core,
};
static const struct qcom_reset_map gcc_msm8998_resets[] = {
@ -3148,6 +3212,14 @@ static int gcc_msm8998_probe(struct platform_device *pdev)
if (ret)
return ret;
/*
* GCC_MMSS_MISC - GCC_GPU_MISC:
* 1. Disable the GPLL0 active input to MMSS and GPU
* 2. Select clk division 1 (CLK/2)
*/
regmap_write(regmap, 0x0902C, 0x10003); /* MMSS*/
regmap_write(regmap, 0x71028, 0x10003); /* GPU */
return qcom_cc_really_probe(pdev, &gcc_msm8998_desc, regmap);
}

View file

@ -520,7 +520,7 @@ static struct clk_rcg2 byte0_clk_src = {
.parent_data = mmss_xo_dsibyte,
.num_parents = 4,
.ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};
@ -533,7 +533,7 @@ static struct clk_rcg2 byte1_clk_src = {
.parent_data = mmss_xo_dsibyte,
.num_parents = 4,
.ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};
@ -1084,7 +1084,7 @@ static struct clk_rcg2 pclk0_clk_src = {
.parent_data = mmss_xo_dsi0pll_dsi1pll,
.num_parents = 4,
.ops = &clk_pixel_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};
@ -1098,7 +1098,7 @@ static struct clk_rcg2 pclk1_clk_src = {
.parent_data = mmss_xo_dsi0pll_dsi1pll,
.num_parents = 4,
.ops = &clk_pixel_ops,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
},
};

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

@ -112,6 +112,7 @@ config ARM_QCOM_SPM_CPUIDLE
select CPU_IDLE_MULTIPLE_DRIVERS
select DT_IDLE_STATES
select QCOM_SCM
select QCOM_SPM
help
Select this to enable cpuidle for Qualcomm processors.
The Subsystem Power Manager (SPM) controls low power modes for the

View file

@ -18,158 +18,18 @@
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/qcom_scm.h>
#include <soc/qcom/spm.h>
#include <asm/proc-fns.h>
#include <asm/suspend.h>
#include "dt_idle_states.h"
#define MAX_PMIC_DATA 2
#define MAX_SEQ_DATA 64
#define SPM_CTL_INDEX 0x7f
#define SPM_CTL_INDEX_SHIFT 4
#define SPM_CTL_EN BIT(0)
enum pm_sleep_mode {
PM_SLEEP_MODE_STBY,
PM_SLEEP_MODE_RET,
PM_SLEEP_MODE_SPC,
PM_SLEEP_MODE_PC,
PM_SLEEP_MODE_NR,
};
enum spm_reg {
SPM_REG_CFG,
SPM_REG_SPM_CTL,
SPM_REG_DLY,
SPM_REG_PMIC_DLY,
SPM_REG_PMIC_DATA_0,
SPM_REG_PMIC_DATA_1,
SPM_REG_VCTL,
SPM_REG_SEQ_ENTRY,
SPM_REG_SPM_STS,
SPM_REG_PMIC_STS,
SPM_REG_NR,
};
struct spm_reg_data {
const u8 *reg_offset;
u32 spm_cfg;
u32 spm_dly;
u32 pmic_dly;
u32 pmic_data[MAX_PMIC_DATA];
u8 seq[MAX_SEQ_DATA];
u8 start_index[PM_SLEEP_MODE_NR];
};
struct spm_driver_data {
struct cpuidle_qcom_spm_data {
struct cpuidle_driver cpuidle_driver;
void __iomem *reg_base;
const struct spm_reg_data *reg_data;
struct spm_driver_data *spm;
};
static const u8 spm_reg_offset_v2_1[SPM_REG_NR] = {
[SPM_REG_CFG] = 0x08,
[SPM_REG_SPM_CTL] = 0x30,
[SPM_REG_DLY] = 0x34,
[SPM_REG_SEQ_ENTRY] = 0x80,
};
/* SPM register data for 8974, 8084 */
static const struct spm_reg_data spm_reg_8974_8084_cpu = {
.reg_offset = spm_reg_offset_v2_1,
.spm_cfg = 0x1,
.spm_dly = 0x3C102800,
.seq = { 0x03, 0x0B, 0x0F, 0x00, 0x20, 0x80, 0x10, 0xE8, 0x5B, 0x03,
0x3B, 0xE8, 0x5B, 0x82, 0x10, 0x0B, 0x30, 0x06, 0x26, 0x30,
0x0F },
.start_index[PM_SLEEP_MODE_STBY] = 0,
.start_index[PM_SLEEP_MODE_SPC] = 3,
};
/* SPM register data for 8226 */
static const struct spm_reg_data spm_reg_8226_cpu = {
.reg_offset = spm_reg_offset_v2_1,
.spm_cfg = 0x0,
.spm_dly = 0x3C102800,
.seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90,
0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B,
0x80, 0x10, 0x26, 0x30, 0x0F },
.start_index[PM_SLEEP_MODE_STBY] = 0,
.start_index[PM_SLEEP_MODE_SPC] = 5,
};
static const u8 spm_reg_offset_v1_1[SPM_REG_NR] = {
[SPM_REG_CFG] = 0x08,
[SPM_REG_SPM_CTL] = 0x20,
[SPM_REG_PMIC_DLY] = 0x24,
[SPM_REG_PMIC_DATA_0] = 0x28,
[SPM_REG_PMIC_DATA_1] = 0x2C,
[SPM_REG_SEQ_ENTRY] = 0x80,
};
/* SPM register data for 8064 */
static const struct spm_reg_data spm_reg_8064_cpu = {
.reg_offset = spm_reg_offset_v1_1,
.spm_cfg = 0x1F,
.pmic_dly = 0x02020004,
.pmic_data[0] = 0x0084009C,
.pmic_data[1] = 0x00A4001C,
.seq = { 0x03, 0x0F, 0x00, 0x24, 0x54, 0x10, 0x09, 0x03, 0x01,
0x10, 0x54, 0x30, 0x0C, 0x24, 0x30, 0x0F },
.start_index[PM_SLEEP_MODE_STBY] = 0,
.start_index[PM_SLEEP_MODE_SPC] = 2,
};
static inline void spm_register_write(struct spm_driver_data *drv,
enum spm_reg reg, u32 val)
{
if (drv->reg_data->reg_offset[reg])
writel_relaxed(val, drv->reg_base +
drv->reg_data->reg_offset[reg]);
}
/* Ensure a guaranteed write, before return */
static inline void spm_register_write_sync(struct spm_driver_data *drv,
enum spm_reg reg, u32 val)
{
u32 ret;
if (!drv->reg_data->reg_offset[reg])
return;
do {
writel_relaxed(val, drv->reg_base +
drv->reg_data->reg_offset[reg]);
ret = readl_relaxed(drv->reg_base +
drv->reg_data->reg_offset[reg]);
if (ret == val)
break;
cpu_relax();
} while (1);
}
static inline u32 spm_register_read(struct spm_driver_data *drv,
enum spm_reg reg)
{
return readl_relaxed(drv->reg_base + drv->reg_data->reg_offset[reg]);
}
static void spm_set_low_power_mode(struct spm_driver_data *drv,
enum pm_sleep_mode mode)
{
u32 start_index;
u32 ctl_val;
start_index = drv->reg_data->start_index[mode];
ctl_val = spm_register_read(drv, SPM_REG_SPM_CTL);
ctl_val &= ~(SPM_CTL_INDEX << SPM_CTL_INDEX_SHIFT);
ctl_val |= start_index << SPM_CTL_INDEX_SHIFT;
ctl_val |= SPM_CTL_EN;
spm_register_write_sync(drv, SPM_REG_SPM_CTL, ctl_val);
}
static int qcom_pm_collapse(unsigned long int unused)
{
qcom_scm_cpu_power_down(QCOM_SCM_CPU_PWR_DOWN_L2_ON);
@ -201,10 +61,10 @@ static int qcom_cpu_spc(struct spm_driver_data *drv)
static int spm_enter_idle_state(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int idx)
{
struct spm_driver_data *data = container_of(drv, struct spm_driver_data,
cpuidle_driver);
struct cpuidle_qcom_spm_data *data = container_of(drv, struct cpuidle_qcom_spm_data,
cpuidle_driver);
return CPU_PM_CPU_IDLE_ENTER_PARAM(qcom_cpu_spc, idx, data);
return CPU_PM_CPU_IDLE_ENTER_PARAM(qcom_cpu_spc, idx, data->spm);
}
static struct cpuidle_driver qcom_spm_idle_driver = {
@ -225,134 +85,92 @@ static const struct of_device_id qcom_idle_state_match[] = {
{ },
};
static int spm_cpuidle_init(struct cpuidle_driver *drv, int cpu)
static int spm_cpuidle_register(struct device *cpuidle_dev, int cpu)
{
struct platform_device *pdev = NULL;
struct device_node *cpu_node, *saw_node;
struct cpuidle_qcom_spm_data *data = NULL;
int ret;
memcpy(drv, &qcom_spm_idle_driver, sizeof(*drv));
drv->cpumask = (struct cpumask *)cpumask_of(cpu);
cpu_node = of_cpu_device_node_get(cpu);
if (!cpu_node)
return -ENODEV;
/* Parse idle states from device tree */
ret = dt_init_idle_driver(drv, qcom_idle_state_match, 1);
saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
if (!saw_node)
return -ENODEV;
pdev = of_find_device_by_node(saw_node);
of_node_put(saw_node);
of_node_put(cpu_node);
if (!pdev)
return -ENODEV;
data = devm_kzalloc(cpuidle_dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->spm = dev_get_drvdata(&pdev->dev);
if (!data->spm)
return -EINVAL;
data->cpuidle_driver = qcom_spm_idle_driver;
data->cpuidle_driver.cpumask = (struct cpumask *)cpumask_of(cpu);
ret = dt_init_idle_driver(&data->cpuidle_driver,
qcom_idle_state_match, 1);
if (ret <= 0)
return ret ? : -ENODEV;
/* We have atleast one power down mode */
return qcom_scm_set_warm_boot_addr(cpu_resume_arm, drv->cpumask);
ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm, cpumask_of(cpu));
if (ret)
return ret;
return cpuidle_register(&data->cpuidle_driver, NULL);
}
static struct spm_driver_data *spm_get_drv(struct platform_device *pdev,
int *spm_cpu)
static int spm_cpuidle_drv_probe(struct platform_device *pdev)
{
struct spm_driver_data *drv = NULL;
struct device_node *cpu_node, *saw_node;
int cpu;
bool found = 0;
for_each_possible_cpu(cpu) {
cpu_node = of_cpu_device_node_get(cpu);
if (!cpu_node)
continue;
saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
found = (saw_node == pdev->dev.of_node);
of_node_put(saw_node);
of_node_put(cpu_node);
if (found)
break;
}
if (found) {
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (drv)
*spm_cpu = cpu;
}
return drv;
}
static const struct of_device_id spm_match_table[] = {
{ .compatible = "qcom,msm8226-saw2-v2.1-cpu",
.data = &spm_reg_8226_cpu },
{ .compatible = "qcom,msm8974-saw2-v2.1-cpu",
.data = &spm_reg_8974_8084_cpu },
{ .compatible = "qcom,apq8084-saw2-v2.1-cpu",
.data = &spm_reg_8974_8084_cpu },
{ .compatible = "qcom,apq8064-saw2-v1.1-cpu",
.data = &spm_reg_8064_cpu },
{ },
};
static int spm_dev_probe(struct platform_device *pdev)
{
struct spm_driver_data *drv;
struct resource *res;
const struct of_device_id *match_id;
void __iomem *addr;
int cpu, ret;
if (!qcom_scm_is_available())
return -EPROBE_DEFER;
drv = spm_get_drv(pdev, &cpu);
if (!drv)
return -EINVAL;
platform_set_drvdata(pdev, drv);
for_each_possible_cpu(cpu) {
ret = spm_cpuidle_register(&pdev->dev, cpu);
if (ret && ret != -ENODEV) {
dev_err(&pdev->dev,
"Cannot register for CPU%d: %d\n", cpu, ret);
}
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
drv->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(drv->reg_base))
return PTR_ERR(drv->reg_base);
match_id = of_match_node(spm_match_table, pdev->dev.of_node);
if (!match_id)
return -ENODEV;
drv->reg_data = match_id->data;
ret = spm_cpuidle_init(&drv->cpuidle_driver, cpu);
if (ret)
return ret;
/* Write the SPM sequences first.. */
addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY];
__iowrite32_copy(addr, drv->reg_data->seq,
ARRAY_SIZE(drv->reg_data->seq) / 4);
/*
* ..and then the control registers.
* On some SoC if the control registers are written first and if the
* CPU was held in reset, the reset signal could trigger the SPM state
* machine, before the sequences are completely written.
*/
spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg);
spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly);
spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly);
spm_register_write(drv, SPM_REG_PMIC_DATA_0,
drv->reg_data->pmic_data[0]);
spm_register_write(drv, SPM_REG_PMIC_DATA_1,
drv->reg_data->pmic_data[1]);
/* Set up Standby as the default low power mode */
spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY);
return cpuidle_register(&drv->cpuidle_driver, NULL);
}
static int spm_dev_remove(struct platform_device *pdev)
{
struct spm_driver_data *drv = platform_get_drvdata(pdev);
cpuidle_unregister(&drv->cpuidle_driver);
return 0;
}
static struct platform_driver spm_driver = {
.probe = spm_dev_probe,
.remove = spm_dev_remove,
static struct platform_driver spm_cpuidle_driver = {
.probe = spm_cpuidle_drv_probe,
.driver = {
.name = "saw",
.of_match_table = spm_match_table,
.name = "qcom-spm-cpuidle",
.suppress_bind_attrs = true,
},
};
builtin_platform_driver(spm_driver);
static int __init qcom_spm_cpuidle_init(void)
{
struct platform_device *pdev;
int ret;
ret = platform_driver_register(&spm_cpuidle_driver);
if (ret)
return ret;
pdev = platform_device_register_simple("qcom-spm-cpuidle",
-1, NULL, 0);
if (IS_ERR(pdev)) {
platform_driver_unregister(&spm_cpuidle_driver);
return PTR_ERR(pdev);
}
return 0;
}
device_initcall(qcom_spm_cpuidle_init);

View file

@ -109,7 +109,7 @@ config DRM_MSM_DSI_14NM_PHY
Choose this option if DSI PHY on 8996 is used on the platform.
config DRM_MSM_DSI_10NM_PHY
bool "Enable DSI 10nm PHY driver in MSM DRM (used by SDM845)"
bool "Enable DSI 10nm PHY driver in MSM DRM (used by MSM8998/SDM845)"
depends on DRM_MSM_DSI
default y
help

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,48 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
{.fl = 0, .lut = 0x0},
};
static const struct dpu_perf_cfg msm8998_perf_data = {
.max_bw_low = 6700000,
.max_bw_high = 6700000,
.min_core_ib = 2400000,
.min_llcc_ib = 800000,
.min_dram_ib = 800000,
.core_ib_ff = "6.0",
.core_clk_ff = "1.0",
.comp_ratio_rt =
"NV12/5/1/1.23 AB24/5/1/1.23 XB24/5/1/1.23",
.comp_ratio_nrt =
"NV12/5/1/1.25 AB24/5/1/1.25 XB24/5/1/1.25",
.undersized_prefill_lines = 2,
.xtra_prefill_lines = 2,
.dest_scale_prefill_lines = 3,
.macrotile_prefill_lines = 4,
.yuv_nv12_prefill_lines = 8,
.linear_prefill_lines = 1,
.downscaling_prefill_lines = 1,
.amortizable_threshold = 25,
.min_prefill_lines = 25,
.danger_lut_tbl = {0xf, 0xffff, 0x0},
.safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(msm8998_qos_linear),
.entries = msm8998_qos_linear
},
{.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
.entries = msm8998_qos_macrotile
},
{.nentry = ARRAY_SIZE(msm8998_qos_nrt),
.entries = msm8998_qos_nrt
},
},
.cdp_cfg = {
{.rd_enable = 1, .wr_enable = 1},
{.rd_enable = 1, .wr_enable = 0}
},
.clk_inefficiency_factor = 200,
.bw_inefficiency_factor = 120,
};
static const struct dpu_perf_cfg sdm845_perf_data = {
.max_bw_low = 6800000,
.max_bw_high = 6800000,
@ -1112,6 +1395,34 @@ static const struct dpu_perf_cfg sc7280_perf_data = {
* Hardware catalog init
*************************************************************/
/*
* msm8998_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
* and instance counts.
*/
static void msm8998_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
{
*dpu_cfg = (struct dpu_mdss_cfg){
.caps = &msm8998_dpu_caps,
.mdp_count = ARRAY_SIZE(msm8998_mdp),
.mdp = msm8998_mdp,
.ctl_count = ARRAY_SIZE(msm8998_ctl),
.ctl = msm8998_ctl,
.sspp_count = ARRAY_SIZE(msm8998_sspp),
.sspp = msm8998_sspp,
.mixer_count = ARRAY_SIZE(msm8998_lm),
.mixer = msm8998_lm,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
.intf_count = ARRAY_SIZE(msm8998_intf),
.intf = msm8998_intf,
.vbif_count = ARRAY_SIZE(msm8998_vbif),
.vbif = msm8998_vbif,
.reg_dma_count = 0,
.perf = msm8998_perf_data,
.mdss_irqs = IRQ_SM8250_MASK,
};
}
/*
* sdm845_cfg_init(): populate sdm845 dpu sub-blocks reg offsets
* and instance counts.
@ -1262,6 +1573,8 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
}
static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = {
{ .hw_rev = DPU_HW_VER_300, .cfg_init = msm8998_cfg_init},
{ .hw_rev = DPU_HW_VER_301, .cfg_init = msm8998_cfg_init},
{ .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init},
{ .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init},
{ .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init},

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

@ -1270,6 +1270,7 @@ static const struct dev_pm_ops dpu_pm_ops = {
};
static const struct of_device_id dpu_dt_match[] = {
{ .compatible = "qcom,msm8998-dpu", },
{ .compatible = "qcom,sdm845-dpu", },
{ .compatible = "qcom,sc7180-dpu", },
{ .compatible = "qcom,sc7280-dpu", },

View file

@ -950,13 +950,12 @@ static const struct mdp5_cfg_hw sdm630_config = {
.mdp = {
.count = 1,
.caps = MDP_CAP_CDM |
MDP_CAP_SRC_SPLIT |
0,
},
.ctl = {
.count = 5,
.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
.flush_hw_mask = 0xf4ffffff,
.flush_hw_mask = 0xf54338c1,
},
.pipe_vig = {
.count = 1,
@ -969,16 +968,6 @@ static const struct mdp5_cfg_hw sdm630_config = {
MDP_PIPE_CAP_SW_PIX_EXT |
0,
},
.pipe_rgb = {
.count = 4,
.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
.caps = MDP_PIPE_CAP_HFLIP |
MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE |
MDP_PIPE_CAP_DECIMATION |
MDP_PIPE_CAP_SW_PIX_EXT |
0,
},
.pipe_dma = {
.count = 2, /* driver supports max of 2 currently */
.base = { 0x24000, 0x26000, 0x28000 },
@ -998,13 +987,12 @@ static const struct mdp5_cfg_hw sdm630_config = {
},
.lm = {
.count = 2,
.base = { 0x44000, 0x46000 },
.count = 3, /* LM_1 seems broken */
.base = { 0x44000, 0x45000, 0x46000 },
.instances = {
{ .id = 0, .pp = 0, .dspp = 0,
.caps = MDP_LM_CAP_DISPLAY |
MDP_LM_CAP_PAIR, },
{ .id = 1, .pp = 1, .dspp = -1,
.caps = MDP_LM_CAP_DISPLAY, },
{ .id = 2, .pp = 2, .dspp = -1,
.caps = MDP_LM_CAP_WB, },
},
.nb_stages = 8,
@ -1020,8 +1008,8 @@ static const struct mdp5_cfg_hw sdm630_config = {
.base = { 0x78000, 0x78800 },
},
.pp = {
.count = 3,
.base = { 0x70000, 0x71000, 0x72000 },
.count = 3, /* Do not use PP1 */
.base = { 0x70000, 0x70800, 0x71000 },
},
.cdm = {
.count = 1,
@ -1049,11 +1037,11 @@ static const struct mdp5_cfg_hw sdm660_config = {
.ctl = {
.count = 5,
.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
.flush_hw_mask = 0xf4ffffff,
.flush_hw_mask = 0xf5437bc3,
},
.pipe_vig = {
.count = 2,
.base = { 0x04000, 0x6000 },
.base = { 0x04000, 0x06000 },
.caps = MDP_PIPE_CAP_HFLIP |
MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE |
@ -1062,16 +1050,6 @@ static const struct mdp5_cfg_hw sdm660_config = {
MDP_PIPE_CAP_SW_PIX_EXT |
0,
},
.pipe_rgb = {
.count = 4,
.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
.caps = MDP_PIPE_CAP_HFLIP |
MDP_PIPE_CAP_VFLIP |
MDP_PIPE_CAP_SCALE |
MDP_PIPE_CAP_DECIMATION |
MDP_PIPE_CAP_SW_PIX_EXT |
0,
},
.pipe_dma = {
.count = 2, /* driver supports max of 2 currently */
.base = { 0x24000, 0x26000, 0x28000 },
@ -1091,19 +1069,19 @@ static const struct mdp5_cfg_hw sdm660_config = {
},
.lm = {
.count = 4,
.base = { 0x44000, 0x45000, 0x46000, 0x49000 },
.count = 6, /* Do not use LM_3, LM_4 */
.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
.instances = {
{ .id = 0, .pp = 0, .dspp = 0,
.caps = MDP_LM_CAP_DISPLAY |
MDP_LM_CAP_PAIR, },
{ .id = 1, .pp = 1, .dspp = 1,
.caps = MDP_LM_CAP_DISPLAY, },
{ .id = 2, .pp = 2, .dspp = -1,
{ .id = 2, .pp = -1, .dspp = -1,
.caps = MDP_LM_CAP_WB, },
{ .id = 5, .pp = 4, .dspp = -1,
.caps = MDP_LM_CAP_DISPLAY |
MDP_LM_CAP_PAIR, },
{ .id = 3, .pp = 3, .dspp = -1,
.caps = MDP_LM_CAP_WB, },
},
.nb_stages = 8,
.max_width = 2560,
@ -1118,7 +1096,7 @@ static const struct mdp5_cfg_hw sdm660_config = {
.base = { 0x78000, 0x78800 },
},
.pp = {
.count = 5,
.count = 5, /* Do not use PP_2 and PP_3 */
.base = { 0x70000, 0x70800, 0x71000, 0x71800, 0x72000 },
},
.cdm = {
@ -1132,10 +1110,10 @@ static const struct mdp5_cfg_hw sdm660_config = {
.intf = {
.base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800 },
.connect = {
[0] = INTF_DISABLED,
[0] = INTF_HDMI,
[1] = INTF_DSI,
[2] = INTF_DSI,
[3] = INTF_HDMI,
[3] = INTF_DISABLED,
},
},
.max_clk = 412500000,

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
@ -260,6 +271,17 @@ config DRM_PANEL_NOVATEK_NT35510
around the Novatek NT35510 display controller, such as some
Hydis panels.
config DRM_PANEL_NOVATEK_NT35950
tristate "Novatek NT35950 DSI panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for the panels built
around the Novatek NT35950 display controller, such as some
Sharp panels used in Sony Xperia Z5 Premium and XZ Premium
mobile phones.
config DRM_PANEL_NOVATEK_NT36672A
tristate "Novatek NT36672A DSI panel"
depends on OF
@ -393,6 +415,36 @@ config DRM_PANEL_SAMSUNG_S6D16D0
depends on DRM_MIPI_DSI
select VIDEOMODE_HELPERS
config DRM_PANEL_SAMSUNG_S6E3FA5
tristate "Samsung S6E3FA5 DSI command mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for Samsung S6E3FA5 AMOLED
command mode panel as found in OnePlus 5 (2017) devices. The panel has a
FHD (1080x1920) resolution and uses 24 bit RGB per pixel. It provides a
MIPI DSI interface to the host and has a built-in LED backlight.
To compile this driver as a module, choose M here: the module
will be called panel-samsung-s6e3fa5.
config DRM_PANEL_SAMSUNG_S6E3FC1
tristate "Samsung S6E3FC1 DSI command mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for Samsung S6E3FC1 AMOLED
command mode panel as found in OnePlus 5T (2017) devices. The panel has a
FHD (1080x2160) resolution and uses 24 bit RGB per pixel. It provides a
MIPI DSI interface to the host and has a built-in LED backlight.
To compile this driver as a module, choose M here: the module
will be called panel-samsung-s6e3fc1.
config DRM_PANEL_SAMSUNG_S6E3HA2
tristate "Samsung S6E3HA2 DSI video mode panel"
depends on OF
@ -547,6 +599,36 @@ config DRM_PANEL_SONY_ACX565AKM
Say Y here if you want to enable support for the Sony ACX565AKM
800x600 3.5" panel (found on the Nokia N900).
config DRM_PANEL_SONY_DISCOVERY_TD4322_INNOLUX
tristate "Sony Discovery TD4322 Innolux panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable the Innolux TD4322
1080-1920 command mode panel (as found on Sony Xperia
XA2 Ultra devices).
config DRM_PANEL_SONY_PIONEER_TD4322_TRULY
tristate "Sony Pioneer TD4322 Truly panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable the Truly TD4322 1080x
1920 command mode display panel (as found on Sony Xperia XA2
devices).
config DRM_PANEL_SONY_VOYAGER_TD4328_TIANMA
tristate "Sony Voyager TD4328 Tianma panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable the Tianma TD4328 1080x
2160 command mode panel (as found on Sony Xperia XA2 Plus
devices).
config DRM_PANEL_TDO_TL070WSH30
tristate "TDO TL070WSH30 DSI panel"
depends on OF

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
@ -24,6 +25,7 @@ obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
@ -39,6 +41,8 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FA5) += panel-samsung-s6e3fa5.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FC1) += panel-samsung-s6e3fc1.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
@ -56,6 +60,9 @@ obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
obj-$(CONFIG_DRM_PANEL_SONY_ACX424AKP) += panel-sony-acx424akp.o
obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
obj-$(CONFIG_DRM_PANEL_SONY_DISCOVERY_TD4322_INNOLUX) += panel-td4322-innolux-fhd.o
obj-$(CONFIG_DRM_PANEL_SONY_PIONEER_TD4322_TRULY) += panel-td4322-truly-fhd.o
obj-$(CONFIG_DRM_PANEL_SONY_VOYAGER_TD4328_TIANMA) += panel-td4328-tianma-fhdplus.o
obj-$(CONFIG_DRM_PANEL_TDO_TL070WSH30) += panel-tdo-tl070wsh30.o
obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o

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

@ -5158,6 +5158,68 @@ static const struct panel_desc_dsi osd101t2045_53ts = {
.lanes = 4,
};
static const struct drm_display_mode sony_kirin_nt36672a_truly_mode = {
.clock = (1080 + 25 + 12 + 120) * (2520 + 12 + 4 + 10) * 60 / 1000,
.hdisplay = 1080,
.hsync_start = 1080 + 25,
.hsync_end = 1080 + 25 + 12,
.htotal = 1080 + 25 + 12 + 120,
.vdisplay = 2520,
.vsync_start = 2520 + 12,
.vsync_end = 2520 + 12 + 4,
.vtotal = 2520 + 12 + 4 + 10,
.width_mm = 60,
.height_mm = 139,
};
static const struct panel_desc_dsi sony_kirin_nt36672a_truly = {
.desc = {
.modes = &sony_kirin_nt36672a_truly_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 60,
.height = 139,
},
.connector_type = DRM_MODE_CONNECTOR_DSI,
},
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_CLOCK_NON_CONTINUOUS,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
};
static const struct drm_display_mode sony_mermaid_nt36672a_tianma_mode = {
.clock = (1080 + 102 + 20 + 40) * (2520 + 10 + 2 + 8) * 60 / 1000,
.hdisplay = 1080,
.hsync_start = 1080 + 102,
.hsync_end = 1080 + 102 + 20,
.htotal = 1080 + 102 + 20 + 40,
.vdisplay = 2520,
.vsync_start = 2520 + 10,
.vsync_end = 2520 + 10 + 2,
.vtotal = 2520 + 10 + 2 + 8,
.width_mm = 65,
.height_mm = 151,
};
static const struct panel_desc_dsi sony_mermaid_nt36672a_tianma = {
.desc = {
.modes = &sony_mermaid_nt36672a_tianma_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 65,
.height = 151,
},
.connector_type = DRM_MODE_CONNECTOR_DSI,
},
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_CLOCK_NON_CONTINUOUS,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
};
static const struct of_device_id dsi_of_match[] = {
{
.compatible = "auo,b080uan01",
@ -5180,6 +5242,12 @@ static const struct of_device_id dsi_of_match[] = {
}, {
.compatible = "osddisplays,osd101t2045-53ts",
.data = &osd101t2045_53ts
}, {
.compatible = "sony,kirin-nt36672a-truly",
.data = &sony_kirin_nt36672a_truly
}, {
.compatible = "sony,mermaid-nt36672a-tianma",
.data = &sony_mermaid_nt36672a_tianma
}, {
/* sentinel */
}

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

@ -22,6 +22,7 @@ obj-$(CONFIG_KEYBOARD_DLINK_DIR685) += dlink-dir685-touchkeys.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_GPIO_FASTMATRIX) += gpio_fastmatrix.o
obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
obj-$(CONFIG_KEYBOARD_TCA8418) += tca8418_keypad.o

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

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