blob: d9a49df685a63b5d6537e8eedfaaf415966c98fc [file] [log] [blame]
From a7fcd02e6c1392a72f79d6173d56d65aafd9c3ae Mon Sep 17 00:00:00 2001
From: Nicolas Boichat <drinkcat@chromium.org>
Date: Thu, 7 Mar 2019 18:17:32 +0800
Subject: [PATCH 2/3] HQ-TOT 40
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1475596/40
Add regulators, change required DT entries.
BUG=b:124335972
TEST=Boot kukui P2
Change-Id: I9992bb3b1427a3baf20fe99c08e2252d9900d83d
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
FIXUP: FROMLIST: arm64: dts: add display nodes for mt8183
This patch add display nodes for mt8183
BUG=b:126008314
TEST=Boot to shell
Change-Id: Ia099f934da5d1f762e6337e9f48667883518a3fa
Signed-off-by: CK Hu <ck.hu@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
CHROMIUM: drm/panel: panel-innolux: Allow 2 reset pins for panel
This is useful when there is a bridge between the SoC and the
panel.
BUG=b:123669273
TEST=Boot rev2
[rebase note: see b/124335972 for justification of CHROMIUM tag]
Change-Id: I487b27f858a262c9bfea16aab8b0321229846025
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
CHROMIUM: drm/panel: panel-innolux: Add support for P097PFZ behind SSD2858
Add commands to setup P097PFZ behing SSD2858 (4 to 8 lanes bridge).
For some unclear reasons, the initialization commands that P097PFZ
is supposed to require... don't seem to be required (and actually
break display if we sent them).
We also need to change the code that sends the MIPI commands to add
necessary delays.
BUG=b:123669273
TEST=Boot kukui rev2
[rebase note: see b/124335972 for justification of CHROMIUM tag.
To make this cleaner, we should probably use a proper DRM bridge to
setup the bridge (instead of hacking the panel driver).]
Change-Id: I0cbe84a496bfd029be4db1fe05e316659eab3468
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
FROMLIST: gpu/drm: mediatek: call mtk_dsi_stop() after mtk_drm_crtc_atomic_disable()
mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(), which needs
ovl irq for drm_crtc_wait_one_vblank(), since after mtk_dsi_stop() is called,
ovl irq will be disabled. If drm_crtc_wait_one_vblank() is called after last
irq, it will timeout with this message: "vblank wait timed out on crtc 0". This
happens sometimes when turning off the screen.
In drm_atomic_helper.c#disable_outputs(),
the calling sequence when turning off the screen is:
1. mtk_dsi_encoder_disable()
--> mtk_output_dsi_disable()
--> mtk_dsi_stop(); // sometimes make vblank timeout in atomic_disable
--> mtk_dsi_poweroff();
2. mtk_drm_crtc_atomic_disable()
--> drm_crtc_wait_one_vblank();
...
--> mtk_dsi_ddp_stop()
--> mtk_dsi_poweroff();
Change to make mtk_dsi_stop() called in mtk_dsi_ddp_stop() instead of
mtk_output_dsi_disable().
(am from https://patchwork.kernel.org/patch/10856865/)
TEST=suspend_stress_test 182 iteration no timeout warning
BUG=b:124486047
Fixes: 0707632b5bac ("drm/mediatek: update DSI sub driver flow for sending commands to panel")
Change-Id: I0916976b27877ed700e339c31022b393ca9e91a4
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
DO-NOT-SUBMIT: QCA wifi patches SQUASH
SQUASH of kukui wifi tot #32
including:
basic functionality:
None
bug fix:
DO-NOT-SUBMIT: kukui: ath10k: move some warning msg to dbg(CL:1639747/1)
FROMLIST: ath10k: add report MIC error for sdio chip(CL:1630539/2)
FROMLIST: ath10k: change firmware file name for UTF mode of SDIO/USB(CL:1628527/2)
FROMLIST: ath10k: add missing error handling(CL:1627070/4)
FROMLIST: ath10k: acquire lock to fix lockdep's warning(CL:1594406/10)
FROMLIST: ath10k: remove mmc_hw_reset while hif power down(CL:1585667/14)
FROMLIST: ath10k: add support for firmware crash recovery on SDIO chip(CL:1568867/19)
BUG=b:121980879
TEST=1) checkout CL:1317245/195
2) revert 1b6091c(old suqash)
3) rebase on m/master
4) cherry-pick this one
5) build, boot and check wifi connection
Change-Id: Iaebb8cf6f4604ec52b6a0b8500aef5d2d20b182c
DO-NOT-SUBMIT: Kukui ToT
Minimal set of patches to boot kukui
BUG=b:109911488
TEST=Boot to shell
Change-Id: I4b8194d5cd0b31670bb2ed7310747bed38775545
FROMLIST: pinctrl: mediatek: Ignore interrupts that are wake only during resume
Before suspending, mtk-eint would set the interrupt mask to the
one in wake_mask. However, some of these interrupts may not have a
corresponding interrupt handler, or the interrupt may be disabled.
On resume, the eint irq handler would trigger nevertheless,
and irq/pm.c:irq_pm_check_wakeup would be called, which would
try to call irq_disable. However, if the interrupt is not enabled
(irqd_irq_disabled(&desc->irq_data) is true), the call does nothing,
and the interrupt is left enabled in the eint driver.
Especially for level-sensitive interrupts, this will lead to an
interrupt storm on resume.
If we detect that an interrupt is only in wake_mask, but not in
cur_mask, we can just mask it out immediately (as mtk_eint_resume
would do anyway at a later stage in the resume sequence, when
restoring cur_mask).
Fixes: bf22ff45bed ("genirq: Avoid unnecessary low level irq function calls")
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
(am from https://patchwork.kernel.org/patch/10921143/)
(also found at https://lkml.kernel.org/r/20190429035515.73611-2-drinkcat@chromium.org)
BUG=b:129240721
TEST=on kukui, EC can wake system from suspend
Change-Id: Ic38985aa7c4dd4a4c5ad6595809ac8a4bc320ace
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
FROMLIST: pinctrl: mediatek: Update cur_mask in mask/mask ops
During suspend/resume, mtk_eint_mask may be called while
wake_mask is active. For example, this happens if a wake-source
with an active interrupt handler wakes the system:
irq/pm.c:irq_pm_check_wakeup would disable the interrupt, so
that it can be handled later on in the resume flow.
However, this may happen before mtk_eint_do_resume is called:
in this case, wake_mask is loaded, and cur_mask is restored
from an older copy, re-enabling the interrupt, and causing
an interrupt storm (especially for level interrupts).
Instead, we just record mask/unmask changes in cur_mask. This
also avoids the need to read the current mask in eint_do_suspend,
and we can remove mtk_eint_chip_read_mask function.
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
(am from https://patchwork.kernel.org/patch/10921147/)
(also found at https://lkml.kernel.org/r/20190429035515.73611-3-drinkcat@chromium.org)
BUG=b:129240721
TEST=on kukui, EC can wake system from suspend
Change-Id: I77d55cfb9ad3a0a0078f931695d6aeb8a6e5c217
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
WIP: usb: mtu3: Modification for MTU3 dualrole mode switch
Usage:
to host:
echo host > /sys/kernel/debug/usb/11201000.usb/mode
to device:
echo device > /sys/kernel/debug/usb/11201000.usb/mode
BUG=b:109911488
TEST=Boot to shell and do host/device mode change
Change-Id: Ie6d5b864ea36a40b959df6d06d4e038b7c3d74ee
Signed-off-by: Jumin Li <jumin.li@mediatek.com>
CHROMIUM: arm64: dts: mt8183: Add manual switch property
Enable manual dual mode
Set maximum-speed as high-speed
BUG=b:109911488
TEST=build and boot to shell and do usb features test
Change-Id: Iea92b3d15823229cf9816275b22cc582ad470aa9
Signed-off-by: Jumin Li <jumin.li@mediatek.com>
DO-NOT-SUBMIT: Snapshot of CMDQ ToT
Snapshot of CMDQ ToT patch set 11 (FROMLIST v3)
BUG=b:109911488
TEST=Display UI
Change-Id: Ie936fd7f2c16875d16a1cb87402a23d2609fa303
Signed-off-by: CK Hu <ck.hu@mediatek.com>
BACKPORT: FROMLIST: arm64: dts: add gce node for mt8183
add gce device node for mt8183
(am from https://patchwork.kernel.org/patch/10932479/)
BUG=b:109911488
TEST=build and boot to shell
Change-Id: I1edbdd1be9db1f128d984adc81895cb80c61e4eb
Signed-off-by: Bibby Hsieh <bibby.hsieh@mediatek.com>
Signed-off-by: CK Hu <ck.hu@mediatek.com>
DO-NOT-SUBMIT: Snapshot of VPU patches
Snapshot of VPU patches.
BUG=b:109911488
TEST=Boot to shell
Change-Id: I47a3afb7edafea353eea566d3fe6468feeedf9cd
Signed-off-by: CK Hu <ck.hu@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
DO-NOT-SUBMIT: arm64: dts: mt8183: add vpu node
New add vpu node
BUG=b:109911488
TEST=build and boot to shell
Change-Id: I0868a628e8c9f30e550ad034fd786ea566ca044b
Signed-off-by: Erin Lo <erin.lo@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
FROMLIST: dt-bindings: soc: Add MT8183 emi dt-bindings
Add emi dt-bindings of MT8183 in binding document.
Signed-off-by: Xi Chen <xixi.chen@mediatek.com>
(am from https://patchwork.kernel.org/patch/10921319/)
[eddie.huang: remove change-id in commit message]
BUG=b:109911488
TEST=build pass and boot to shell
Change-Id: I7182f3eda5835af8bf081d1056228bf73cb63f61
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
BACKPORT: FROMLIST: arm64: dts: mt8183: add emi node
Add emi dts node.
(am from https://patchwork.kernel.org/patch/10921629/)
[eddie.huang: remove change-id in commit message.
Fix context confclit]
BUG=b:109911488
TEST=build pass and boot to shell
Change-Id: I0b84e566d20af6fcb33b91f69be2f14f40a6e540
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
BACKPORT: FROMLIST: mt8183: emi: add bandwidth driver support
EMI provides interface for get bandwidth on every 1 miliseconds.
Currently, just support GPU bandwidth info.
Signed-off-by: Xi Chen <xixi.chen@mediatek.com>
(am from https://patchwork.kernel.org/patch/10921627/)
[eddie.huang: fix context confclit. Remove change-id in commit message.
Add MTK_EMI_MBW description to let defconfig to select]
BUG=b:109911488
TEST=build pass and boot to shell
Change-Id: I10d8f36d78c1dca8d91bc0e242fe83209a6c8190
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
WIP: clk: mediatek: mt8183: Register 13MHz clock earlier for clocksource
The 13MHz clock should be registered before clocksource driver is
initialized. Use CLK_OF_DECLARE_DRIVER() to guarantee.
BUG=b:126007177
TEST=build and boot to shell
Change-Id: I63f1c881bb4053da4214ddb14d725b37fd108ffd
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
Signed-off-by: Dehui Sun <dehui.sun@mediatek.com>
WIP: arm64: dts: mt8183: add systimer0 node
Add systimer0 node to the mt8183's devicetree.
BUG=b:109911488
BUG=None
TEST=build and boot to shell
Change-Id: I816152c47ad0aa86eb269b654d3a22d953f60c81
Signed-off-by: Dehui Sun <dehui.sun@mediatek.com>
WIP: serial: 8250-mtk: modify serial driver
modify serial power management function.
BUG=b:129106594
TEST=build and boot to shell
Change-Id: I23051b5f23ad314be518fce994d7affb2a8b1a27
Signed-off-by: Changqi Hu <changqi.hu@mediatek.com>
WIP: thermal: mtk_thermal: add suspend/resume callback
Added suspend/resume callback to disable/enable Mediatek thermal sensor
respectively. Since thermal power domain is off in suspend, thermal driver
needs re-initialization during resume.
BUG=none
TEST: boot to shell
Change-Id: I43f9af5c2d2b682f985eb570d6ed984243772e91
Signed-off-by: Louis Yu <louis.yu@mediatek.com>
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
HACK: clkdbg: clkdbg support for 8183
Clkdbg provides commands to view clock info and operate clocks,
such as enable/disable clocks and change their rate. Use the
following command to see available clkdbg commands:
.
echo cmds > /proc/clkdbg ; cat /proc/clkdbg
.
BUG=b:109911488
TEST=build and boot to shell
Change-Id: Ieb6a05b7f5ee9330cd10a02fafbdfc6654163f5e
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
HACK: clkchk: add clkchk support for 8183
dump the clocks those still ON during system suspend
BUG=b:109911488
TEST=build and boot to shell
Change-Id: Ifb7a0d683aed75b57161b27d76efd4318395dbca
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
HACK: sdio: mediatek: add sdio debug driver
New add sdio debug driver
BUG=b:109911488
TEST=cmd test is ok
Change-Id: Id1f53eb395a035caffc03a3a6f0e6c554c63a9ad
Signed-off-by: jjian zhou <jjian.zhou@mediatek.com>
CHROMIUM: config: Enable MT8183 usb dualrole mode configs
Features be enabled as follow:
USB mtu3 dualrole mode
USB gadget configfs functions
USB gadget ACM/MASS_STORAGE/SERIAL features
The change is generated from the following commands:
cat <<EOF | tee -a \
chromeos/config/arm64/chromiumos-arm64.flavour.config \
chromeos/config/arm64/chromiumos-mediatek.flavour.config
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_F_ACM=y
CONFIG_USB_F_FS=m
CONFIG_USB_F_MASS_STORAGE=y
CONFIG_USB_F_SERIAL=y
CONFIG_USB_MTU3_DEBUG=y
CONFIG_USB_MTU3_DUAL_ROLE=y
EOF
./chromeos/scripts/kernelconfig olddefconfig
BUG=b:109911488
TEST=build and boot to shell and test the function of these configs
Change-Id: Ie957cae98b3331668f4e29332c25714776e5fe80
Signed-off-by: Jumin Li <jumin.li@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
CHROMIUM: config: Enable MT8183 emi configs
The change is generated from the following commands:
cat <<EOF | tee -a \
chromeos/config/arm64/chromiumos-arm64.flavour.config \
chromeos/config/arm64/chromiumos-mediatek.flavour.config
CONFIG_MTK_EMI_MBW=y
EOF
./chromeos/scripts/kernelconfig olddefconfig
BUG=b:109911488
TEST=build and boot to shell
Change-Id: I9c92096719b72c077258a5d2b52b3ccec272af39
Signed-off-by: Xi Chen <xixi.chen@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
FROMLIST: PM / devfreq: Generic CPU frequency to device frequency mapping governor
Many CPU architectures have caches that can scale independent of the CPUs.
Frequency scaling of the caches is necessary to make sure the cache is not
a performance bottleneck that leads to poor performance and power. The same
idea applies for RAM/DDR.
To achieve this, this patch adds a generic devfreq governor that takes the
current frequency of each CPU frequency domain and then adjusts the
frequency of the cache (or any devfreq device) based on the frequency of
the CPUs. It listens to CPU frequency transition notifiers to keep itself
up to date on the current CPU frequency.
To decide the frequency of the device, the governor does one of the
following:
* Uses a CPU frequency to device frequency mapping table
- Either one mapping table used for all CPU freq policies (typically used
for system with homogeneous cores/clusters that have the same OPPs).
- One mapping table per CPU freq policy (typically used for ASMP systems
with heterogeneous CPUs with different OPPs)
OR
* Scales the device frequency in proportion to the CPU frequency. So, if
the CPUs are running at their max frequency, the device runs at its max
frequency. If the CPUs are running at their min frequency, the device
runs at its min frequency. And interpolated for frequencies in between.
Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
(am from https://patchwork.kernel.org/patch/10553171/)
BUG=b:122571050
TEST=boot to kukui
Change-Id: I299eecb1f1bb12679fcb394a28fb2655760568d2
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
CHROMIUM: config: Enable cpufreq-map governor for mtk-cci
cat <<EOF | tee -a \
chromeos/config/arm64/chromiumos-mediatek.flavour.config
CONFIG_DEVFREQ_GOV_CPUFREQ_MAP=y
EOF
./chromeos/scripts/kernelconfig olddefconfig
BUG=b:122571050
TEST=echo cpufreq-map > /sys/class/devfreq/devfreq0/governor;
observe /sys/class/devfreq/devfreq0/trans_stat
Change-Id: Ie822b0fc47dc04a9019383dd079854b73e8840e9
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
CHROMIUM: arm64: dts: mt8183: set devfreq-cpufreq-map for mt8183-cci
Set cpu frequency to cci frequency mapping table.
BUG=b:122571050
TEST=boot to kukui
Change-Id: I531cd70c98fc86155eb99a932737cb3ed0d02fb5
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
WIP: devfreq: mt8183-cci: using cpufreq-map governor in cci dvfs driver
1. remove mtk_cci_vmon governor, using cpufreq-map
2. SVS: TBD
BUG=b:122571050
TEST=cat /sys/class/devfreq/devfreq0/governor
TEST=run speedometer
Change-Id: I4c4da92dde5f369aaf07a55761f3f9cdc9e80f44
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
FIXUP: arm64: dts: mediatek: Modify opp table for cpu big cluster for mt8183
Modify opp table for cpu big cluster for mt8183
BUG=b:129039370
TEST=build and boot to shell
Change-Id: I54569c513c36db0e08011d0a4f474b1e8808ae3a
Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
DO-NOT-SUBMIT: Snapshot of iommu tot
Snapshot of iommu tot. (CL:1369894/26)
BUG=b:109911488
TEST=Boot to shell
Change-Id: Iec62b81c8e3162110723d7b6e6e759d3672b3af8
Signed-off-by: CK Hu <ck.hu@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
WIP: arm64: dts: mediatek: Get rid of mediatek,larb for MM nodes
After adding device_link between the IOMMU consumer and smi,
the mediatek,larb is unnecessary now.
Change-Id: I3b4457af3df3bc51705af618cb09085953fbcd12
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
WIP: drm/panel: add panel driver for boe-tv101wum
BUG=b:129299873
TEST=build and boot to shell
Change-Id: I08d1ddb1a2d368ccbcd1e358cb5e302b8161328b
Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
CHROMIUM: config: enable boe TV101WUM panel support
The change is generated from the following commands:
cat <<EOF | tee -a \
chromeos/config/arm64/chromiumos-arm64.flavour.config \
chromeos/config/arm64/chromiumos-mediatek.flavour.config
CONFIG_DRM_PANEL_BOE_TV101WUM=y
EOF
./chromeos/scripts/kernelconfig olddefconfig
BUG=b:129299873
TEST=build and boot to shell
Change-Id: Ice61a327f17e69bd2207a9033dda7460ec078765
Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
CHROMIUM: arm64: dts: mt8183: add krane rev3 board dts and Makefile
add krane rev3 board dts and Makefile
BUG=b:131115073
TEST=build and boot to shell
Change-Id: I65906cf9a89353c3040e751b85bd2f9710f74802
Signed-off-by: Ben Ho <Ben.Ho@mediatek.com>
CHROMIUM: arm64: dts: mt8183-kukui: add wifi power controller
To comply with schematic design, remove gpio119 from
mmc1_fixed_power and add it back as wlan_en pin in
mmc1default. msdcpll is only for mmc module. Assign
msdcpll to mmc1 clk for avoiding unexpected changes.
BUG=b:131043339
TEST=Cherry-pick and update kernel with
https://crrev.com/c/1585667. Make sure SDIO clk
is running at 200MHz correctly by checking
/sys/kernel/debug/mmc1/ios
Change-Id: I325df93ae939e929618f7234f18c674cce4e4138
Signed-off-by: jjian zhou <jjian.zhou@mediatek.com>
Signed-off-by: Ayo Wu <ayowu@chromium.org>
DO-NOT-SUBMIT: Kukui MTK ToT
Collect MTK patches on chromeos-4.19
BUG=b:109911488
TEST=Boot to shell
Change-Id: Ifed5c7cb2dacf916c2ac41c4a70f07215f46f0d7
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
CHROMIUM: config: enable BOE HIMAX8279D config
The change is generated from the following commands:
cat <<EOF | tee -a \
chromeos/config/arm64/chromiumos-arm64.flavour.config \
chromeos/config/arm64/chromiumos-mediatek.flavour.config
CONFIG_DRM_PANEL_BOE_HIMAX8279D=y
EOF
./chromeos/scripts/kernelconfig olddefconfig
BUG=b:128652504
TEST=None
Change-Id: Idc9444ee10a99a994839cc686c8ec1d0e05a9130
WIP: CHROMIUM: arm64: dts: mt8183: add flapjack board rev3 dts and Makefile
Add flapjack board rev3 dts and Makefile.
1. Board ID of P0C and P1 is 3.
2. SKU ID Map:
0: CBI is blank
1: 8 inch flapjack
3: 10 inch flapjack
3. Display Panel Info
hwconfig0: boe,himax8279d10p
hwconfig1: boe,himax8279d8p
TO-DO: The hwconfig may changes in future.
BUG=b:124634888
TEST=build and boot to shell
Change-Id: Iee95096bf8ddabe0747b5d8adc735c4bae209c3d
Signed-off-by: Kaka Ni <nigang@huaqin.corp-partner.google.com>
CHROMIUM: arm64: dts: mt8183: Support Wacom W9015A for flapjack
Enable Stylus Wacom W9015A for flapjack
BUG=b:124639007
TEST=1). Boot to shell
2). Run "evtest" in console and get results :
Available devices:
/dev/input/event0: hid-over-i2c 2D1F:490C
/dev/input/event1: hid-over-i2c 2D1F:490C Pen
Change-Id: I3d9ae8fd61350f0e73c8b5f5d4ebcba9d851acd4
Signed-off-by: Kaka Ni <nigang@huaqin.corp-partner.google.com>
DO-NOT-SUBMIT:ASoC: mt8183: machine driver support da7219
Cherry-picks CL:1520431
Only for Huaqin Flapjack ToT
BUG=b:124717947
TEST=build pass and boot to shell
Change-Id: Idbdc9bb99f7d4b3ce1d5ff1ff4c344a53b939295
WIP: CHROMIUM: config: enable SND_SOC_MT8183_DA7219_MAX98357A
Cherry-picks CL:1424761
Only for Huaqin Flapjack ToT
BUG=None
TEST=None
Change-Id: I94c3b3b229c7dda4124dbc42895b2ae78ed6cdee
WIP: CHROMIUM: arm64: dts: mt8183: Support DA7219
Cherry-picks CL:1424761
Only for Huaqin Flapjack ToT
BUG=None
TEST=None
Change-Id: I8683080325dae35133a9981b3af10d68b5412345
DO-NOT-SUBMIT:max98357a:add dai without triggered by pcm
Cherry-picks CL:1520429
Only for Huaqin Flapjack ToT
max98357a's enable pin need setting independently
when max98357a is shared I2S with other codec.
add dai "max98357a-hifi" without pcm trigger,
and use "Spk PA Switch" to set the enable pin.
BRANCH=none
BUG=b:124721198
TEST= build flapjack ok, and can boot up to shell.
Change-Id: I81e4c091f501d10315b829eb78e7c18cecbfac9f
WIP:flapjack:separate speaker control from pcm
use dai "max98357a-hifi" to separate speaker control from pcm
BRANCH=none
BUG=b:124721198
TEST=local build test ok.
Change-Id: I5dc7c5932b9331dd395adcdad0d3aacb740a72fc
DO-NOT-SUBMIT: CHROMIUM: iio: Add SEMTECH SX9311 sensor driver
Add SEMTECH SX9311 driver. just include it in Flapjack ToT Tree.
BUG=b:124858024
BRANCH=None
TEST=On Nocturne, check:
- that the device is correctly probed and instantiated;
- that it is possible to enable events on all channels and read from /dev
- can test with toolkit
Change-Id: Id7d38b30d2a66dfdbe78a1c86e4428e5f2207f7d
DO-NOT-SUBMIT: thermal: mediatek: mt8183: fix bank number settings
Cherry-picked from CL:1510928 to Huaqin ToT
mt8183 does not have bank.
The micro of MT8183_NUM_ZONES should set to 1.
Fixes: a4ffe6b52d27 ("thermal: mediatek: add support for MT8183")
Change-Id: I6c4d6e37dd40ff9129d0c43eb697afa60c94309a
Signed-off-by: Michael Kao <michael.kao@mediatek.com>
TEST-ONLY: drm/bridge: add it6505 driver
This CL is only for Flapjack debug to fix re-plug in can't be recognized
issue.
Please DO-NOT-SUBMIT.
support it6505
BUG=b:109911488
TEST= no
Change-Id: I3014cd5db5a0efe1edbd4d5c158d1b010015550c
DO-NOT-SUBMIT: Add Auo nt51021d and Inx ota7290d MIPI-DSI LCD panel
BUG=None
TEST=build and boot to shell
Change-Id: I1e8cc7f39d62fc29bd0561968cd453b2c20abc99
DO-NOT-SUBMIT: Change 8inch 1st panel boe-tv080wum-ng0 to normal scan
BUG=None
TEST=build and boot to shell
Change-Id: I189e19cb4ea128b3b0eb271ab760bf87f5bd3474
DO-NOT-SUBMIT: Change 10inch 1st panel boe-tv101wum-ng0 to normal scan
BUG=None
TEST=build and boot to shell
Change-Id: I6761fb2d49f53888206f1ab56007ff4638da93d9
CHROMIUM: arm64: dts: mt8183: Modify flapjack panel config
SKU_ID w/o LCM_ID 0x1:
8inch boe,tv080wum_ng0: mt8183-flapjack-rev4-sku1-hwconfig2
8inch auo,nt51021d8p: mt8183-flapjack-rev4-sku1-hwconfig4
SKU_ID w/o LCM_ID 0x3:
10inch boe,tv101wum_ng0: mt8183-flapjack-rev4-sku3-hwconfig1
10inch inx,ota7290d10p: mt8183-flapjack-rev4-sku3-hwconfig3
BUG=None
TEST=build and boot to shell
Change-Id: I43120b7feb54cd6b11463174b5fa2e54e87f660a
CHROMIUM: drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel
orientation) from the device tree.
BUG=b:121173026
TEST=emerge-flapjack chromeos-kernel-4_14
Change-Id: I5a195c3aa23346aff4629967b891b89357056544
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
CHROMIUM: drm/panel: Add attach/detach callbacks
This adds the attach/detach callbacks. These are for setting up
internal state for the connector/panel pair that can't be done at
probe (since the connector doesn't exist) and which don't need to be
repeatedly done for every get/modes, prepare, or enable callback.
Values such as the panel orientation, and display size can be filled
in for the connector.
BUG=b:121173026
TEST=emerge-flapjack chromeos-kernel-4_19
Change-Id: I9d1f56ce585a561e82068cc373a8f636643c1e33
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
CHROMIUM: drm/panel: add boe himax8279d orientation
This adds reading the panel orientation from the device tree to the
boe himax8279d panel driver. This is done by adding the drm_panel
attach callback. The width_mm, heigh_mm, and bpc values are also
updated for the connector display info in this function since it makes
more sense there than in get_modes (which is called multiple times).
BUG=b:121173026
TEST=boot flapjack
Change-Id: I2b75f22c101aedc986d6d086657965e3f3e4615b
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
CHROMIUM: drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver
if the panel orientation (connector.display_info.panel_orientation) is
not DRM_MODE_PANEL_ORIENTATION_UNKNOWN.
BUG=b:121173026
TEST=boot Flapjack
Change-Id: I3955e2ff0d633586cc77b34a649b385cf9c3aa19
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
HACK: drm/mtk: set plane rotation based on panel orientation
This sets a 180 degree rotation if there's an upside down panel. This
is only a temporary solution until userspace handles this properly by
specifying the rotation itself when the panel is upside down.
BUG=b:121173026
TEST=boot flapjack
Change-Id: I8f2d3c154610ee1837d1f2af6e6c22f85e790fc2
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
DO NOT COMMIT: dts: mediatek: add rotation property for flapjack
This adds the default rotation property for flapjack panels.
BUG=b:121173026
TEST=boot flapjack and check that the display isn't flipped
Change-Id: I7d29173f4e159dc6fac1bd2263483325e09980bc
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
WIP: CHROMIUM: arm64: dts: mt8183: add flapjack board rev5 compatible
Currently, LCM_ID are pulled up to 1800 mV. This causes inaccurate
reading by ADC.
We change the pull-up to 3300 mV. This patch adjusts the thresholds
accordingly.
we add new board version for this change
Change-Id: I1dfb38f58f1affd99a0f9fbb5cca9aa5c1f029f9
DO-NOT-SUBMIT: WIFI FTM patch
BUG=b:124327202
BRANCH=none
TEST=build pass and support the FTM mode
Change-Id: I43280a12cebe088a91e7ef96c2ba2d688efe614b
TEST-ONLY: set dpi pins as gpio and output low when dpi disabled
Pull dpi pins low when dpi has nothing to display. Or theree will be
Some dpi pins (Hsync Vsync DE ... ) keeping high voltage. And will
cause leadage.
Please DO-NOT-SUBMIT.
BUG=b:132674731
TEST=build and boot to shell
Change-Id: I6b6cfab647cb05357d717590140346a5a746ab9c
DO-NOT-SUBMIT: Flapjack Huaqin ToT
Collect Huaqin patches on chromeos-4.19
Rely On MTK's Tot Tree: CL:1317245
BUG=b:124595117
TEST=Boot to shell
Change-Id: Iaec249f694c9a1aaff3236bdfd098194e8d64a4a
---
.../bindings/iio/proximity/sx9311.txt | 19 +
README | 3 +-
arch/arm64/boot/dts/mediatek/Makefile | 4 +
arch/arm64/boot/dts/mediatek/mt6358.dtsi | 4 +-
.../mt8183-flapjack-rev4-sku1-hwconfig2.dts | 278 ++
.../mt8183-flapjack-rev4-sku1-hwconfig4.dts | 267 ++
.../mt8183-flapjack-rev4-sku3-hwconfig1.dts | 280 ++
.../mt8183-flapjack-rev4-sku3-hwconfig3.dts | 268 ++
.../boot/dts/mediatek/mt8183-flapjack.dtsi | 140 +
.../arm64/boot/dts/mediatek/mt8183-kukui.dtsi | 111 +
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 11 +
.../arm64/chromiumos-arm64.flavour.config | 1 +
.../arm64/chromiumos-mediatek.flavour.config | 15 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/ite-it6505.c | 2948 +++++++++++++++++
drivers/gpu/drm/drm_panel.c | 38 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 14 +
drivers/gpu/drm/mediatek/mtk_dpi.c | 13 +-
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 28 +
drivers/gpu/drm/mediatek/mtk_dsi.c | 18 +
drivers/gpu/drm/panel/panel-boe-himax8279d.c | 954 +++++-
drivers/iio/proximity/Kconfig | 13 +
drivers/iio/proximity/Makefile | 1 +
drivers/iio/proximity/sx9311.c | 1144 +++++++
drivers/net/wireless/ath/ath10k/core.c | 2 +-
drivers/net/wireless/ath/ath10k/hif.h | 6 +-
drivers/net/wireless/ath/ath10k/sdio.c | 5 +-
drivers/thermal/mtk_thermal.c | 2 -
include/drm/drm_panel.h | 11 +
sound/soc/codecs/max98357a.c | 96 +-
.../mediatek/mt8183/mt8183-da7219-max98357.c | 2 +-
31 files changed, 6656 insertions(+), 41 deletions(-)
create mode 100644 Documentation/devicetree/bindings/iio/proximity/sx9311.txt
create mode 100755 arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig2.dts
create mode 100755 arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig4.dts
create mode 100755 arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig1.dts
create mode 100755 arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig3.dts
create mode 100644 arch/arm64/boot/dts/mediatek/mt8183-flapjack.dtsi
create mode 100755 drivers/gpu/drm/bridge/ite-it6505.c
create mode 100644 drivers/iio/proximity/sx9311.c
mode change 100644 => 100755 sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
diff --git a/Documentation/devicetree/bindings/iio/proximity/sx9311.txt b/Documentation/devicetree/bindings/iio/proximity/sx9311.txt
new file mode 100644
index 000000000000..65a1114e4147
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/proximity/sx9311.txt
@@ -0,0 +1,19 @@
+Semtech's SX9311 capacitive proximity device driver
+
+Required properties:
+ - compatible: must be "semtech,sx9311"
+ - reg: i2c address where to find the device
+ - interrupts : the sole interrupt generated by the device
+
+ Refer to interrupt-controller/interrupts.txt for generic
+ interrupt client node bindings.
+
+Example:
+
+sx9311@28 {
+ compatible = "semtech,sx9311";
+ reg = <0x28>;
+ interrupt-parent = <&pio>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW 5 0>;
+ int-gpio = <&pio 5 0>;
+ };
diff --git a/README b/README
index 768caa3970ef..5f0f9bcd9863 100644
--- a/README
+++ b/README
@@ -1,6 +1,5 @@
+HUAQIN FLAPJACK TOT
MTK TOT
-Linux kernel
-============
There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index d09409979c84..95c7896b6d19 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -11,3 +11,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-krane-rev3.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-rev1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-rev2.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-flapjack-rev4-sku1-hwconfig2.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-flapjack-rev4-sku1-hwconfig4.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-flapjack-rev4-sku3-hwconfig1.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-flapjack-rev4-sku3-hwconfig3.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt6358.dtsi b/arch/arm64/boot/dts/mediatek/mt6358.dtsi
index a7e655c42a54..f31345ef16b3 100644
--- a/arch/arm64/boot/dts/mediatek/mt6358.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6358.dtsi
@@ -349,8 +349,8 @@
mt6358_vsim2_reg: ldo_vsim2 {
regulator-name = "vsim2";
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <3100000>;
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
regulator-enable-ramp-delay = <540>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig2.dts b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig2.dts
new file mode 100755
index 000000000000..baec567d4975
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig2.dts
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2019 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/dts-v1/;
+#include "mt8183-flapjack.dtsi"
+
+/ {
+ model = "MediaTek Flapjack Rev 4 board Sku 1 BOE TV080WUM NG0";
+
+ /* SKU_ID: 0x20001 BOE_TV080WUM_NG0 for REV >=3 */
+ compatible = "google,flapjack-rev3-sku131073",
+ "google,flapjack-rev4-sku131073",
+ "google,flapjack-rev5-sku131073",
+ "google,flapjack-sku131073",
+
+ /* SKU_ID: 0x1 for Rev 2 */
+ "google,flapjack-rev2-sku1",
+
+ /* SKU_ID: 0x50001 Panel Unknown */
+ "google,flapjack-rev2-sku327681",
+ "google,flapjack-rev3-sku327681",
+ "google,flapjack-rev4-sku327681",
+ "google,flapjack-rev5-sku327681",
+ "google,flapjack-sku327681",
+
+ "google,flapjack-rev2",
+ "google,flapjack-rev3",
+ "google,flapjack-rev4",
+ "google,flapjack",
+ "google,kukui", "mediatek,mt8183";
+};
+
+&dsi0 {
+ /delete-node/ panel@0;
+ panel: panel@0 {
+ compatible = "boe,tv080wum_ng0";
+ reg = <0>;
+ enable-gpios = <&pio 45 0>;
+ pp33-gpios = <&pio 35 0>;
+ pp18-gpios = <&pio 36 0>;
+ pinctrl-names = "default", "state_3300mv", "state_1800mv";
+ pinctrl-0 = <&panel_pins_default>;
+ pinctrl-1 = <&panel_pins_3300mv>;
+ pinctrl-2 = <&panel_pins_1800mv>;
+ backlight = <&backlight_lcd0>;
+ rotation = <180>;
+ status = "okay";
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+};
+
+
+&it6505dptx{
+ ovdd-supply = <&mt6358_vsim2_reg>;
+};
+
+&pio {
+ /* 192 lines */
+ gpio-line-names =
+ "SPI_AP_EC_CS_L",
+ "SPI_AP_EC_MOSI",
+ "SPI_AP_EC_CLK",
+ "I2S3_DO",
+ "USB_PD_INT_ODL",
+ "",
+ "",
+ "",
+ "",
+ "IT6505_HPD_L",
+ "I2S3_TDM_D3",
+ "SOC_I2C6_1V8_SCL",
+ "SOC_I2C6_1V8_SDA",
+ "DPI_D0",
+ "DPI_D1",
+ "DPI_D2",
+ "DPI_D3",
+ "DPI_D4",
+ "DPI_D5",
+ "DPI_D6",
+ "DPI_D7",
+ "DPI_D8",
+ "DPI_D9",
+ "DPI_D10",
+ "DPI_D11",
+ "DPI_HSYNC",
+ "DPI_VSYNC",
+ "DPI_DE",
+ "DPI_CK",
+ "AP_MSDC1_CLK",
+ "AP_MSDC1_DAT3",
+ "AP_MSDC1_CMD",
+ "AP_MSDC1_DAT0",
+ "AP_MSDC1_DAT2",
+ "AP_MSDC1_DAT1",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "OTG_EN",
+ "DRVBUS",
+ "DISP_PWM",
+ "DSI_TE",
+ "LCM_RST_1V8",
+ "AP_CTS_WIFI_RTS",
+ "AP_RTS_WIFI_CTS",
+ "SOC_I2C5_1V8_SCL",
+ "SOC_I2C5_1V8_SDA",
+ "SOC_I2C3_1V8_SCL",
+ "SOC_I2C3_1V8_SDA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SOC_I2C1_1V8_SDA",
+ "SOC_I2C0_1V8_SDA",
+ "SOC_I2C0_1V8_SCL",
+ "SOC_I2C1_1V8_SCL",
+ "AP_SPI_H1_MISO",
+ "AP_SPI_H1_CS_L",
+ "AP_SPI_H1_MOSI",
+ "AP_SPI_H1_CLK",
+ "I2S5_BCK",
+ "I2S5_LRCK",
+ "I2S5_DO",
+ "BOOTBLOCK_EN_L",
+ "MT8183_KPCOL0",
+ "SPI_AP_EC_MISO",
+ "UART_DBG_TX_AP_RX",
+ "UART_AP_TX_DBG_RX",
+ "I2S2_MCK",
+ "I2S2_BCK",
+ "CLK_5M_WCAM",
+ "CLK_2M_UCAM",
+ "I2S2_LRCK",
+ "I2S2_DI",
+ "SOC_I2C2_1V8_SCL",
+ "SOC_I2C2_1V8_SDA",
+ "SOC_I2C4_1V8_SCL",
+ "SOC_I2C4_1V8_SDA",
+ "",
+ "SCL8",
+ "SDA8",
+ "FCAM_PWDN_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ /*
+ * AP_FLASH_WP_L is crossystem ABI. Rev1 schematics
+ * call it BIOS_FLASH_WP_R_L.
+ */
+ "AP_FLASH_WP_L",
+ "EC_AP_INT_ODL",
+ "IT6505_INT_ODL",
+ "H1_INT_OD_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AP_SPI_FLASH_MISO",
+ "AP_SPI_FLASH_CS_L",
+ "AP_SPI_FLASH_MOSI",
+ "AP_SPI_FLASH_CLK",
+ "DA7219_IRQ",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+&scp_pins {
+ /* EINT pins are used for other purpose on rev2. */
+ /delete-node/ pins_eint;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig4.dts b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig4.dts
new file mode 100755
index 000000000000..f341993d584a
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku1-hwconfig4.dts
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2019 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/dts-v1/;
+#include "mt8183-flapjack.dtsi"
+
+/ {
+ model = "MediaTek Flapjack Rev 4 board Sku 1 AUO NT51021D8P";
+
+ /* SKU_ID: 0x40001 AUO_NT51021D8P for REV >=3 */
+ compatible = "google,flapjack-rev3-sku262145",
+ "google,flapjack-rev4-sku262145",
+ "google,flapjack-rev5-sku262145",
+ "google,flapjack-sku262145",
+
+ "google,flapjack-rev3",
+ "google,flapjack-rev4",
+ "google,flapjack",
+ "google,kukui", "mediatek,mt8183";
+};
+
+&dsi0 {
+ /delete-node/ panel@0;
+ panel: panel@0 {
+ compatible = "auo,nt51021d8p";
+ reg = <0>;
+ enable-gpios = <&pio 45 0>;
+ pp33-gpios = <&pio 35 0>;
+ pp18-gpios = <&pio 36 0>;
+ pinctrl-names = "default", "state_3300mv", "state_1800mv";
+ pinctrl-0 = <&panel_pins_default>;
+ pinctrl-1 = <&panel_pins_3300mv>;
+ pinctrl-2 = <&panel_pins_1800mv>;
+ backlight = <&backlight_lcd0>;
+ rotation = <180>;
+ status = "okay";
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+};
+
+
+&it6505dptx{
+ ovdd-supply = <&mt6358_vsim2_reg>;
+};
+
+&pio {
+ /* 192 lines */
+ gpio-line-names =
+ "SPI_AP_EC_CS_L",
+ "SPI_AP_EC_MOSI",
+ "SPI_AP_EC_CLK",
+ "I2S3_DO",
+ "USB_PD_INT_ODL",
+ "",
+ "",
+ "",
+ "",
+ "IT6505_HPD_L",
+ "I2S3_TDM_D3",
+ "SOC_I2C6_1V8_SCL",
+ "SOC_I2C6_1V8_SDA",
+ "DPI_D0",
+ "DPI_D1",
+ "DPI_D2",
+ "DPI_D3",
+ "DPI_D4",
+ "DPI_D5",
+ "DPI_D6",
+ "DPI_D7",
+ "DPI_D8",
+ "DPI_D9",
+ "DPI_D10",
+ "DPI_D11",
+ "DPI_HSYNC",
+ "DPI_VSYNC",
+ "DPI_DE",
+ "DPI_CK",
+ "AP_MSDC1_CLK",
+ "AP_MSDC1_DAT3",
+ "AP_MSDC1_CMD",
+ "AP_MSDC1_DAT0",
+ "AP_MSDC1_DAT2",
+ "AP_MSDC1_DAT1",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "OTG_EN",
+ "DRVBUS",
+ "DISP_PWM",
+ "DSI_TE",
+ "LCM_RST_1V8",
+ "AP_CTS_WIFI_RTS",
+ "AP_RTS_WIFI_CTS",
+ "SOC_I2C5_1V8_SCL",
+ "SOC_I2C5_1V8_SDA",
+ "SOC_I2C3_1V8_SCL",
+ "SOC_I2C3_1V8_SDA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SOC_I2C1_1V8_SDA",
+ "SOC_I2C0_1V8_SDA",
+ "SOC_I2C0_1V8_SCL",
+ "SOC_I2C1_1V8_SCL",
+ "AP_SPI_H1_MISO",
+ "AP_SPI_H1_CS_L",
+ "AP_SPI_H1_MOSI",
+ "AP_SPI_H1_CLK",
+ "I2S5_BCK",
+ "I2S5_LRCK",
+ "I2S5_DO",
+ "BOOTBLOCK_EN_L",
+ "MT8183_KPCOL0",
+ "SPI_AP_EC_MISO",
+ "UART_DBG_TX_AP_RX",
+ "UART_AP_TX_DBG_RX",
+ "I2S2_MCK",
+ "I2S2_BCK",
+ "CLK_5M_WCAM",
+ "CLK_2M_UCAM",
+ "I2S2_LRCK",
+ "I2S2_DI",
+ "SOC_I2C2_1V8_SCL",
+ "SOC_I2C2_1V8_SDA",
+ "SOC_I2C4_1V8_SCL",
+ "SOC_I2C4_1V8_SDA",
+ "",
+ "SCL8",
+ "SDA8",
+ "FCAM_PWDN_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ /*
+ * AP_FLASH_WP_L is crossystem ABI. Rev1 schematics
+ * call it BIOS_FLASH_WP_R_L.
+ */
+ "AP_FLASH_WP_L",
+ "EC_AP_INT_ODL",
+ "IT6505_INT_ODL",
+ "H1_INT_OD_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AP_SPI_FLASH_MISO",
+ "AP_SPI_FLASH_CS_L",
+ "AP_SPI_FLASH_MOSI",
+ "AP_SPI_FLASH_CLK",
+ "DA7219_IRQ",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+&scp_pins {
+ /* EINT pins are used for other purpose on rev2. */
+ /delete-node/ pins_eint;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig1.dts b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig1.dts
new file mode 100755
index 000000000000..7d4e3c4e3b60
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig1.dts
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Device Tree Source for the Google flapjack board
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/dts-v1/;
+#include "mt8183-flapjack.dtsi"
+
+/ {
+ model = "MediaTek Flapjack Rev 4 board Sku 3 BOE TV101WUM NG0";
+
+ /* SKU_ID: 0x10003 BOE_TV101WUM_NG0 for REV >=3 */
+ compatible = "google,flapjack-rev3-sku65539",
+ "google,flapjack-rev4-sku65539",
+ "google,flapjack-rev5-sku65539",
+ "google,flapjack-sku65539",
+
+ /* SKU_ID: 0x3 for Rev 2 */
+ "google,flapjack-rev2-sku3",
+
+ /* SKU_ID: 0x50003 Panel Unknown */
+ "google,flapjack-rev2-sku327683",
+ "google,flapjack-rev3-sku327683",
+ "google,flapjack-rev4-sku327683",
+ "google,flapjack-rev5-sku327683",
+ "google,flapjack-sku327683",
+
+ "google,flapjack-rev2",
+ "google,flapjack-rev3",
+ "google,flapjack-rev4",
+ "google,flapjack",
+ "google,kukui", "mediatek,mt8183";
+};
+
+&dsi0 {
+ /delete-node/ panel@0;
+ panel: panel@0 {
+ compatible = "boe,tv101wum_ng0";
+ reg = <0>;
+ enable-gpios = <&pio 45 0>;
+ pp33-gpios = <&pio 35 0>;
+ pp18-gpios = <&pio 36 0>;
+ pinctrl-names = "default", "state_3300mv", "state_1800mv";
+ pinctrl-0 = <&panel_pins_default>;
+ pinctrl-1 = <&panel_pins_3300mv>;
+ pinctrl-2 = <&panel_pins_1800mv>;
+ backlight = <&backlight_lcd0>;
+ rotation = <180>;
+ status = "okay";
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+};
+
+
+&it6505dptx{
+ ovdd-supply = <&mt6358_vsim2_reg>;
+};
+
+&pio {
+ /* 192 lines */
+ gpio-line-names =
+ "SPI_AP_EC_CS_L",
+ "SPI_AP_EC_MOSI",
+ "SPI_AP_EC_CLK",
+ "I2S3_DO",
+ "USB_PD_INT_ODL",
+ "",
+ "",
+ "",
+ "",
+ "IT6505_HPD_L",
+ "I2S3_TDM_D3",
+ "SOC_I2C6_1V8_SCL",
+ "SOC_I2C6_1V8_SDA",
+ "DPI_D0",
+ "DPI_D1",
+ "DPI_D2",
+ "DPI_D3",
+ "DPI_D4",
+ "DPI_D5",
+ "DPI_D6",
+ "DPI_D7",
+ "DPI_D8",
+ "DPI_D9",
+ "DPI_D10",
+ "DPI_D11",
+ "DPI_HSYNC",
+ "DPI_VSYNC",
+ "DPI_DE",
+ "DPI_CK",
+ "AP_MSDC1_CLK",
+ "AP_MSDC1_DAT3",
+ "AP_MSDC1_CMD",
+ "AP_MSDC1_DAT0",
+ "AP_MSDC1_DAT2",
+ "AP_MSDC1_DAT1",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "OTG_EN",
+ "DRVBUS",
+ "DISP_PWM",
+ "DSI_TE",
+ "LCM_RST_1V8",
+ "AP_CTS_WIFI_RTS",
+ "AP_RTS_WIFI_CTS",
+ "SOC_I2C5_1V8_SCL",
+ "SOC_I2C5_1V8_SDA",
+ "SOC_I2C3_1V8_SCL",
+ "SOC_I2C3_1V8_SDA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SOC_I2C1_1V8_SDA",
+ "SOC_I2C0_1V8_SDA",
+ "SOC_I2C0_1V8_SCL",
+ "SOC_I2C1_1V8_SCL",
+ "AP_SPI_H1_MISO",
+ "AP_SPI_H1_CS_L",
+ "AP_SPI_H1_MOSI",
+ "AP_SPI_H1_CLK",
+ "I2S5_BCK",
+ "I2S5_LRCK",
+ "I2S5_DO",
+ "BOOTBLOCK_EN_L",
+ "MT8183_KPCOL0",
+ "SPI_AP_EC_MISO",
+ "UART_DBG_TX_AP_RX",
+ "UART_AP_TX_DBG_RX",
+ "I2S2_MCK",
+ "I2S2_BCK",
+ "CLK_5M_WCAM",
+ "CLK_2M_UCAM",
+ "I2S2_LRCK",
+ "I2S2_DI",
+ "SOC_I2C2_1V8_SCL",
+ "SOC_I2C2_1V8_SDA",
+ "SOC_I2C4_1V8_SCL",
+ "SOC_I2C4_1V8_SDA",
+ "",
+ "SCL8",
+ "SDA8",
+ "FCAM_PWDN_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ /*
+ * AP_FLASH_WP_L is crossystem ABI. Rev1 schematics
+ * call it BIOS_FLASH_WP_R_L.
+ */
+ "AP_FLASH_WP_L",
+ "EC_AP_INT_ODL",
+ "IT6505_INT_ODL",
+ "H1_INT_OD_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AP_SPI_FLASH_MISO",
+ "AP_SPI_FLASH_CS_L",
+ "AP_SPI_FLASH_MOSI",
+ "AP_SPI_FLASH_CLK",
+ "DA7219_IRQ",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+&scp_pins {
+ /* EINT pins are used for other purpose on rev2. */
+ /delete-node/ pins_eint;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig3.dts b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig3.dts
new file mode 100755
index 000000000000..2a77a3f521b4
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8183-flapjack-rev4-sku3-hwconfig3.dts
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Device Tree Source for the Google flapjack board
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/dts-v1/;
+#include "mt8183-flapjack.dtsi"
+
+/ {
+ model = "MediaTek Flapjack Rev 3 board Sku 3 INX OTA7290D10P";
+ /* SKU_ID: 0x30003 INX OTA7290D10 for REV >=3 */
+ compatible = "google,flapjack-rev3-sku196611",
+ "google,flapjack-rev4-sku196611",
+ "google,flapjack-rev5-sku196611",
+ "google,flapjack-sku196611",
+
+
+ "google,flapjack-rev3",
+ "google,flapjack-rev4",
+ "google,flapjack",
+ "google,kukui", "mediatek,mt8183";
+};
+
+&dsi0 {
+ /delete-node/ panel@0;
+ panel: panel@0 {
+ compatible = "inx,ota7290d10p";
+ reg = <0>;
+ enable-gpios = <&pio 45 0>;
+ pp33-gpios = <&pio 35 0>;
+ pp18-gpios = <&pio 36 0>;
+ pinctrl-names = "default", "state_3300mv", "state_1800mv";
+ pinctrl-0 = <&panel_pins_default>;
+ pinctrl-1 = <&panel_pins_3300mv>;
+ pinctrl-2 = <&panel_pins_1800mv>;
+ backlight = <&backlight_lcd0>;
+ rotation = <180>;
+ status = "okay";
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+};
+
+&it6505dptx{
+ ovdd-supply = <&mt6358_vsim2_reg>;
+};
+
+&pio {
+ /* 192 lines */
+ gpio-line-names =
+ "SPI_AP_EC_CS_L",
+ "SPI_AP_EC_MOSI",
+ "SPI_AP_EC_CLK",
+ "I2S3_DO",
+ "USB_PD_INT_ODL",
+ "",
+ "",
+ "",
+ "",
+ "IT6505_HPD_L",
+ "I2S3_TDM_D3",
+ "SOC_I2C6_1V8_SCL",
+ "SOC_I2C6_1V8_SDA",
+ "DPI_D0",
+ "DPI_D1",
+ "DPI_D2",
+ "DPI_D3",
+ "DPI_D4",
+ "DPI_D5",
+ "DPI_D6",
+ "DPI_D7",
+ "DPI_D8",
+ "DPI_D9",
+ "DPI_D10",
+ "DPI_D11",
+ "DPI_HSYNC",
+ "DPI_VSYNC",
+ "DPI_DE",
+ "DPI_CK",
+ "AP_MSDC1_CLK",
+ "AP_MSDC1_DAT3",
+ "AP_MSDC1_CMD",
+ "AP_MSDC1_DAT0",
+ "AP_MSDC1_DAT2",
+ "AP_MSDC1_DAT1",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "OTG_EN",
+ "DRVBUS",
+ "DISP_PWM",
+ "DSI_TE",
+ "LCM_RST_1V8",
+ "AP_CTS_WIFI_RTS",
+ "AP_RTS_WIFI_CTS",
+ "SOC_I2C5_1V8_SCL",
+ "SOC_I2C5_1V8_SDA",
+ "SOC_I2C3_1V8_SCL",
+ "SOC_I2C3_1V8_SDA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SOC_I2C1_1V8_SDA",
+ "SOC_I2C0_1V8_SDA",
+ "SOC_I2C0_1V8_SCL",
+ "SOC_I2C1_1V8_SCL",
+ "AP_SPI_H1_MISO",
+ "AP_SPI_H1_CS_L",
+ "AP_SPI_H1_MOSI",
+ "AP_SPI_H1_CLK",
+ "I2S5_BCK",
+ "I2S5_LRCK",
+ "I2S5_DO",
+ "BOOTBLOCK_EN_L",
+ "MT8183_KPCOL0",
+ "SPI_AP_EC_MISO",
+ "UART_DBG_TX_AP_RX",
+ "UART_AP_TX_DBG_RX",
+ "I2S2_MCK",
+ "I2S2_BCK",
+ "CLK_5M_WCAM",
+ "CLK_2M_UCAM",
+ "I2S2_LRCK",
+ "I2S2_DI",
+ "SOC_I2C2_1V8_SCL",
+ "SOC_I2C2_1V8_SDA",
+ "SOC_I2C4_1V8_SCL",
+ "SOC_I2C4_1V8_SDA",
+ "",
+ "SCL8",
+ "SDA8",
+ "FCAM_PWDN_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "I2S_PMIC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ /*
+ * AP_FLASH_WP_L is crossystem ABI. Rev1 schematics
+ * call it BIOS_FLASH_WP_R_L.
+ */
+ "AP_FLASH_WP_L",
+ "EC_AP_INT_ODL",
+ "IT6505_INT_ODL",
+ "H1_INT_OD_L",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AP_SPI_FLASH_MISO",
+ "AP_SPI_FLASH_CS_L",
+ "AP_SPI_FLASH_MOSI",
+ "AP_SPI_FLASH_CLK",
+ "DA7219_IRQ",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+&scp_pins {
+ /* EINT pins are used for other purpose on rev2. */
+ /delete-node/ pins_eint;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-flapjack.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-flapjack.dtsi
new file mode 100644
index 000000000000..7bcc6d8e5b62
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8183-flapjack.dtsi
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Device Tree Source for the Google flapjack board
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "mt8183-kukui.dtsi"
+
+/ {
+ /delete-node/ mt8183-mt6358-ts3a227e-max98357a;
+
+ sound: mt8183-da7219-max98357a {
+ compatible = "mediatek,mt8183_da7219_max98357";
+ mediatek,platform = <&afe>;
+ mediatek,headset-codec = <&da7219>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins>;
+ status = "okay";
+ };
+};
+
+&i2c0 {
+ /delete-node/ digitizer@9;
+ /delete-node/ touchscreen@10;
+
+ touchscreen@0a {
+ compatible = "hid-over-i2c";
+ reg = <0x0a>;
+ interrupt-parent = <&pio>;
+ interrupts = <155 IRQ_TYPE_LEVEL_LOW 155>;
+ int-gpio = <&pio 155 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_default>;
+ hid-descr-addr = <0x1>;
+ wakeup-source;
+ };
+};
+
+&i2c1 {
+ sx9311@28 {
+ compatible = "semtech,sx9311";
+ reg = <0x28>;
+ interrupt-parent = <&pio>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sx9311_pins>;
+ };
+};
+
+&i2c5 {
+ /delete-node/ ts3a227e@3b;
+ da7219: da7219@1a {
+ pinctrl-names = "default";
+ pinctrl-0 = <&da7219_pins>;
+ compatible = "dlg,da7219";
+ reg = <0x1a>;
+ interrupt-parent = <&pio>;
+ interrupts = <165 IRQ_TYPE_LEVEL_LOW 165>;
+
+ dlg,micbias-lvl = <2600>;
+ dlg,mic-amp-in-sel = "diff";
+
+ da7219_aad {
+ dlg,adc-1bit-rpt = <1>;
+ dlg,btn-avg = <4>;
+ dlg,btn-cfg = <50>;
+ dlg,mic-det-thr = <500>;
+ dlg,jack-ins-deb = <20>;
+ dlg,jack-det-rate = "32ms_64ms";
+ dlg,jack-rem-deb = <1>;
+
+ dlg,a-d-btn-thr = <0xa>;
+ dlg,d-b-btn-thr = <0x16>;
+ dlg,b-c-btn-thr = <0x21>;
+ dlg,c-mic-btn-thr = <0x3E>;
+ };
+ };
+};
+
+&pio {
+ /delete-node/ ts3a227e_pins;
+
+ da7219_pins: da7219_pins {
+ pins1 {
+ pinmux = <PINMUX_GPIO165__FUNC_GPIO165>;
+ input-enable;
+ bias-enable;
+ bias-pull-up;
+ };
+ };
+
+ panel_pins_1800mv: panel_pins_1800mv {
+ pins_cmd_dat {
+ pinmux = <PINMUX_GPIO36__FUNC_GPIO36>;
+ output-low;
+ bias-pull-up;
+ };
+ };
+
+ panel_pins_3300mv: panel_pins_3300mv {
+ pins_cmd_dat {
+ pinmux = <PINMUX_GPIO35__FUNC_GPIO35>;
+ output-low;
+ bias-pull-up;
+ };
+ };
+
+ /delete-node/ touchdefault;
+ touch_default: touchdefault {
+ pin_irq {
+ pinmux = <PINMUX_GPIO155__FUNC_GPIO155>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ touch_pin_reset: pin_reset {
+ pinmux = <PINMUX_GPIO156__FUNC_GPIO156>;
+ output-low;
+ };
+ };
+
+ sx9311_pins: sx9311_pins {
+ pins_eint {
+ pinmux = <PINMUX_GPIO5__FUNC_GPIO5>;
+ input-enable;
+ };
+ };
+};
+
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
index e93b0587cfbc..aa67bb4cedcf 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
@@ -73,6 +73,15 @@
regulator-max-microvolt = <1800000>;
};
+ it6505_pp18_reg: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "it6505_pp18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&pio 178 0>;
+ enable-active-high;
+ };
+
reserved_memory: reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
@@ -162,6 +171,18 @@
proc-supply = <&mt6358_vproc11_reg>;
};
+&dpi0 {
+ pinctrl-names = "default", "dpimode";
+ pinctrl-0 = <&dpi_pin_default>;
+ pinctrl-1 = <&dpi_pin_func>;
+ status = "okay";
+ port {
+ dpi_out: endpoint {
+ remote-endpoint = <&it6505_in>;
+ };
+ };
+};
+
&dsi0 {
status = "okay";
#address-cells = <1>;
@@ -237,6 +258,29 @@
pinctrl-0 = <&i2c3_pins>;
status = "okay";
clock-frequency = <100000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ it6505dptx: it6505dptx@5c {
+ compatible = "ite,it6505";
+ status = "okay";
+ interrupt-parent = <&pio>;
+ interrupts = <152 IRQ_TYPE_EDGE_RISING 152 0>;
+ reg = <0x5c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&it6505_pins>;
+ ovdd-supply = <&mt6358_vsim1_reg>;
+ pwr18-supply = <&it6505_pp18_reg>;
+ reset-gpios = <&pio 179 1>;
+ hpd-gpios = <&pio 9 0>;
+ cros-ec = <&cros_ec>;
+ extcon = <&usbc_extcon0>;
+ port {
+ it6505_in: endpoint {
+ remote-endpoint = <&dpi_out>;
+ };
+ };
+ };
};
&i2c4 {
@@ -370,6 +414,51 @@
};
};
+ dpi_pin_default: dpi_pin_default{
+ pins_cmd_dat {
+ pinmux = <PINMUX_GPIO13__FUNC_GPIO13>,
+ <PINMUX_GPIO14__FUNC_GPIO14>,
+ <PINMUX_GPIO15__FUNC_GPIO15>,
+ <PINMUX_GPIO16__FUNC_GPIO16>,
+ <PINMUX_GPIO17__FUNC_GPIO17>,
+ <PINMUX_GPIO18__FUNC_GPIO18>,
+ <PINMUX_GPIO19__FUNC_GPIO19>,
+ <PINMUX_GPIO20__FUNC_GPIO20>,
+ <PINMUX_GPIO21__FUNC_GPIO21>,
+ <PINMUX_GPIO22__FUNC_GPIO22>,
+ <PINMUX_GPIO23__FUNC_GPIO23>,
+ <PINMUX_GPIO24__FUNC_GPIO24>,
+ <PINMUX_GPIO25__FUNC_GPIO25>,
+ <PINMUX_GPIO26__FUNC_GPIO26>,
+ <PINMUX_GPIO27__FUNC_GPIO27>,
+ <PINMUX_GPIO28__FUNC_GPIO28>;
+ drive-strength = <MTK_DRIVE_6mA>;
+ output-low;
+ };
+ };
+
+ dpi_pin_func: dpi_pin_func {
+ pins_cmd_dat {
+ pinmux = <PINMUX_GPIO13__FUNC_DBPI_D0>,
+ <PINMUX_GPIO14__FUNC_DBPI_D1>,
+ <PINMUX_GPIO15__FUNC_DBPI_D2>,
+ <PINMUX_GPIO16__FUNC_DBPI_D3>,
+ <PINMUX_GPIO17__FUNC_DBPI_D4>,
+ <PINMUX_GPIO18__FUNC_DBPI_D5>,
+ <PINMUX_GPIO19__FUNC_DBPI_D6>,
+ <PINMUX_GPIO20__FUNC_DBPI_D7>,
+ <PINMUX_GPIO21__FUNC_DBPI_D8>,
+ <PINMUX_GPIO22__FUNC_DBPI_D9>,
+ <PINMUX_GPIO23__FUNC_DBPI_D10>,
+ <PINMUX_GPIO24__FUNC_DBPI_D11>,
+ <PINMUX_GPIO25__FUNC_DBPI_HSYNC>,
+ <PINMUX_GPIO26__FUNC_DBPI_VSYNC>,
+ <PINMUX_GPIO27__FUNC_DBPI_DE>,
+ <PINMUX_GPIO28__FUNC_DBPI_CK>;
+ drive-strength = <MTK_DRIVE_6mA>;
+ };
+ };
+
ec_ap_int_odl: ec_ap_int_odl {
pins1 {
pinmux = <PINMUX_GPIO151__FUNC_GPIO151>;
@@ -455,6 +544,22 @@
};
};
+ it6505_pins: it6505_pins{
+ pins_cmd_dat {
+ pinmux = <PINMUX_GPIO178__FUNC_GPIO178>,
+ <PINMUX_GPIO179__FUNC_GPIO179>;
+ output-low;
+ bias-pull-up;
+ };
+
+ pins_cmd_dat1 {
+ pinmux = <PINMUX_GPIO9__FUNC_GPIO9>,
+ <PINMUX_GPIO152__FUNC_GPIO152>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
mmc0_pins_default: mmc0default {
pins_cmd_dat {
pinmux = <PINMUX_GPIO123__FUNC_MSDC0_DAT0>,
@@ -774,6 +879,12 @@
#address-cells = <1>;
#size-cells = <0>;
};
+
+ usbc_extcon0: extcon@0 {
+ compatible = "google,extcon-usbc-cros-ec";
+ google,usb-port-id = <0>;
+ #extcon-cells = <0>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index ff9ce0f93a3e..93b78344925d 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -1625,6 +1625,17 @@
phy-names = "dphy";
};
+ dpi0: dpi@14015000 {
+ compatible = "mediatek,mt8183-dpi";
+ reg = <0 0x14015000 0 0x1000>;
+ interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW 0>;
+ power-domains = <&scpsys MT8183_POWER_DOMAIN_DISP>;
+ clocks = <&mmsys CLK_MM_DPI_IF>,
+ <&mmsys CLK_MM_DPI_MM>,
+ <&apmixedsys CLK_APMIXED_TVDPLL>;
+ clock-names = "pixel", "engine", "pll";
+ };
+
mutex: mutex@14016000 {
compatible = "mediatek,mt8183-disp-mutex";
reg = <0 0x14016000 0 0x1000>;
diff --git a/chromeos/config/arm64/chromiumos-arm64.flavour.config b/chromeos/config/arm64/chromiumos-arm64.flavour.config
index ba263ecb9cd9..8b791d78b328 100644
--- a/chromeos/config/arm64/chromiumos-arm64.flavour.config
+++ b/chromeos/config/arm64/chromiumos-arm64.flavour.config
@@ -173,6 +173,7 @@ CONFIG_SND_SOC_MT8173_RT5650=y
CONFIG_SND_SOC_MT8173_RT5650_RT5514=y
CONFIG_SND_SOC_MT8173_RT5650_RT5676=y
CONFIG_SND_SOC_MT8183=y
+CONFIG_SND_SOC_MT8183_DA7219_MAX98357A=y
CONFIG_SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A=y
CONFIG_SND_SOC_RK3399_GRU_SOUND=y
CONFIG_SND_SOC_ROCKCHIP=y
diff --git a/chromeos/config/arm64/chromiumos-mediatek.flavour.config b/chromeos/config/arm64/chromiumos-mediatek.flavour.config
index 9a2ddb58a7d7..cac227d1cf69 100644
--- a/chromeos/config/arm64/chromiumos-mediatek.flavour.config
+++ b/chromeos/config/arm64/chromiumos-mediatek.flavour.config
@@ -31,6 +31,9 @@ CONFIG_DRM_ANALOGIX_ANX78XX=y
CONFIG_DRM_MEDIATEK=y
CONFIG_DRM_MEDIATEK_HDMI=y
CONFIG_DRM_PANEL_BOE_TV101WUM=y
+CONFIG_DRM_MIPI_DSI=y
+CONFIG_DRM_PANEL_BOE_HIMAX8279D=y
+# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set
CONFIG_DRM_PANEL_INNOLUX_P079ZCA=y
# CONFIG_EFI is not set
CONFIG_ENERGY_MODEL=y
@@ -73,6 +76,7 @@ CONFIG_SND_SOC_MT8173_RT5650=y
CONFIG_SND_SOC_MT8173_RT5650_RT5514=y
CONFIG_SND_SOC_MT8173_RT5650_RT5676=y
CONFIG_SND_SOC_MT8183=y
+CONFIG_SND_SOC_MT8183_DA7219_MAX98357A=y
CONFIG_SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_MT65XX=y
@@ -87,3 +91,14 @@ CONFIG_USB_MTU3=y
CONFIG_USB_MTU3_DEBUG=y
CONFIG_VIDEO_MEDIATEK_MDP=y
CONFIG_VIDEO_MEDIATEK_VCODEC=y
+CONFIG_VIDEO_MEDIATEK_VPU=y
+# CONFIG_VIDEO_V4L2_SUBDEV_API is not set
+CONFIG_VIRTIO=y
+# CONFIG_VIRTIO_BALLOON is not set
+# CONFIG_VIRTIO_BLK is not set
+# CONFIG_VIRTIO_CONSOLE is not set
+# CONFIG_VIRTIO_INPUT is not set
+# CONFIG_VIRTIO_MMIO is not set
+# CONFIG_VIRTIO_NET is not set
+# CONFIG_VIRTIO_WL is not set
+CONFIG_SX9311=y
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 4934fcf5a6f8..a83507bf6300 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -16,4 +16,5 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-y += ite-it6505.o
obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
new file mode 100755
index 000000000000..35f0bede1ace
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -0,0 +1,2948 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/spi/spi.h>
+#include <linux/fs.h>
+#include <linux/bits.h>
+#include <linux/of_platform.h>
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_edid.h>
+#include <crypto/sha.h>
+#include <crypto/hash.h>
+
+#define AX 0
+#define BX 1
+#define ENAUD 1
+#define AUDSEL I2S
+#define AUDTYPE LPCM
+#define AUDFS AUD48K
+#define AUDCH 2
+/* 0: Standard I2S;1: 32bit I2S */
+#define I2SINPUTFMT 1
+/* 0: Left-justified;1: Right-justified */
+#define I2SJUSTIFIED 0
+/* 0: Data delay 1T correspond to WS;1: No data delay correspond to WS */
+#define I2SDATADELAY 0
+/* 0: is left channel;1: is right channel */
+#define I2SWSCHANNEL 0
+/* 0: MSB shift first;1: LSB shift first */
+#define I2SDATASEQ 0
+
+#define LANESWAP 0
+#define LANE 4
+#define _HBR 1
+#define ENHFRAME 1
+#define ENSSC 1
+
+#define FLAGTRAINDOWN 100
+#define TRAINFAILCNT 5
+#define AUX_WAIT_TIMEOUT_MS 15
+#define PCLK_DELAY 1
+#define PCLK_INV 0
+#define EDIDRETRYTIME 5
+#define SHOWVIDEOTIMING 2
+#define PWROFFRETRYTIME 5
+
+/* AX or BX */
+#define CHIP_VERSION BX
+#define ENHDCP 1
+
+/* if use this define will enable power on/off option */
+#define ENPWRONOFF
+
+/* if use this define will power on in probe */
+/* #define TEST_MODE */
+
+/* if use this define will enable AUX debug option */
+/* #define ENAUX_TRANSFER_DEBUG */
+
+/* if use this define will enable SHA debug */
+/* #define SHA_DEBUG */
+
+/* register char device for it6505 */
+#define IT6505_CLASS_NAME "it6505_class"
+#define IT6505_DEVICE_NAME "it6505_device"
+#define IT6505_MAX_DEV 128
+/* The device-driver class struct pointer */
+static int it6505_major_num;
+
+enum sys_status {
+ SYS_UNPLUG = 0,
+ SYS_HPD,
+ SYS_AUTOTRAIN,
+ SYS_WAIT,
+ SYS_TRAINFAIL,
+ SYS_ReHDCP,
+ SYS_PWRDN,
+ SYS_NOROP,
+ SYS_Unknown,
+};
+
+enum it6505_aud_sel {
+ I2S = 0,
+ SPDIF,
+};
+
+enum it6505_aud_fs {
+ AUD24K = 0x6,
+ AUD32K = 0x3,
+ AUD48K = 0x2,
+ AUD96K = 0xA,
+ AUD192K = 0xE,
+ AUD44P1K = 0x0,
+ AUD88P2K = 0x8,
+ AUD176P4K = 0xC,
+};
+
+enum it6505_aud_type {
+ LPCM = 0,
+ NLPCM,
+ DSS,
+ HBR,
+};
+
+enum aud_word_length {
+ AUD16BIT = 0,
+ AUD18BIT,
+ AUD20BIT,
+ AUD24BIT,
+};
+
+/* Audio Sample Word Length: AUD16BIT, AUD18BIT, AUD20BIT, AUD24BIT */
+#define AUDWORDLENGTH AUD24BIT
+
+enum SWITCH {
+ Off = 0,
+ On
+};
+
+struct it6505_platform_data {
+ struct regulator *pwr18;
+ struct regulator *ovdd;
+ struct gpio_desc *gpiod_hpd;
+ struct gpio_desc *gpiod_pd;
+ struct gpio_desc *gpiod_reset;
+
+ int hpd_irq;
+ int intp_irq;
+};
+
+struct it6505_dp_port {
+ struct it6505 *it6505_dp;
+ struct notifier_block event_nb;
+ struct extcon_dev *extcon;
+ struct work_struct extcon_wq;
+ u8 id;
+};
+
+struct it6505 {
+ struct cros_ec_device *cros_ec;
+ struct drm_dp_aux aux;
+ struct drm_bridge bridge;
+ struct i2c_client *client;
+ struct edid *edid;
+ struct drm_connector connector;
+ struct drm_dp_link link;
+ struct it6505_platform_data pdata;
+ struct mutex lock;
+ struct regmap *regmap;
+ struct cdev cdev;
+ struct device class_dev;
+ struct it6505_dp_port *port;
+
+ u8 dpcd[DP_RECEIVER_CAP_SIZE];
+ enum sys_status status;
+ u8 dumpdpcd[30];
+ u8 dpcd_rev;
+ bool hbr;
+ u8 lane;
+ u8 en_ssc;
+ bool en_hframe;
+ bool laneswap;
+ u8 hpd_status;
+
+ enum it6505_aud_sel aud_sel;
+ enum it6505_aud_fs aud_fs;
+ enum it6505_aud_type aud_type;
+ u8 aud_ch;
+ u8 i2s_input_fmt;
+ u8 i2s_justified;
+ u8 i2s_data_delay;
+ u8 i2s_ws_channel;
+ u8 i2s_data_seq;
+ u8 vidstable_done;
+ enum aud_word_length audwordlength;
+ u8 cntfsm;
+ u8 enhdcp;
+ bool cp_ready;
+ unsigned int bstatus;
+ bool cp_done;
+ u8 downstreamrepeater;
+ u8 am0[8];
+ u8 binfo[2];
+ u8 ksvlist[5*12];
+ unsigned int sha[5];
+ unsigned int w[80];
+ u8 shainput[64];
+ u8 av[5][4];
+ u8 bv[5][4];
+ u8 passsha;
+ bool powered;
+ /* it6505 driver hold option */
+ unsigned int it6505_drv_hold;
+};
+
+static int it6505_poweron(struct it6505 *it6505);
+#ifdef ENPWRONOFF
+static int it6505_poweroff(struct it6505 *it6505);
+#endif
+
+static const struct regmap_range it6505_bridge_volatile_ranges[] = {
+ { .range_min = 0, .range_max = 0xFF },
+};
+
+static const struct regmap_access_table it6505_bridge_volatile_table = {
+ .yes_ranges = it6505_bridge_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(it6505_bridge_volatile_ranges),
+};
+
+static const struct regmap_config it6505_bridge_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &it6505_bridge_volatile_table,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int dptxrd(struct it6505 *it6505,
+ unsigned int reg_addr, unsigned int *value)
+{
+ int err;
+
+ err = regmap_read(it6505->regmap, reg_addr, value);
+ if (err < 0) {
+ DRM_ERROR("%s read fail err reg_addr[0x%x] err:%d\n",
+ __func__, reg_addr, err);
+ return err;
+ }
+
+ return 0;
+}
+
+static void it6505_dump(struct it6505 *it6505)
+{
+ unsigned int value, i;
+
+ DRM_DEBUG_DRIVER("\n----------%s start----------\n", __func__);
+ for (i = 0; i <= 0xff; i++) {
+ dptxrd(it6505, i, &value);
+ DRM_DEBUG_DRIVER("%s[0x%x] = 0x%x\n", __func__, i, value);
+ }
+ DRM_DEBUG_DRIVER("\n----------%s end----------\n\n", __func__);
+}
+
+static int dptxwr(struct it6505 *it6505,
+ unsigned int reg_addr, unsigned int reg_val)
+{
+ int err;
+
+ err = regmap_write(it6505->regmap, reg_addr, reg_val);
+
+ if (err < 0) {
+ DRM_ERROR(
+ "%s write fail err reg_addr[0x%x] = 0x%x err = %d\n",
+ __func__, reg_addr, reg_val, err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int dptxset(struct it6505 *it6505, unsigned int reg,
+ unsigned int mask, unsigned int setvalue)
+{
+ int err;
+
+ err = regmap_update_bits(it6505->regmap, reg, mask, setvalue);
+ if (err < 0) {
+ DRM_ERROR("%s write fail err %d\n", __func__, err);
+ return err;
+ }
+
+ return 0;
+}
+
+static inline struct it6505 *connector_to_it6505(struct drm_connector *c)
+{
+ return container_of(c, struct it6505, connector);
+}
+
+static inline struct it6505 *bridge_to_it6505(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct it6505, bridge);
+}
+
+
+void it6505_initfsm(struct it6505 *it6505)
+{
+ it6505->aud_sel = AUDSEL;
+ it6505->aud_fs = AUDFS;
+ it6505->aud_ch = AUDCH;
+ it6505->aud_type = AUDTYPE;
+ it6505->i2s_input_fmt = I2SINPUTFMT;
+ it6505->i2s_justified = I2SJUSTIFIED;
+ it6505->i2s_data_delay = I2SDATADELAY;
+ it6505->i2s_ws_channel = I2SWSCHANNEL;
+ it6505->i2s_data_seq = I2SDATASEQ;
+ it6505->audwordlength = AUDWORDLENGTH;
+
+ it6505->status = SYS_Unknown;
+ it6505->enhdcp = ENHDCP;
+ it6505->hbr = _HBR;
+ it6505->lane = LANE;
+ it6505->en_ssc = ENSSC;
+ it6505->en_hframe = ENHFRAME;
+ it6505->laneswap = LANESWAP;
+ it6505->vidstable_done = 0;
+}
+
+#if (CHIP_VERSION == BX)
+void iTE6505_termination(struct it6505 *it6505, enum SWITCH s)
+{
+ DRM_DEBUG_DRIVER("%s switch!!\n", __func__);
+ if (s) {
+ dptxset(it6505, 0x5D, 0x80, 0x00);
+ dptxset(it6505, 0x5E, 0x02, 0x02);
+ DRM_DEBUG_DRIVER("%s ON!!\n", __func__);
+ } else {
+ dptxset(it6505, 0x5D, 0x80, 0x80);
+ dptxset(it6505, 0x5E, 0x02, 0x00);
+ dptxset(it6505, 0x5C, 0xF0, 0x00);
+ DRM_DEBUG_DRIVER("%s OFF!!\n", __func__);
+ }
+}
+#endif
+
+static bool dptx_getsinkhpd(struct it6505 *it6505)
+{
+ unsigned int value;
+ int ret;
+
+ ret = dptxrd(it6505, 0x0D, &value);
+
+ if (ret < 0)
+ return false;
+
+ return (value & 2) == 2;
+}
+
+void show_vid_info(struct it6505 *it6505)
+{
+ int HSyncPol, VSyncPol, InterLaced;
+ int HTotal, HDES, HDEW, HFPH, HSYNCW;
+ int VTotal, VDES, VDEW, VFPH, VSYNCW;
+ int rddata, rddata1, i;
+ int PCLK, sum;
+
+ usleep_range(10000, 15000);
+ dptxwr(it6505, 0x0F, 0x00);
+ dptxrd(it6505, 0xa0, &rddata);
+ HSyncPol = rddata & BIT(0);
+ VSyncPol = (rddata & BIT(2)) >> 2;
+ InterLaced = (rddata & BIT(4)) >> 4;
+
+ dptxrd(it6505, 0xa1, &rddata);
+ dptxrd(it6505, 0xa2, &rddata1);
+ HTotal = ((rddata1 & 0x1F) << 8) + rddata;
+
+ dptxrd(it6505, 0xa3, &rddata);
+ dptxrd(it6505, 0xa4, &rddata1);
+
+ HDES = ((rddata1 & 0x1F) << 8) + rddata;
+
+ dptxrd(it6505, 0xa5, &rddata);
+ dptxrd(it6505, 0xa6, &rddata1);
+
+ HDEW = ((rddata1 & 0x1F) << 8) + rddata;
+
+ dptxrd(it6505, 0xa7, &rddata);
+ dptxrd(it6505, 0xa8, &rddata1);
+
+ HFPH = ((rddata1 & 0x1F) << 8) + rddata;
+
+ dptxrd(it6505, 0xa9, &rddata);
+ dptxrd(it6505, 0xaa, &rddata1);
+
+ HSYNCW = ((rddata1 & 0x1F) << 8) + rddata;
+
+ dptxrd(it6505, 0xab, &rddata);
+ dptxrd(it6505, 0xac, &rddata1);
+ VTotal = ((rddata1 & 0x0F) << 8) + rddata;
+
+ dptxrd(it6505, 0xad, &rddata);
+ dptxrd(it6505, 0xae, &rddata1);
+ VDES = ((rddata1 & 0x0F) << 8) + rddata;
+
+ dptxrd(it6505, 0xaf, &rddata);
+ dptxrd(it6505, 0xb0, &rddata1);
+ VDEW = ((rddata1 & 0x0F) << 8) + rddata;
+
+ dptxrd(it6505, 0xb1, &rddata);
+ dptxrd(it6505, 0xb2, &rddata1);
+ VFPH = ((rddata1 & 0x0F) << 8) + rddata;
+
+ dptxrd(it6505, 0xb3, &rddata);
+ dptxrd(it6505, 0xb4, &rddata1);
+ VSYNCW = ((rddata1 & 0x0F) << 8) + rddata;
+
+ sum = 0;
+ for (i = 0; i < 100; i++) {
+ dptxset(it6505, 0x12, 0x80, 0x80);
+ usleep_range(10000, 15000);
+ dptxset(it6505, 0x12, 0x80, 0x00);
+
+ dptxrd(it6505, 0x13, &rddata);
+ dptxrd(it6505, 0x14, &rddata1);
+ rddata = ((rddata1 & 0x0F) << 8)+rddata;
+
+ sum += rddata;
+ }
+
+ sum /= 100;
+ PCLK = 13500 * 2048 / sum;
+
+ DRM_DEBUG_DRIVER("\n----------Video Input Timing----------\n");
+ DRM_DEBUG_DRIVER("PCLK = %d.%dMHz\n", PCLK / 1000, PCLK % 1000);
+ DRM_DEBUG_DRIVER("HTotal = %d\n", HTotal);
+ DRM_DEBUG_DRIVER("HActive = %d\n", HDEW);
+ DRM_DEBUG_DRIVER("HFrontPorch = %d\n", HFPH);
+ DRM_DEBUG_DRIVER("HSyncWidth = %d\n", HSYNCW);
+ DRM_DEBUG_DRIVER("HBackPorch = %d\n", HTotal - HDEW - HFPH - HSYNCW);
+ DRM_DEBUG_DRIVER("VTotal = %d\n", VTotal);
+ DRM_DEBUG_DRIVER("VActive = %d\n", VDEW);
+ DRM_DEBUG_DRIVER("VFrontPorch = %d\n", VFPH);
+ DRM_DEBUG_DRIVER("VSyncWidth = %d\n", VSYNCW);
+ DRM_DEBUG_DRIVER("VBackPorch = %d\n", VTotal - VDEW - VFPH - VSYNCW);
+}
+
+void dptx_sys_chg(struct it6505 *it6505, enum sys_status newstate)
+{
+ unsigned int i = 0;
+ unsigned int reg06, reg07, reg08, reg0d, reg0e;
+
+ dptxrd(it6505, 0x06, &reg06);
+ dptxrd(it6505, 0x07, &reg07);
+ dptxrd(it6505, 0x08, &reg08);
+ dptxrd(it6505, 0x0d, &reg0d);
+ dptxrd(it6505, 0x0e, &reg0e);
+
+ DRM_DEBUG_DRIVER("%s reg06 = 0x%x\n", __func__, reg06);
+ DRM_DEBUG_DRIVER("%s reg07 = 0x%x\n", __func__, reg07);
+ DRM_DEBUG_DRIVER("%s reg08 = 0x%x\n", __func__, reg08);
+ DRM_DEBUG_DRIVER("%s reg0d = 0x%x\n", __func__, reg0d);
+ DRM_DEBUG_DRIVER("%s reg0e = 0x%x\n", __func__, reg0e);
+
+ if (newstate != SYS_UNPLUG) {
+ if (!dptx_getsinkhpd(it6505))
+ newstate = SYS_UNPLUG;
+ }
+
+ it6505->status = newstate;
+
+ switch (it6505->status) {
+ case SYS_UNPLUG:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_UNPLUG!!\n");
+ kfree(it6505->edid);
+ it6505->edid = NULL;
+ DRM_DEBUG_DRIVER("Free it6505 EDID memory!!\n");
+#if (CHIP_VERSION == BX)
+ iTE6505_termination(it6505, Off);
+#endif
+ break;
+ case SYS_HPD:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_HPD!!\n");
+#if (CHIP_VERSION == BX)
+ iTE6505_termination(it6505, On);
+#endif
+ break;
+ case SYS_AUTOTRAIN:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_AUTOTRAIN!!\n");
+ break;
+ case SYS_WAIT:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_WAIT!!\n");
+ break;
+#if ENHDCP
+ case SYS_ReHDCP:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_ReHDCP!!\n");
+ break;
+#endif
+ case SYS_NOROP:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_NOROP!!\n");
+ for (i = 0; i < SHOWVIDEOTIMING; i++)
+ show_vid_info(it6505);
+#ifdef TEST_MODE
+ it6505->it6505_drv_hold = 1;
+ DRM_DEBUG_DRIVER("set it6505_drv_hold:%d",
+ it6505->it6505_drv_hold);
+#endif
+ break;
+ case SYS_PWRDN:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_PWRDN!!\n");
+ /* Reset and PwrDn AFE */
+ break;
+ default:
+ DRM_DEBUG_DRIVER("sys_state is changing to SYS_UNKNOWN!!\n");
+ break;
+ }
+}
+
+static bool it6505_aux_op_finished(struct it6505 *it6505)
+{
+ unsigned int value;
+ int err;
+
+ err = regmap_read(it6505->regmap, 0x2b, &value);
+ if (err < 0)
+ return false;
+
+ return (value & BIT(5)) == 0;
+}
+
+
+static int dptx_auxwait(struct it6505 *it6505)
+{
+ unsigned int status;
+ unsigned long timeout;
+ int err;
+
+ timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1;
+
+ while (!it6505_aux_op_finished(it6505)) {
+ if (time_after(jiffies, timeout)) {
+ DRM_DEBUG_DRIVER("Timed out waiting AUX to finish\n");
+ return -ETIMEDOUT;
+ }
+ usleep_range(1000, 2000);
+ }
+
+ err = dptxrd(it6505, 0x9f, &status);
+ if (err < 0) {
+ DRM_ERROR("Failed to read from AUX channel: %d\n", err);
+ return err;
+ }
+
+ if (status & 0x03) {
+ DRM_ERROR("Failed to wait for AUX channel (status: 0x%x)\n",
+ status);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int dptx_aux_r_edid(struct it6505 *it6505,
+ unsigned int nosegw, unsigned int block, unsigned int offset)
+{
+ unsigned int value, status;
+ int ret;
+
+ /* enable pc aux access */
+ dptxwr(it6505, 0x23, (nosegw << 6) + 0x03);
+ /* edid fifo clr */
+ dptxwr(it6505, 0x23, (nosegw << 6) + 0x82);
+ /* start address[7:0] */
+ dptxwr(it6505, 0x24, (block % 2) * 128 + offset);
+ /* start address[15:8] */
+ dptxwr(it6505, 0x25, block / 256);
+ /* writenum[3:0]+startadr[19:16] */
+ dptxwr(it6505, 0x26, 0xf0);
+ /* aux edid read fire */
+ dptxwr(it6505, 0x2b, 0x0b);
+ dptx_auxwait(it6505);
+
+ ret = dptxrd(it6505, 0x07, &value);
+ if (ret) {
+ DRM_DEBUG_DRIVER("Failed to read reg07: %d\n", ret);
+ return ret;
+ }
+
+ if (value & BIT(0)) {
+ DRM_DEBUG_DRIVER("aux channel request fail interrupt\n");
+
+ ret = dptxrd(it6505, 0x9f, &status);
+ if (ret) {
+ DRM_DEBUG_DRIVER("AUX channel failed : %d !\n",
+ ret);
+ return ret;
+ }
+
+ switch ((status & 0xc0) >> 6) {
+ case 0:
+ DRM_DEBUG_DRIVER("no error !!!\n");
+ return 0;
+ case 1:
+ DRM_DEBUG_DRIVER("defer > 7 times status: 0x%x!!!\n",
+ status);
+ return -ETIMEDOUT;
+
+ case 2:
+ DRM_DEBUG_DRIVER("Nack response status: 0x%x!!!\n",
+ status);
+ return -ETIMEDOUT;
+
+ default:
+ DRM_DEBUG_DRIVER("timeout status: 0x%x!!!\n",
+ status);
+ return -ETIMEDOUT;
+ }
+
+ }
+ return 0;
+}
+
+unsigned int dptx_getedidblock(struct it6505 *it6505, u8 *pedidbuff,
+ unsigned int blockno)
+{
+ ushort i;
+ unsigned int offset, checksum, value;
+
+ if (pedidbuff == NULL)
+ return 0xff;
+
+ dptxset(it6505, 0x05, 0x08, 0x08);
+ dptxset(it6505, 0x05, 0x08, 0x00);
+
+ for (offset = 0; offset < 0x80; offset += 8) {
+ dptx_aux_r_edid(it6505, 1, blockno, offset);
+
+ for (i = 0; i < 8; i++) {
+ dptxrd(it6505, 0x2f, &value);
+ pedidbuff[offset + i] = value;
+ DRM_DEBUG_DRIVER("%s[%d][%d]: 0x%x !!\n",
+ __func__, blockno, i, value);
+ }
+ }
+ /* disable pc aux access */
+ dptxwr(it6505, 0x23, 1 << 6);
+ checksum = 0;
+ for (i = 0; i < 0x80; i++)
+ checksum += pedidbuff[i];
+
+ checksum &= 0xff;
+
+ return checksum;
+}
+
+static u8 it6505_get_extension_num(struct it6505 *it6505)
+{
+ unsigned int checksum = 0, retrytime = 0, reg0D;
+ u8 buff[EDID_LENGTH];
+
+ DRM_DEBUG_DRIVER("start %s!\n", __func__);
+
+ do {
+ dptxrd(it6505, 0x0D, &reg0D);
+ checksum = dptx_getedidblock(it6505, buff, 0);
+ retrytime++;
+ DRM_DEBUG_DRIVER("read EDID %d time", retrytime);
+ if (!(reg0D & BIT(1))) {
+ dptx_sys_chg(it6505, SYS_UNPLUG);
+ break;
+ }
+ } while (checksum != 0 && retrytime < EDIDRETRYTIME);
+
+ DRM_DEBUG_DRIVER("extension number:%d",buff[0x7e]);
+ DRM_DEBUG_DRIVER("end %s!\n", __func__);
+ return buff[0x7e];
+}
+
+static struct edid *it6505_get_edid(struct it6505 *it6505)
+{
+ unsigned int checksum = 0, retrytime = 0;
+ unsigned int i, block, reg0D, total_size;
+ u8 *pedidbuff = kmalloc(EDID_LENGTH, GFP_KERNEL);
+
+ DRM_DEBUG_DRIVER("start %s", __func__);
+ if (!pedidbuff) {
+ DRM_DEBUG_DRIVER("%s(null)!\n", __func__);
+ return NULL;
+ }
+
+ it6505_dump(it6505);
+ block = it6505_get_extension_num(it6505);
+
+ /* dp does not have the hdmi tx four block test requirement */
+ if (block > 2)
+ block = 2;
+
+ total_size = (block + 1) * EDID_LENGTH;
+ if (total_size > EDID_LENGTH)
+ pedidbuff = krealloc(pedidbuff, total_size, GFP_KERNEL);
+
+ for (i = 0; i <= block; i++) {
+ DRM_DEBUG_DRIVER("Read block 0x%x", i);
+ retrytime = 0;
+ do {
+ dptxrd(it6505, 0x0D, &reg0D);
+ checksum = dptx_getedidblock(it6505,
+ pedidbuff + i * EDID_LENGTH, i);
+ DRM_DEBUG_DRIVER("%s in block %d %s",
+ checksum ? "Fake" : "True", i,
+ checksum ? "and read again!" : "!");
+ retrytime++;
+ DRM_DEBUG_DRIVER("read EDID %d time", retrytime);
+ if (!(reg0D & BIT(1))) {
+ dptx_sys_chg(it6505, SYS_UNPLUG);
+ break;
+ }
+ } while (checksum != 0 && retrytime < EDIDRETRYTIME);
+ if (checksum || it6505->status == SYS_UNPLUG)
+ break;
+ }
+ DRM_DEBUG_DRIVER("end %s and edid correct!", __func__);
+ return (struct edid *)pedidbuff;
+}
+
+static int it6505_get_modes(struct drm_connector *connector)
+{
+ struct it6505 *ctx = connector_to_it6505(connector);
+ int err, num_modes = 0;
+ u8 *p;
+ unsigned int reg9F, reg0D;
+
+ DRM_DEBUG_DRIVER("start %s", __func__);
+ err = it6505_poweron(ctx);
+ if (err) {
+ DRM_DEBUG_DRIVER("power on fail!");
+ goto unlock;
+ }
+ DRM_DEBUG_DRIVER("power on success!");
+ if (ctx->edid) {
+ DRM_DEBUG_DRIVER("ctx->edid is exist\n");
+ return drm_add_edid_modes(connector, ctx->edid);
+ }
+ DRM_DEBUG_DRIVER("ctx->edid not exist\n");
+ DRM_DEBUG_DRIVER("call it6505_get_edid to get EDID!\n");
+ mutex_lock(&ctx->lock);
+ dptxrd(ctx, 0x0D, &reg0D);
+ if (reg0D & BIT(1))
+ dptx_sys_chg(ctx, SYS_HPD);
+ else
+ dptx_sys_chg(ctx, SYS_UNPLUG);
+
+ dptxrd(ctx, 0x9F, &reg9F);
+ DRM_DEBUG_DRIVER("Aux status reg9F:0x%02x\n", reg9F);
+ ctx->edid = it6505_get_edid(ctx);
+ DRM_DEBUG_DRIVER("After it6505_get_edid, show the EDID:\n");
+ err = 256;
+ p = (u8 *)ctx->edid;
+ while (err) {
+ DRM_DEBUG_DRIVER("err = %d\n", err);
+ DRM_DEBUG_DRIVER("0x%02x 0x%02x 0x%02x 0x%02x\n",
+ p[0], p[1], p[2], p[3]);
+ DRM_DEBUG_DRIVER("0x%02x 0x%02x 0x%02x 0x%02x\n",
+ p[4], p[5], p[6], p[7]);
+ DRM_DEBUG_DRIVER("0x%02x 0x%02x 0x%02x 0x%02x\n",
+ p[8], p[9], p[10], p[11]);
+ DRM_DEBUG_DRIVER("0x%02x 0x%02x 0x%02x 0x%02x\n",
+ p[12], p[13], p[14], p[15]);
+
+ err -= 16;
+ p += 16;
+ }
+ if (!ctx->edid) {
+ DRM_ERROR("Failed to read EDID\n");
+ goto unlock;
+ }
+
+ err = drm_connector_update_edid_property(connector, ctx->edid);
+ if (err) {
+ DRM_ERROR("Failed to update EDID property: %d\n", err);
+ goto unlock;
+ }
+
+ num_modes = drm_add_edid_modes(connector, ctx->edid);
+
+unlock:
+ mutex_unlock(&ctx->lock);
+
+ return num_modes;
+}
+
+static const struct drm_connector_helper_funcs it6505_connector_helper_funcs = {
+ .get_modes = it6505_get_modes,
+};
+
+static enum drm_connector_status it6505_detect(struct drm_connector *connector,
+ bool force)
+{
+ struct it6505 *ctx = connector_to_it6505(connector);
+
+ if (gpiod_get_value(ctx->pdata.gpiod_hpd))
+ return connector_status_disconnected;
+
+ return connector_status_connected;
+}
+
+static const struct drm_connector_funcs it6505_connector_funcs = {
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = it6505_detect,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+/* reverved for future use */
+/*
+ *BYTE iTE6505_dptx_aux(char *RORW, char *addr,
+ * int offset, BYTE *array, BYTE size)
+ *{
+ * BYTE i = 0;
+ * if (!strcmp(RORW, "w") || !strcmp(RORW, "W")) {
+ * while (i < size) {
+ * if (!dptx_dpcdwr(offset++, array[i++])) {
+ * DRM_DEBUG_DRIVER(("DPCD write fail!!\n"));
+ * return 3;
+ * }
+ * else {
+ * DRM_DEBUG_DRIVER(("DPCD write success!!\n"));
+ * return 0;
+ * }
+ * }
+ * }
+ * else if (!strcmp(RORW, "r") || !strcmp(RORW, "R")) {
+ * if (!strcmp(addr, "EDID")) {
+ * BYTE blocknum = offset / 0x80;
+ * offset = offset%0x80;
+ * dptx_AUX_R_EDID(1, blocknum, offset);
+ * while (i < size) {
+ * array[i] = dptxrd(0x2F);
+ * i++;
+ * }
+ * return 0;
+ * }
+ * else if (!strcmp(addr, "DPCD")) {
+ * while (i < size) {
+ * array[i++] = dptx_dpcdrd(offset++);
+ * }
+ * return 0;
+ * }
+ * else {
+ * DRM_DEBUG_DRIVER(("%s second parameter error!!\n"));
+ * return 2;
+ * }
+ * }
+ * else {
+ * DRM_DEBUG_DRIVER(%s first parameter error!!\n",
+ __func__);
+ * return 1;
+ * }
+ *}
+ */
+
+
+static ssize_t it6505_aux_transfer(struct drm_dp_aux *aux,
+ struct drm_dp_aux_msg *msg)
+{
+ /* reserved code for future debug using */
+#ifdef ENAUX_TRANSFER_DEBUG
+
+ struct it6505 *ctx = container_of(aux, struct it6505, aux);
+ u8 ctrl1 = msg->request;
+ u8 ctrl2 = SP_AUX_EN;
+ u8 *buffer = msg->buffer;
+ int err;
+
+ /* The DP AUX transmit and receive buffer has 16 bytes. */
+ if (WARN_ON(msg->size > AUX_CH_BUFFER_SIZE))
+ return -E2BIG;
+
+ /* Zero-sized messages specify address-only transactions. */
+ if (msg->size < 1)
+ ctrl2 |= SP_ADDR_ONLY;
+ else /* For non-zero-sized set the length field. */
+ ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT;
+
+ if ((msg->request & DP_AUX_I2C_READ) == 0) {
+ /* When WRITE | MOT write values to data buffer */
+ err = regmap_bulk_write(ctx->map[I2C_IDX_TX_P0],
+ SP_DP_BUF_DATA0_REG, buffer,
+ msg->size);
+ if (err)
+ return err;
+ }
+
+ /* Write address and request */
+ err = it6505_aux_address(ctx, msg->address);
+ if (err)
+ return err;
+
+ err = regmap_write(ctx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL1_REG,
+ ctrl1);
+ if (err)
+ return err;
+
+ /* Start transaction */
+ err = regmap_update_bits(ctx->map[I2C_IDX_TX_P0],
+ SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY |
+ SP_AUX_EN, ctrl2);
+ if (err)
+ return err;
+
+ err = it6505_aux_wait(ctx);
+ if (err)
+ return err;
+
+ msg->reply = DP_AUX_I2C_REPLY_ACK;
+
+ if ((msg->size > 0) && (msg->request & DP_AUX_I2C_READ)) {
+ /* Read values from data buffer */
+ err = regmap_bulk_read(ctx->map[I2C_IDX_TX_P0],
+ SP_DP_BUF_DATA0_REG, buffer,
+ msg->size);
+ if (err)
+ return err;
+ }
+
+ err = it6505_clear_bits(ctx->map[I2C_IDX_TX_P0],
+ SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY);
+ if (err)
+ return err;
+
+ return msg->size;
+
+#endif
+ return 0;
+}
+
+static int it6505_extcon_notifier(struct notifier_block *self,
+ unsigned long event, void *ptr)
+{
+ struct it6505_dp_port *port =
+ container_of(self, struct it6505_dp_port, event_nb);
+
+ schedule_work(&port->extcon_wq);
+ DRM_DEBUG_DRIVER("[%s]", __func__);
+ return NOTIFY_DONE;
+}
+
+static void it6505_extcon_work(struct work_struct *work)
+{
+ struct it6505_dp_port *port =
+ container_of(work, struct it6505_dp_port, extcon_wq);
+ struct it6505 *ctx = port->it6505_dp;
+ int state = extcon_get_state(port->extcon, EXTCON_DISP_DP);
+#ifdef ENPWRONOFF
+ unsigned int pwroffretry = 0;
+#endif
+
+ mutex_lock(&ctx->lock);
+ DRM_DEBUG_DRIVER("[%s] state:%d %s", __func__, state,
+ state ? "cable in": "cable out");
+ if (state > 0) {
+ DRM_DEBUG_DRIVER("[%s] state:%d",
+ __func__, state);
+ DRM_DEBUG_DRIVER("[%s] start to power on!", __func__);
+ it6505_poweron(ctx);
+ } else {
+ DRM_DEBUG_DRIVER("[%s] state:%d",
+ __func__, state);
+#ifdef ENPWRONOFF
+ DRM_DEBUG_DRIVER("[%s] start to power off!", __func__);
+ while (it6505_poweroff(ctx) &&
+ pwroffretry++ < PWROFFRETRYTIME) {
+ DRM_DEBUG_DRIVER("power off it6505 fail! %d times",
+ pwroffretry);
+ }
+ DRM_DEBUG_DRIVER("power off it6505 success!");
+#endif
+ }
+ mutex_unlock(&ctx->lock);
+}
+
+static int use_notifier_module(struct it6505 *ctx)
+{
+ struct it6505_dp_port *port = ctx->port;
+ int ret;
+
+ DRM_DEBUG_DRIVER("[%s]", __func__);
+ port->event_nb.notifier_call = it6505_extcon_notifier;
+ INIT_WORK(&port->extcon_wq, it6505_extcon_work);
+ ret = devm_extcon_register_notifier(&ctx->client->dev,
+ port->extcon, EXTCON_DISP_DP, &port->event_nb);
+ if (ret) {
+ DRM_DEBUG_DRIVER("failed to register notifier for DP");
+ return ret;
+ }
+ return 0;
+}
+
+static int it6505_bridge_attach(struct drm_bridge *bridge)
+{
+ struct it6505 *ctx = bridge_to_it6505(bridge);
+ struct cros_ec_device *cros_ec;
+ struct extcon_dev *extcon;
+ struct it6505_dp_port *port;
+ struct device *dev;
+ int err;
+
+ DRM_DEBUG_DRIVER(" This is %s~start!!\n", __func__);
+ dev = &ctx->client->dev;
+ if (!bridge->encoder) {
+ DRM_ERROR("Parent encoder object not found");
+ return -ENODEV;
+ }
+
+ /* Register aux channel */
+ ctx->aux.name = "DP-AUX";
+ ctx->aux.dev = &ctx->client->dev;
+ ctx->aux.transfer = it6505_aux_transfer;
+
+ err = drm_dp_aux_register(&ctx->aux);
+ if (err < 0) {
+ DRM_ERROR("Failed to register aux channel: %d\n", err);
+ return err;
+ }
+
+ err = drm_connector_init(bridge->dev, &ctx->connector,
+ &it6505_connector_funcs,
+ DRM_MODE_CONNECTOR_DisplayPort);
+ if (err) {
+ DRM_ERROR("Failed to initialize connector: %d\n", err);
+ return err;
+ }
+
+ drm_connector_helper_add(&ctx->connector,
+ &it6505_connector_helper_funcs);
+
+ err = drm_connector_register(&ctx->connector);
+ if (err) {
+ DRM_ERROR("Failed to register connector: %d\n", err);
+ return err;
+ }
+
+ ctx->connector.polled = DRM_CONNECTOR_POLL_HPD;
+
+ err = drm_connector_attach_encoder(&ctx->connector,
+ bridge->encoder);
+ if (err) {
+ DRM_ERROR("Failed to link up connector to encoder: %d\n", err);
+ return err;
+ }
+
+ /* get extcon device from DTS */
+ extcon = extcon_get_edev_by_phandle(dev, 0);
+ if (PTR_ERR(extcon) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ if (IS_ERR(extcon)){
+ DRM_DEBUG_DRIVER("%s can not get extcon device!", __func__);
+ return -EINVAL;
+ } else
+ DRM_DEBUG_DRIVER("%s get extcon device!", __func__);
+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+ port->extcon = extcon;
+ port->it6505_dp = ctx;
+ port->id = 0;
+ ctx->port = port;
+
+ err = use_notifier_module(ctx);
+ if (err < 0) {
+ DRM_DEBUG_DRIVER("%s fail to use notifier module!", __func__);
+ return err;
+ }
+ DRM_DEBUG_DRIVER("ctx->cros_ec = 0x%p\n", cros_ec);
+ DRM_DEBUG_DRIVER(" This is %s~end!!\n", __func__);
+ return 0;
+}
+
+static enum drm_mode_status
+it6505_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode)
+{
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ return MODE_NO_INTERLACE;
+
+ /* Max 1200p at 5.4 Ghz, one lane */
+ if (mode->clock > 80000)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+static int it6505_send_video_infoframe(struct it6505 *it6505,
+ struct hdmi_avi_infoframe *frame)
+{
+ u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
+ int err;
+
+ err = hdmi_avi_infoframe_pack(frame, buffer, sizeof(buffer));
+ if (err < 0) {
+ DRM_ERROR("Failed to pack AVI infoframe: %d\n", err);
+ return err;
+ }
+
+ err = dptxset(it6505, 0xe8, 1, 0);
+ if (err)
+ return err;
+
+ err = regmap_bulk_write(it6505->regmap, 0xe9, buffer, frame->length);
+ if (err)
+ return err;
+
+ err = dptxset(it6505, 0xe8, 1, 1);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static void it6505_bridge_mode_set(struct drm_bridge *bridge,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct it6505 *ctx = bridge_to_it6505(bridge);
+ struct hdmi_avi_infoframe frame;
+ int err;
+
+ mutex_lock(&ctx->lock);
+
+ DRM_DEBUG_DRIVER("%s\n", __func__);
+
+ err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
+ adjusted_mode, false);
+ if (err) {
+ DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
+ goto unlock;
+ }
+
+ err = it6505_send_video_infoframe(ctx, &frame);
+ if (err)
+ DRM_ERROR("Failed to send AVI infoframe: %d\n", err);
+
+unlock:
+ mutex_unlock(&ctx->lock);
+}
+
+void dptx_init(struct it6505 *it6505)
+{
+ dptxwr(it6505, 0x05, 0x3B);
+ usleep_range(1000, 2000);
+ dptxwr(it6505, 0x05, 0x1F);
+ usleep_range(1000, 1500);
+
+ DRM_DEBUG_DRIVER("this is %s end !!\n", __func__);
+}
+
+void iTE6505_INT_mask(struct it6505 *it6505)
+{
+#if ENHDCP
+ dptxwr(it6505, 0x09, 0x1F);
+#else
+ dptxwr(it6505, 0x09, 0x07);
+#endif
+
+#if ENAUD
+ dptxwr(it6505, 0x0A, 0x07);
+#else
+ dptxwr(it6505, 0x0A, 0x03);
+#endif
+ dptxwr(it6505, 0x0B, 0x90);
+}
+
+void dptx_set_aud_fmt(struct it6505 *it6505,
+ enum it6505_aud_sel audsel, unsigned int audch)
+{
+ unsigned int audsrc;
+ /* I2S MODE */
+ dptxwr(it6505, 0xB9, (it6505->audwordlength << 5)
+ | (it6505->i2s_data_seq << 4) | (it6505->i2s_ws_channel << 3)
+ | (it6505->i2s_data_delay << 2) | (it6505->i2s_justified << 1)
+ | it6505->i2s_input_fmt);
+ if (audsel == SPDIF) {
+ dptxwr(it6505, 0xBA, 0x00);
+ /* 0x30 = 128*FS */
+ dptxset(it6505, 0x11, 0xF0, 0x30);
+ } else {
+ dptxwr(it6505, 0xBA, 0xe4);
+ }
+
+ dptxwr(it6505, 0xBB, 0x00);
+ dptxwr(it6505, 0xBC, 0x00);
+ audsrc = 1;
+
+ if (audch > 2)
+ audsrc |= 2;
+
+ if (audch > 4)
+ audsrc |= 4;
+
+ if (audch == 8)
+ audsrc |= 8;
+
+ audsrc |= audsel << 4;
+
+ dptxwr(it6505, 0xB8, audsrc);
+}
+
+void dptx_set_aud_chsts(struct it6505 *it6505,
+ enum it6505_aud_type audtype, enum it6505_aud_fs audfs)
+{
+ /* Channel Status */
+ dptxwr(it6505, 0xBF, audtype << 1);
+ dptxwr(it6505, 0xC0, 0x00);
+ dptxwr(it6505, 0xC1, 0x00);
+ dptxwr(it6505, 0xC2, audfs);
+ switch (it6505->audwordlength) {
+ case AUD16BIT:
+ dptxwr(it6505, 0xC3, ((~audfs) << 4) + 0x02);
+ break;
+
+ case AUD18BIT:
+ dptxwr(it6505, 0xC3, ((~audfs) << 4) + 0x04);
+ break;
+
+ case AUD20BIT:
+ dptxwr(it6505, 0xC3, ((~audfs) << 4) + 0x03);
+ break;
+
+ case AUD24BIT:
+ dptxwr(it6505, 0xC3, ((~audfs) << 4) + 0x0B);
+ break;
+ }
+}
+
+
+void dptx_set_audio_infoframe(struct it6505 *it6505, unsigned int audch)
+{
+ dptxwr(it6505, 0xf7, audch - 1);
+
+ switch (audch) {
+ case 2:
+ dptxwr(it6505, 0xF9, 0x00);
+ break;
+ case 3:
+ dptxwr(it6505, 0xF9, 0x01);
+ break;
+ case 4:
+ dptxwr(it6505, 0xF9, 0x03);
+ break;
+ case 5:
+ dptxwr(it6505, 0xF9, 0x07);
+ break;
+ case 6:
+ dptxwr(it6505, 0xF9, 0x0B);
+ break;
+ case 7:
+ dptxwr(it6505, 0xF9, 0x0F);
+ break;
+ case 8:
+ dptxwr(it6505, 0xF9, 0x1F);
+ break;
+ default:
+ DRM_DEBUG_DRIVER("Error:Audio Channel Number Error !!!\n");
+ }
+ /* Enable Audio InfoFrame */
+ dptxset(it6505, 0xE8, 0x22, 0x22);
+}
+
+
+void iTE6505_SetAudio(struct it6505 *it6505, enum it6505_aud_sel audsel,
+ enum it6505_aud_type audtype, enum it6505_aud_fs audfs,
+ unsigned int audch)
+{
+ /* Audio Clock Domain Reset */
+ dptxset(it6505, 0x05, 0x02, 0x02);
+ /* Audio mute */
+ dptxset(it6505, 0xD3, 0x20, 0x20);
+ /* Release Audio Clock Domain Reset */
+ dptxset(it6505, 0x05, 0x02, 0x00);
+
+ dptx_set_aud_chsts(it6505, audtype, audfs);
+ dptx_set_audio_infoframe(it6505, audch);
+ dptx_set_aud_fmt(it6505, audsel, audch);
+ /* Enable Enhanced Audio TimeStmp Mode */
+ dptxset(it6505, 0xD4, 0x04, 0x04);
+ /* Disable Full Audio Packet */
+ dptxset(it6505, 0xBB, 0x10, 0x00);
+
+ dptxwr(it6505, 0xDE, 0x00);
+ dptxwr(it6505, 0xDF, 0x80);
+ dptxwr(it6505, 0xE0, 0x00);
+ dptxset(it6505, 0xD3, 0x20, 0x00);
+
+ /* Clear Video M Error Interrupt */
+ dptxset(it6505, 0x08, 0x08, 0x08);
+ /* Clear Audio FIFO OverFlow Interrupt */
+ dptxset(it6505, 0x07, 0x04, 0x04);
+}
+
+/***************************************************************************
+ * DPCD Read and EDID
+ ***************************************************************************/
+
+static unsigned int dptx_dpcdrd(struct it6505 *it6505,
+ unsigned long offset)
+{
+ unsigned int startadr0, startadr1, startadr2;
+
+ startadr0 = (unsigned int)((offset >> 0) & 0xFF);
+ startadr1 = (unsigned int)((offset >> 8) & 0xFF);
+ startadr2 = (unsigned int)((offset >> 16) & 0x0F);
+ /* Enable PC Aux Access */
+ dptxwr(it6505, 0x23, (0 << 6) + 0x02);
+ /* Start Address[7:0] */
+ dptxwr(it6505, 0x24, startadr0);
+ /* Start Address[15:8] */
+ dptxwr(it6505, 0x25, startadr1);
+ /* WriteNum[3:0]+StartAdr[19:16] */
+ dptxwr(it6505, 0x26, startadr2);
+ /* Aux Read Fire */
+ dptxwr(it6505, 0x2B, 0x00);
+ dptx_auxwait(it6505);
+ /* Disable PC Aux Access */
+ dptxwr(it6505, 0x23, (0 << 6) + 0x00);
+
+ dptxrd(it6505, 0x2C, &startadr0);
+
+ return startadr0;
+}
+
+static int dptx_dpcdwr(struct it6505 *it6505,
+ unsigned long offset, unsigned long datain)
+{
+ unsigned int startadr0, startadr1, startadr2;
+
+ startadr0 = (unsigned int)(offset >> 0) & 0xFF;
+ startadr1 = (unsigned int)(offset >> 8) & 0xFF;
+ startadr2 = (unsigned int)(offset >> 16) & 0x0F;
+ /* Enable PC Aux Access */
+ dptxwr(it6505, 0x23, (1 << 6) + 0x02);
+ /* Start Address[7:0] */
+ dptxwr(it6505, 0x24, startadr0);
+ /* Start Address[15:8] */
+ dptxwr(it6505, 0x25, startadr1);
+ /* WriteNum[3:0]+StartAdr[19:16] */
+ dptxwr(it6505, 0x26, startadr2);
+ /* WriteData Byte 1 */
+ dptxwr(it6505, 0x27, datain);
+ /* Aux Write Fire */
+ dptxwr(it6505, 0x2B, 0x05);
+ dptx_auxwait(it6505);
+ /* Aux Read Fire */
+ dptxwr(it6505, 0x2B, 0x00);
+ dptx_auxwait(it6505);
+ /* Disable PC Aux Access */
+ dptxwr(it6505, 0x23, (1 << 6) + 0x00);
+
+ dptxrd(it6505, 0x2C, &startadr0);
+
+ if (startadr0 != datain)
+ return -EINVAL;
+
+ return 0;
+}
+
+int iTE6505_GetSinkSupportHDCP(struct it6505 *it6505)
+{
+ unsigned int rddata;
+
+ dptxrd(it6505, 0x0D, &rddata);
+ if (!(rddata & BIT(1))) {
+ DRM_DEBUG_DRIVER("sys is unplug!! ...\n");
+ dptx_sys_chg(it6505, SYS_UNPLUG);
+ it6505->cp_ready = -1;
+ } else {
+ if (dptx_dpcdrd(it6505, 0x68028) & BIT(0)) {
+ DRM_DEBUG_DRIVER("Sink support HDCP!!\n");
+ it6505->cp_ready = 1;
+ DRM_DEBUG_DRIVER("Config ENHDCP, output with HDCP!!\n");
+ } else {
+ DRM_DEBUG_DRIVER("Sink not support HDCP !!\n");
+ it6505->cp_ready = 0;
+ DRM_DEBUG_DRIVER("Config ENHDCP, output no HDCP!\n");
+ }
+ }
+ return it6505->cp_ready;
+}
+
+static void iTE6505_GetDPCD(struct it6505 *it6505)
+{
+ unsigned int offset = 0;
+
+ DRM_DEBUG_DRIVER("\n ========== [DPCD] ===========\n");
+ for (offset = 0; offset < 0x10; offset++) {
+ it6505->dumpdpcd[offset] = dptx_dpcdrd(it6505, offset);
+ DRM_DEBUG_DRIVER("DPCD[0x%02x]=0x%02x ",
+ offset, it6505->dumpdpcd[offset]);
+ if (offset == 0x07)
+ DRM_DEBUG_DRIVER("\n");
+ }
+ DRM_DEBUG_DRIVER("\n =============================\n");
+}
+
+static void iTE6505_ParseDPCD(struct it6505 *it6505)
+{
+ it6505->dpcd_rev = it6505->dumpdpcd[0];
+ DRM_DEBUG_DRIVER(" =========== Start Parse DPCD! !===========\n");
+ DRM_DEBUG_DRIVER("#########DPCD Rev.: %d.%d###########\n",
+ it6505->dpcd_rev >> 4, it6505->dpcd_rev & 0x0F);
+
+ switch (it6505->dumpdpcd[1]) {
+ case 0x06:
+ DRM_DEBUG_DRIVER("Maximum Link Rate: 1.62Gbps per lane\n");
+ if (it6505->hbr) {
+ DRM_DEBUG_DRIVER("Not support HBR Mode");
+ DRM_DEBUG_DRIVER("will train LBR\n");
+ it6505->hbr = false;
+ } else
+ DRM_DEBUG_DRIVER("Training LBR\n");
+ break;
+
+ case 0x0A:
+ DRM_DEBUG_DRIVER("Maximum Link Rate: 2.7Gbps per lane\n");
+ if (!it6505->hbr) {
+ DRM_DEBUG_DRIVER("Support HBR Mode");
+ DRM_DEBUG_DRIVER("will train LBR\n");
+ it6505->hbr = false;
+ } else
+ DRM_DEBUG_DRIVER("Training HBR\n");
+ break;
+
+ case 0x14:
+ DRM_DEBUG_DRIVER("Maximum Link Rate: 2.7Gbps per lane\n");
+ break;
+
+ default:
+ DRM_DEBUG_DRIVER("Unknown Maximum Link Rate!!\n");
+ break;
+ }
+
+ switch (it6505->dumpdpcd[2] & 0x1F) {
+ case 1:
+ DRM_DEBUG_DRIVER("Maximum Lane Count : 1 lane\n");
+ if (it6505->lane > 1) {
+ DRM_DEBUG_DRIVER("Not support %d lane training\n",
+ it6505->lane);
+ DRM_DEBUG_DRIVER("Training 1 lane\n");
+ it6505->lane = 1;
+ } else
+ DRM_DEBUG_DRIVER("Training %d lane!!\n", it6505->lane);
+ break;
+ case 2:
+ DRM_DEBUG_DRIVER("Maximum Lane Count : 2 lanes\n");
+ if (it6505->lane > 2) {
+ DRM_DEBUG_DRIVER("Not support %d lane training\n",
+ it6505->lane);
+ DRM_DEBUG_DRIVER("Training 2 lane\n");
+ it6505->lane = 2;
+ } else
+ DRM_DEBUG_DRIVER("Training %d lane!!\n", it6505->lane);
+ break;
+ case 4:
+ DRM_DEBUG_DRIVER("Maximum Lane Count : 4 lanes\n");
+ if (it6505->lane > 4) {
+ DRM_DEBUG_DRIVER("Not support %d lane training\n",
+ it6505->lane);
+ DRM_DEBUG_DRIVER("Training 4 lane\n");
+ it6505->lane = 4;
+ } else
+ DRM_DEBUG_DRIVER("Training %d lane!!\n", it6505->lane);
+ break;
+ default:
+ DRM_DEBUG_DRIVER("Maximum Lane Count : Error !!!\n");
+ }
+
+ if (it6505->dpcd_rev == 0x11 && it6505->dumpdpcd[2] & BIT(7)) {
+ DRM_DEBUG_DRIVER("Support Enhanced Framing Mode\n");
+ } else {
+ DRM_DEBUG_DRIVER("Can not support Enhanced Framing Mode\n");
+ if (it6505->en_hframe) {
+ DRM_DEBUG_DRIVER("Can not support Enhanced Framing!\n");
+ it6505->en_hframe = 0;
+ }
+ }
+
+ if (it6505->dumpdpcd[3] & BIT(0)) {
+ DRM_DEBUG_DRIVER("Maximum Down-Spread: 0.5, support SSC!\n");
+ } else {
+ DRM_DEBUG_DRIVER("Maximum Down-Spread: 0, No support SSC!\n");
+ if (it6505->en_ssc) {
+ DRM_DEBUG_DRIVER("Can not support SSC!!\n");
+ it6505->en_ssc = 0;
+ }
+ }
+
+ if (it6505->dpcd_rev == 0x11 && it6505->dumpdpcd[3] & BIT(6))
+ DRM_DEBUG_DRIVER("Support No AUX Training\n");
+ else
+ DRM_DEBUG_DRIVER("Can not support No AUX Training\n");
+
+ if (dptx_dpcdrd(it6505, 0x68028) & BIT(0)) {
+ DRM_DEBUG_DRIVER("Sink support HDCP!\n");
+ it6505->cp_ready = true;
+#if ENHDCP
+ DRM_DEBUG_DRIVER("Config ENHDCP output with HDCP!\n");
+#else
+ DRM_DEBUG_DRIVER("Not config ENHDCP output no HDCP!\n");
+#endif
+ } else {
+ DRM_DEBUG_DRIVER("Sink not support HDCP !\n");
+ it6505->cp_ready = false;
+#if ENHDCP
+ DRM_DEBUG_DRIVER("Config ENHDCP output no HDCP!\n");
+#else
+ DRM_DEBUG_DRIVER("Not config ENHDCP output no HDCP!\n");
+#endif
+ }
+
+ if (dptx_dpcdrd(it6505, 0x68028) & BIT(1)) {
+ DRM_DEBUG_DRIVER("Downstream is repeater!!\n");
+ it6505->downstreamrepeater = true;
+ } else {
+ DRM_DEBUG_DRIVER("Downstream is receiver!!\n");
+ it6505->downstreamrepeater = false;
+ }
+
+ DRM_DEBUG_DRIVER(" ======== Parse DPCD END! ========\n");
+}
+
+void iTE6505_EnableHDCP(struct it6505 *it6505)
+{
+ int i;
+ u8 c;
+ unsigned long BKSV[5], bksv;
+
+ DRM_DEBUG_DRIVER("%s start!!", __func__);
+ /* Disable CP_Desired */
+ dptxset(it6505, 0x38, 0x0B, 0x00);
+ dptxset(it6505, 0x05, 0x10, 0x10);
+
+ usleep_range(1000, 1500);
+ c = dptx_dpcdrd(it6505, 0x68028);
+ DRM_DEBUG_DRIVER("DPCD[0x68028]:0x%x!!\n", c);
+ if (!c)
+ return;
+
+ dptxset(it6505, 0x05, 0x10, 0x00);
+ /* Disable CP_Desired */
+ dptxset(it6505, 0x38, 0x01, 0x00);
+ /* Use R0' 100ms waiting */
+ dptxset(it6505, 0x38, 0x08, 0x00);
+ /* clear the repeater List Chk Done and fail bit */
+ dptxset(it6505, 0x39, 0x30, 0x00);
+
+ for (i = 0; i < 5; i++)
+ BKSV[i] = dptx_dpcdrd(it6505, 0x68000 + i);
+
+ bksv = BKSV[0] + (BKSV[1] << 8) + (BKSV[2] << 16)
+ + (BKSV[3] << 24) + (BKSV[4] << 32);
+ DRM_DEBUG_DRIVER("Sink BKSV = 0x%lx", bksv);
+
+ /* Select An Generator */
+ dptxset(it6505, 0x3A, 0x01, 0x01);
+ /* Enable An Generator */
+ dptxset(it6505, 0x3A, 0x02, 0x02);
+ /* delay1ms(10);*/
+ usleep_range(10000, 15000);
+ /* Stop An Generator */
+ dptxset(it6505, 0x3A, 0x02, 0x00);
+
+ dptxset(it6505, 0x38, 0x01, 0x01);
+ dptxset(it6505, 0x39, 0x01, 0x01);
+
+ DRM_DEBUG_DRIVER("%s end !!\n", __func__);
+}
+
+void iTE6505_lanespeed_setup(struct it6505 *it6505)
+{
+ if (!it6505->hbr) {
+ dptxset(it6505, 0x16, 0x01, 1);
+ dptxset(it6505, 0x5C, 0x02, 0x00);
+ } else {
+ dptxset(it6505, 0x16, 0x01, 0);
+ dptxset(it6505, 0x5C, 0x02, 0x02);
+ }
+}
+
+void iTE6505_lane_swap(struct it6505 *it6505)
+{
+ int err;
+ union extcon_property_value property;
+
+ if (it6505->hpd_status == 0) {
+ err = extcon_get_property(it6505->port->extcon,
+ EXTCON_DISP_DP,
+ EXTCON_PROP_USB_TYPEC_POLARITY, &property);
+ if (err) {
+ DRM_DEBUG_DRIVER("%s get property fail!",
+ __func__);
+ }
+ it6505->laneswap = property.intval;
+ DRM_DEBUG_DRIVER("property.intval = 0x%d\n", property.intval);
+ }
+
+ dptxset(it6505, 0x16, 0x08, (it6505->laneswap) ? 8 : 0);
+ dptxset(it6505, 0x16, 0x06, (it6505->lane - 1) << 1);
+ DRM_DEBUG_DRIVER("it6505->laneswap = 0x%x\n", it6505->laneswap);
+
+ if (it6505->laneswap) {
+ switch (it6505->lane) {
+ case 1:
+ dptxset(it6505, 0x5C, 0xF1, 0x81);
+ break;
+ case 2:
+ dptxset(it6505, 0x5C, 0xF1, 0xC1);
+ break;
+ default:
+ dptxset(it6505, 0x5C, 0xF1, 0xF1);
+ break;
+ }
+ } else {
+ switch (it6505->lane) {
+ case 1:
+ dptxset(it6505, 0x5C, 0xF1, 0x11);
+ break;
+ case 2:
+ dptxset(it6505, 0x5C, 0xF1, 0x31);
+ break;
+ default:
+ dptxset(it6505, 0x5C, 0xF1, 0xF1);
+ break;
+ }
+ }
+}
+
+void iTE6505_lane_config(struct it6505 *it6505)
+{
+ iTE6505_lanespeed_setup(it6505);
+ iTE6505_lane_swap(it6505);
+}
+
+void dptx_chgbank(struct it6505 *it6505, unsigned int bank_id)
+{
+ dptxset(it6505, 0x0F, 0x01, bank_id & BIT(0));
+}
+
+void iTE6505_set_ssc(struct it6505 *it6505)
+{
+ dptxset(it6505, 0x16, 0x10, it6505->en_ssc << 4);
+ if (it6505->en_ssc) {
+ dptx_chgbank(it6505, 1);
+ dptxwr(it6505, 0x88, 0x9e);
+ dptxwr(it6505, 0x89, 0x1c);
+ dptxwr(it6505, 0x8A, 0x42);
+ dptx_chgbank(it6505, 0);
+ dptxwr(it6505, 0x58, 0x07);
+ dptxwr(it6505, 0x59, 0x29);
+ dptxwr(it6505, 0x5A, 0x03);
+ DRM_DEBUG_DRIVER("Enable 27M 4463 PPM SSC\n");
+ /* Stamp Interrupt Step */
+ dptxset(it6505, 0xD4, 0x30, 0x10);
+ dptx_dpcdwr(it6505, 0x107, 0x10);
+ } else {
+ dptx_dpcdwr(it6505, 0x107, 0x00);
+ dptxset(it6505, 0xD4, 0x30, 0x00);
+ }
+}
+
+void PCLK_phase(struct it6505 *it6505)
+{
+ dptxset(it6505, 0x10, 0x03, PCLK_DELAY);
+ dptxset(it6505, 0x12, 0x10, PCLK_INV << 4);
+}
+
+void AFE_driving_setting(struct it6505 *it6505)
+{
+ dptxset(it6505, 0x0F, 0x01, 0x01);
+ dptxwr(it6505, 0x7E, 0x93);
+ dptxwr(it6505, 0x7F, 0x2A);
+ dptxwr(it6505, 0x81, 0x85);
+ dptxset(it6505, 0x0F, 0x01, 0x00);
+}
+
+void dptx_output(struct it6505 *it6505, unsigned int HBR, unsigned int lane,
+ unsigned int laneswap, unsigned int en_ssc,
+ unsigned int EnhFraming)
+{
+ dptxwr(it6505, 0x05, 0x13);
+ /* change bank 0 */
+ dptxset(it6505, 0x0F, 0x01, 0x00);
+ /* RegTxFFRst set */
+ dptxset(it6505, 0x61, 0x02, 0x02);
+ /* RegTxFFRst clear */
+ dptxset(it6505, 0x61, 0x02, 0x00);
+ dptxwr(it6505, 0x64, 0x10);
+ dptxwr(it6505, 0x65, 0x80);
+ dptxwr(it6505, 0x66, 0x10);
+ dptxwr(it6505, 0x67, 0x4F);
+ dptxwr(it6505, 0x68, 0x09);
+ dptxwr(it6505, 0x69, 0xBA);
+ dptxwr(it6505, 0x6A, 0x3B);
+ dptxwr(it6505, 0x6B, 0x4B);
+ dptxwr(it6505, 0x6C, 0x3E);
+ dptxwr(it6505, 0x6D, 0x4F);
+ dptxwr(it6505, 0x6E, 0x09);
+ dptxwr(it6505, 0x6F, 0x56);
+ dptxwr(it6505, 0x70, 0x0E);
+ dptxwr(it6505, 0x71, 0x00);
+ dptxwr(it6505, 0x72, 0x00);
+ dptxwr(it6505, 0x73, 0x4F);
+ dptxwr(it6505, 0x74, 0x09);
+ dptxwr(it6505, 0x75, 0x00);
+ dptxwr(it6505, 0x76, 0x00);
+ dptxwr(it6505, 0x77, 0xE7);
+ dptxwr(it6505, 0x78, 0x10);
+ dptxwr(it6505, 0xE8, 0x00);
+ dptxset(it6505, 0xCE, 0x70, 0x60);
+ dptxset(it6505, 0xD0, 0xC0, 0x80);
+ dptxwr(it6505, 0xCA, 0x4D);
+ dptxwr(it6505, 0xC9, 0xF5);
+ dptxwr(it6505, 0x5C, 0x02);
+
+ dptx_dpcdwr(it6505, 0x600, 0x01);
+ dptxset(it6505, 0x59, 0x01, 0x01);
+ dptxset(it6505, 0x5A, 0x05, 0x01);
+ dptxwr(it6505, 0x12, 0x01);
+ dptxwr(it6505, 0xCB, 0x17);
+ dptxwr(it6505, 0x11, 0x09);
+ dptxwr(it6505, 0x20, 0x28);
+ dptxset(it6505, 0x23, 0x30, 00);
+ dptxset(it6505, 0x3A, 0x04, 0x04);
+ dptxset(it6505, 0x15, 0x01, 0x01);
+ dptxwr(it6505, 0x0C, 0x08);
+
+ dptxset(it6505, 0x5F, 0x20, 0x00);
+ iTE6505_lane_config(it6505);
+
+ iTE6505_set_ssc(it6505);
+
+ if (EnhFraming)
+ dptxwr(it6505, 0xD3, 0x33);
+ else
+ dptxwr(it6505, 0xD3, 0x32);
+
+ dptxset(it6505, 0x15, 0x02, 0x02);
+ dptxset(it6505, 0x15, 0x02, 0x00);
+ dptxset(it6505, 0x05, 0x03, 0x02);
+ dptxset(it6505, 0x05, 0x03, 0x00);
+
+ /* reg60[2] = InDDR */
+ dptxwr(it6505, 0x60, 0x44);
+ /* M444B24 foramt */
+ dptxwr(it6505, 0x62, 1);
+ /* select RGB Bypass CSC */
+ dptxwr(it6505, 0x63, 0);
+
+ PCLK_phase(it6505);
+ dptxset(it6505, 0x61, 0x01, 0x01);
+ dptxwr(it6505, 0x06, 0xFF);
+ dptxwr(it6505, 0x07, 0xFF);
+ dptxwr(it6505, 0x08, 0xFF);
+
+ dptxset(it6505, 0xd3, 0x30, 0x00);
+ dptxset(it6505, 0xd4, 0x41, 0x41);
+ dptxset(it6505, 0xe8, 0x11, 0x11);
+
+ AFE_driving_setting(it6505);
+ dptxwr(it6505, 0x17, 0x04);
+ dptxwr(it6505, 0x17, 0x01);
+ DRM_DEBUG_DRIVER(" ======= end main flow! !========\n");
+}
+
+
+void dptx_sys_fsm(struct it6505 *it6505)
+{
+ unsigned int value, temp1, temp2, temp3;
+ unsigned int count, dpcd1[0x09], dpcd2[0x18];
+ unsigned int temp, i, dpcdstart = 0x100;
+ int ret, reg0D, reg9F;
+#if ENHDCP
+ unsigned int Ar0_low, Ar0_high, Br0_low, Br0_high;
+#endif
+
+ DRM_DEBUG_DRIVER("%s start state: %d\n", __func__,
+ it6505->status);
+
+ dptxrd(it6505, 0x0D, &reg0D);
+
+ if (it6505->status != SYS_UNPLUG && !(reg0D & BIT(1)))
+ dptx_sys_chg(it6505, SYS_UNPLUG);
+
+ switch (it6505->status) {
+ case SYS_PWRDN:
+ break;
+ case SYS_UNPLUG:
+ DRM_DEBUG_DRIVER("sys_state is in SYS_UNPLUG!!\n");
+ break;
+
+ case SYS_HPD:
+ DRM_DEBUG_DRIVER("Is in SYS_HPD!!\n");
+ dptxrd(it6505, 0x9f, &reg9F);
+ DRM_DEBUG_DRIVER("Aux channel status reg9F=0x%02x\n", reg9F);
+ /* GETDPCD */
+ iTE6505_GetDPCD(it6505);
+ iTE6505_ParseDPCD(it6505);
+
+ /*
+ * training fail TRAINFAILCNT times,
+ * then change to HPD to restart
+ */
+ it6505->cntfsm = TRAINFAILCNT;
+ DRM_DEBUG_DRIVER("will Train %s %d lanes\n",
+ it6505->hbr ? "HBR" : "LBR", it6505->lane);
+ dptx_sys_chg(it6505, SYS_AUTOTRAIN);
+ break;
+
+ case SYS_AUTOTRAIN:
+ DRM_DEBUG_DRIVER("%s in SYS_AUTOTRAIN!\n", __func__);
+ dptx_output(it6505,
+ it6505->hbr,
+ it6505->lane,
+ it6505->laneswap,
+ it6505->en_ssc,
+ it6505->en_hframe);
+
+ /*
+ * waiting for training down flag
+ * because we don't know
+ * how long this step will be completed
+ * so use step 1ms to wait
+ */
+ for (count = 0; count < FLAGTRAINDOWN; count++) {
+ msleep(1);
+ dptxrd(it6505, 0x0E, &temp3);
+ if (temp3 & BIT(4))
+ break;
+ }
+
+ dptx_sys_chg(it6505, SYS_WAIT);
+ break;
+
+ case SYS_WAIT:
+ DRM_DEBUG_DRIVER("%s in SYS_WAIT!!\n", __func__);
+ ret = dptxrd(it6505, 0x0E, &value);
+ i = dpcdstart;
+ temp = ARRAY_SIZE(dpcd1);
+ DRM_DEBUG_DRIVER("SYS_WAIT state parse %d dpcd offset!\n",
+ temp + ARRAY_SIZE(dpcd2));
+
+ for (i = 0; i < temp; i++) {
+ dpcd1[i] = dptx_dpcdrd(it6505, dpcdstart + i);
+ DRM_DEBUG_DRIVER("dpcd[0x%02x]:0x%02x",
+ dpcdstart + i, dpcd1[i]);
+ }
+ dpcdstart = 0x200;
+ i = dpcdstart;
+ temp = ARRAY_SIZE(dpcd2);
+
+ for (i = 0; i < temp; i++) {
+ dpcd2[i] = dptx_dpcdrd(it6505, dpcdstart + i);
+ DRM_DEBUG_DRIVER("dpcd[0x%02x]:0x%02x",
+ dpcdstart + i, dpcd2[i]);
+ }
+
+ if (value & BIT(4)) {
+ DRM_DEBUG_DRIVER("Auto Link Training Success ...\n");
+ DRM_DEBUG_DRIVER("Link State : 0x%X\n", value & 0x1F);
+#if ENAUD
+ iTE6505_SetAudio(it6505,
+ it6505->aud_sel, it6505->aud_type,
+ it6505->aud_fs, it6505->aud_ch);
+#endif
+ DRM_DEBUG_DRIVER("it6505->VidStable_Done = %02x\n",
+ it6505->vidstable_done);
+#if ENHDCP
+ DRM_DEBUG_DRIVER("Config ENHDCP\n");
+ if (it6505->cp_ready) {
+ DRM_DEBUG_DRIVER("Sink cp_ready:%02x\n",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Support HDCP\n");
+ dptx_sys_chg(it6505, SYS_ReHDCP);
+ } else {
+ DRM_DEBUG_DRIVER("Sink cp_ready:%02x\n",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Not support HDCP\n");
+ dptx_sys_chg(it6505, SYS_NOROP);
+ }
+#else
+ DRM_DEBUG_DRIVER("Not config ENHDCP\n");
+ dptx_sys_chg(it6505, SYS_NOROP);
+#endif
+ } else {
+ dptxrd(it6505, 0x0D, &temp2);
+ dptxrd(it6505, 0x0E, &temp1);
+ DRM_DEBUG_DRIVER("Auto Link Training fail step %d!\n",
+ it6505->cntfsm);
+ DRM_DEBUG_DRIVER("reg0E:0x%x, reg0D:0x%x!\n",
+ temp1, temp2);
+ if (it6505->cntfsm > 0) {
+ it6505->cntfsm--;
+ dptx_sys_chg(it6505, SYS_AUTOTRAIN);
+ } else {
+ DRM_DEBUG_DRIVER("Auto Training Fail");
+ DRM_DEBUG_DRIVER("0x%x times\n",
+ TRAINFAILCNT);
+ DRM_DEBUG_DRIVER("Sys change to SYS_HPD!\n");
+ dptx_dpcdwr(it6505, 0x102, 0x00);
+ dptx_sys_chg(it6505, SYS_HPD);
+ }
+ }
+ break;
+
+#if ENHDCP
+ case SYS_ReHDCP:
+ msleep(600);
+ dptxrd(it6505, 0x3B, &Ar0_low);
+ dptxrd(it6505, 0x3C, &Ar0_high);
+ dptxrd(it6505, 0x45, &Br0_low);
+ dptxrd(it6505, 0x46, &Br0_high);
+ DRM_DEBUG_DRIVER("Before EnableHDCP\n");
+ DRM_DEBUG_DRIVER("Ar0_low:%x, Ar0_high:%x\n",
+ Ar0_low, Ar0_high);
+ DRM_DEBUG_DRIVER("Br0_low:%x, Br0_high:%x\n",
+ Br0_low, Br0_high);
+ iTE6505_EnableHDCP(it6505);
+ msleep(200);
+ DRM_DEBUG_DRIVER("SYS_ReHDCP end !!\n");
+ break;
+
+#endif
+ case SYS_NOROP:
+ break;
+
+ default:
+ DRM_DEBUG_DRIVER("sys_state change to unknown_state!!\n");
+ break;
+ }
+
+ DRM_DEBUG_DRIVER("%s end!!\n", __func__);
+
+}
+
+static int it6505_poweron(struct it6505 *it6505)
+{
+ struct it6505_platform_data *pdata = &it6505->pdata;
+ int err = 0;
+
+ DRM_DEBUG_DRIVER("%s\n", __func__);
+
+ if (it6505->powered) {
+ DRM_DEBUG_DRIVER("[%s] had already been power on!", __func__);
+ return 0;
+ }
+
+ DRM_DEBUG_DRIVER("it6505 start to power on\n");
+
+ err = regulator_enable(pdata->pwr18);
+ DRM_DEBUG_DRIVER("%s to enable pwr18 regulator",
+ err ? "Failed" : "Successed");
+ /* time interval between IVDD and OVDD at least be 1ms */
+ msleep(5);
+ err = regulator_enable(pdata->ovdd);
+ DRM_DEBUG_DRIVER("%s to enable ovdd regulator",
+ err ? "Failed" : "Successed");
+ /* time interval between OVDD and SYSRSTN at least be 10ms */
+ msleep(15);
+ usleep_range(10000, 20000);
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
+ usleep_range(10000, 20000);
+
+ dptx_init(it6505);
+ if (err == 0)
+ it6505->powered = true;
+ return err;
+}
+
+#ifdef ENPWRONOFF
+static int it6505_poweroff(struct it6505 *it6505)
+{
+ struct it6505_platform_data *pdata = &it6505->pdata;
+ int err = 0;
+
+ DRM_DEBUG_DRIVER("[%s]\n", __func__);
+ if (!(it6505->powered)) {
+ DRM_DEBUG_DRIVER("[%s] power had been already off", __func__);
+ return 0;
+ }
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+ err = regulator_disable(pdata->pwr18);
+ DRM_DEBUG_DRIVER("%s to disable pwr18 regulator",
+ err ? "Failed" : "Successed");
+
+ err = regulator_disable(pdata->ovdd);
+ DRM_DEBUG_DRIVER("%s to disable ovdd regulator",
+ err ? "Failed" : "Successed");
+ if (err == 0) {
+ kfree(it6505->edid);
+ it6505->edid = NULL;
+ it6505->powered = false;
+ }
+ return err;
+}
+#endif
+
+static irqreturn_t it6505_hpd_threaded_handler(int irq, void *data)
+{
+ struct it6505 *ctx = data;
+
+ DRM_DEBUG_DRIVER("start %s", __func__);
+
+ mutex_lock(&ctx->lock);
+
+ DRM_DEBUG_DRIVER("[%s]it6505->hpd_status = 0x%02x\n",
+ __func__, ctx->hpd_status);
+ DRM_DEBUG_DRIVER("[%s]GPIO hpd status = 0x%02x\n",
+ __func__,
+ gpiod_get_value(ctx->pdata.gpiod_hpd));
+
+ if ((ctx->it6505_drv_hold == 0)
+ && (ctx->hpd_status
+ != gpiod_get_value(ctx->pdata.gpiod_hpd))) {
+ drm_helper_hpd_irq_event(ctx->connector.dev);
+ DRM_DEBUG_DRIVER("it6505->hpd_status = 0x%02x",
+ ctx->hpd_status);
+ DRM_DEBUG_DRIVER("GPIO hpd status = 0x%02x",
+ gpiod_get_value(ctx->pdata.gpiod_hpd));
+ DRM_DEBUG_DRIVER("after drm_helper_hpd_irq_event!\n");
+ ctx->hpd_status = gpiod_get_value(ctx->pdata.gpiod_hpd);
+ }
+
+ mutex_unlock(&ctx->lock);
+
+ DRM_DEBUG_DRIVER("end %s", __func__);
+
+ return IRQ_HANDLED;
+}
+
+void SHA1_digest(u8 *sha1_input, u8 size, u8 *output_av)
+{
+ struct shash_desc *desc;
+ struct sha1_state *sha1_st;
+ struct crypto_shash *tfm = crypto_alloc_shash("sha1", 0, 0);
+
+ DRM_DEBUG_DRIVER("start %s",__func__);
+ DRM_DEBUG_DRIVER("sha_input size:%d", size);
+ desc = kzalloc(sizeof(*desc)
+ + crypto_shash_descsize(tfm), GFP_KERNEL);
+ desc->tfm = tfm;
+ DRM_DEBUG_DRIVER("crypto_alloc_shash %s!",
+ IS_ERR(desc->tfm) ? "fail" : "success");
+ DRM_DEBUG_DRIVER("crypto_shash_init %s!",
+ crypto_shash_init(desc) ? "fail" : "success");
+ DRM_DEBUG_DRIVER("crypto_shash_update %s!",
+ crypto_shash_update(desc, sha1_input, size)
+ ? "fail" : "success");
+ sha1_st = (struct sha1_state *)(desc->__ctx);
+#ifdef SHA_DEBUG
+ DRM_DEBUG_DRIVER("sha1_state.state[0]:0x%lx",
+ sha1_st->state[0]);
+ DRM_DEBUG_DRIVER("sha1_state.state[1]:0x%lx",
+ sha1_st->state[1]);
+ DRM_DEBUG_DRIVER("sha1_state.state[2]:0x%lx",
+ sha1_st->state[2]);
+ DRM_DEBUG_DRIVER("sha1_state.state[3]:0x%lx",
+ sha1_st->state[3]);
+ DRM_DEBUG_DRIVER("sha1_state.state[4]:0x%lx",
+ sha1_st->state[4]);
+#endif
+ memcpy(output_av, sha1_st->state, sizeof(u8)*20);
+ crypto_free_shash(tfm);
+ tfm = NULL;
+ kfree(desc);
+ desc = NULL;
+ sha1_st = NULL;
+ DRM_DEBUG_DRIVER("end %s", __func__);
+}
+
+void it6505_makeup_sha1_input(struct it6505 *it6505)
+{
+ int msgcnt = 0, i;
+ unsigned long ksvlist;
+
+ dptxset(it6505, 0x3A, 0x20, 0x20);
+ DRM_DEBUG_DRIVER("read am0: ");
+ for (i = 0; i < 8; i++) {
+ dptxrd(it6505,
+ 0x4C + i,
+ (unsigned int *)(it6505->am0 + i));
+ DRM_DEBUG_DRIVER("0x%02X , ", it6505->am0[i]);
+ }
+ DRM_DEBUG_DRIVER("\n\n");
+ dptxset(it6505, 0x3A, 0x20, 0x00);
+
+ it6505->binfo[0] = dptx_dpcdrd(it6505,
+ 0x6802A);
+ it6505->binfo[1] = dptx_dpcdrd(it6505,
+ 0x6802B);
+ DRM_DEBUG_DRIVER("read Binfo!!");
+ DRM_DEBUG_DRIVER("Attached devices:%02x\n",
+ it6505->binfo[0] & 0x7F);
+
+ DRM_DEBUG_DRIVER("%s 127 devices are attached\n",
+ ((it6505->binfo[0] & BIT(7)) >> 7) ?
+ "over" : "under");
+ DRM_DEBUG_DRIVER("depth, attached levels:%02x\n",
+ it6505->binfo[1] & 0x07);
+ DRM_DEBUG_DRIVER("%s seven levels cascaded\n",
+ ((it6505->binfo[1] & BIT(3)) >> 3) ?
+ "more than" : "less");
+
+ for (i = 0; i < (it6505->binfo[0] & 0x7F); i++) {
+ it6505->shainput[msgcnt]
+ = it6505->ksvlist[msgcnt]
+ = dptx_dpcdrd(it6505,
+ 0x6802C + (i % 3) * 5);
+ msgcnt++;
+ it6505->shainput[msgcnt]
+ = it6505->ksvlist[msgcnt]
+ = dptx_dpcdrd(it6505,
+ 0x6802D + (i % 3) * 5);
+ msgcnt++;
+ it6505->shainput[msgcnt]
+ = it6505->ksvlist[msgcnt]
+ = dptx_dpcdrd(it6505,
+ 0x6802E + (i % 3) * 5);
+ msgcnt++;
+ it6505->shainput[msgcnt]
+ = it6505->ksvlist[msgcnt]
+ = dptx_dpcdrd(it6505,
+ 0x6802F + (i % 3) * 5);
+ msgcnt++;
+ it6505->shainput[msgcnt]
+ = it6505->ksvlist[msgcnt]
+ = dptx_dpcdrd(it6505,
+ 0x68030 + (i % 3) * 5);
+ msgcnt++;
+ ksvlist
+ = ((unsigned long)
+ (it6505->ksvlist[i * 5 + 4]) << 32)
+ + (it6505->ksvlist[i * 5 + 3] << 24)
+ + (it6505->ksvlist[i * 5 + 2] << 16)
+ + (it6505->ksvlist[i * 5 + 1] << 8)
+ + it6505->ksvlist[i * 5];
+
+ DRM_DEBUG_DRIVER("KSV List %d device:0x%lx\n",
+ i, ksvlist);
+ }
+ DRM_DEBUG_DRIVER("\n");
+ it6505->shainput[msgcnt++] = it6505->binfo[0];
+ it6505->shainput[msgcnt++] = it6505->binfo[1];
+ for (i = 0; i < 8; i++) {
+ it6505->shainput[msgcnt++] =
+ it6505->am0[i];
+ }
+ DRM_DEBUG_DRIVER("SHA Message Count = %d\n", msgcnt);
+ it6505->shainput[msgcnt] = 0x80;
+
+ for (i = msgcnt+1; i < 62; i++)
+ it6505->shainput[i] = 0x00;
+
+ it6505->shainput[62] = ((8 * msgcnt) >> 8) & 0xFF;
+ it6505->shainput[63] = (8 * msgcnt) & 0xFF;
+}
+
+void it6505_check_sha1_result(struct it6505 *it6505)
+{
+ unsigned int i, value;
+
+ DRM_DEBUG_DRIVER("SHA calculate complete!\n");
+ for (i = 0; i < 5; i++) {
+ value
+ = (it6505->av[i][3] << 24)
+ + (it6505->av[i][2] << 16)
+ + (it6505->av[i][1] << 8)
+ + it6505->av[i][0];
+ DRM_DEBUG_DRIVER("av %d :0x%08x\n",
+ i, value);
+ }
+ DRM_DEBUG_DRIVER("\n");
+
+ it6505->passsha = 1;
+ for (i = 0; i < 5; i++) {
+ it6505->bv[i][0]
+ = dptx_dpcdrd(it6505, 0x68014 + i * 4);
+ it6505->bv[i][1]
+ = dptx_dpcdrd(it6505, 0x68015 + i * 4);
+ it6505->bv[i][2]
+ = dptx_dpcdrd(it6505, 0x68016 + i * 4);
+ it6505->bv[i][3]
+ = dptx_dpcdrd(it6505, 0x68017 + i * 4);
+ value
+ = (it6505->bv[i][3] << 24)
+ + (it6505->bv[i][2] << 16)
+ + (it6505->bv[i][1] << 8)
+ + it6505->bv[i][0];
+ DRM_DEBUG_DRIVER("bv %d :0x%08x\n",
+ i, value);
+ if ((it6505->bv[i][0]
+ != it6505->av[i][0]) ||
+ (it6505->bv[i][1]
+ != it6505->av[i][1]) ||
+ (it6505->bv[i][2]
+ != it6505->av[i][2]) ||
+ (it6505->bv[i][3]
+ != it6505->av[i][3])) {
+ it6505->passsha = 0;
+ }
+ }
+ if (it6505->passsha) {
+ DRM_DEBUG_DRIVER("SHA check result pass!\n");
+ DRM_DEBUG_DRIVER("trigger reg0x39[4] = 1\n");
+ dptxset(it6505, 0x39, 0x10, 0x10);
+ } else {
+ DRM_DEBUG_DRIVER("SHA check result fail\n");
+ DRM_DEBUG_DRIVER("trigger reg0x39[5] = 1\n");
+ dptxset(it6505, 0x39, 0x20, 0x20);
+ }
+}
+
+void HPD_IRQ(struct it6505 *it6505)
+{
+ unsigned int dpcd200, dpcd201, dpcd202, dpcd203;
+ unsigned int dpcd204, dpcd205, auxbusycnt, AuxBusy, value, reg55;
+ int ret;
+#ifdef SHA_DEBUG
+ int i;
+#endif
+
+ dpcd200 = dptx_dpcdrd(it6505, 0x200);
+ dpcd201 = dptx_dpcdrd(it6505, 0x201);
+ dpcd202 = dptx_dpcdrd(it6505, 0x202);
+ dpcd203 = dptx_dpcdrd(it6505, 0x203);
+ dpcd204 = dptx_dpcdrd(it6505, 0x204);
+ dpcd205 = dptx_dpcdrd(it6505, 0x205);
+
+ DRM_DEBUG_DRIVER("dpcd200 = 0x%x\n", dpcd200);
+ DRM_DEBUG_DRIVER("dpcd201 = 0x%x\n", dpcd201);
+ DRM_DEBUG_DRIVER("dpcd202 = 0x%x\n", dpcd202);
+ DRM_DEBUG_DRIVER("dpcd203 = 0x%x\n", dpcd203);
+ DRM_DEBUG_DRIVER("dpcd204 = 0x%x\n", dpcd204);
+ DRM_DEBUG_DRIVER("dpcd205 = 0x%x\n", dpcd205);
+
+ if (dpcd201 & BIT(2)) {
+ ret = dptxrd(it6505, 0x38, &value);
+ it6505->bstatus = dptx_dpcdrd(it6505, 0x68029);
+ dptxrd(it6505, 0x55, &reg55);
+ DRM_DEBUG_DRIVER("reg0x55 = 0x%02x, reg0x68029 = 0x%02x\n",
+ reg55, it6505->bstatus);
+ if (value & BIT(0)) {
+
+ if (it6505->cp_done) {
+ DRM_DEBUG_DRIVER("Received CP_IRQ");
+ DRM_DEBUG_DRIVER(" cp_done = '1'");
+ DRM_DEBUG_DRIVER("Current bstatus = 0x%x\n",
+ it6505->bstatus);
+ } else {
+ DRM_DEBUG_DRIVER("Received CP_IRQ\n");
+ DRM_DEBUG_DRIVER("cp_done = '0'\n");
+ }
+
+ if (!it6505->cp_done || it6505->bstatus & BIT(2)) {
+ DRM_DEBUG_DRIVER("Trigger CP_IRQ");
+ DRM_DEBUG_DRIVER(" to HDCP Engine\n");
+
+ dptxset(it6505, 0x39, 0x02, 0x02);
+
+ auxbusycnt = 0;
+ do {
+ usleep_range(1000, 1500);
+
+ auxbusycnt++;
+ ret = dptxrd(it6505, 0x2B, &value);
+ AuxBusy = (value & BIT(5)) >> 5;
+ } while (AuxBusy == 1 && auxbusycnt < 20);
+
+
+ if (AuxBusy) {
+ DRM_DEBUG_DRIVER("AUX Busy Period!");
+ } else {
+ msleep(1000);
+ dptxrd(it6505, 0x55, &it6505->bstatus);
+ DRM_DEBUG_DRIVER("Link Integrity Fail");
+ DRM_DEBUG_DRIVER(" = %d\n",
+ (it6505->bstatus & BIT(2)) >> 2);
+ DRM_DEBUG_DRIVER("R0' Available = %d\n",
+ (it6505->bstatus & BIT(1)) >> 1);
+ DRM_DEBUG_DRIVER("KSV List Ready=%d\n",
+ (it6505->bstatus & BIT(0)));
+ }
+ }
+ }
+ DRM_DEBUG_DRIVER("Receive CP_IRQ!\n");
+ it6505->bstatus = dptx_dpcdrd(it6505, 0x68029);
+ dptxrd(it6505, 0x55, &reg55);
+ DRM_DEBUG_DRIVER("Cause of the interrupt!");
+ DRM_DEBUG_DRIVER("reg0x68029 = 0x%02x, reg0x55 = 0x%02x\n",
+ it6505->bstatus, reg55);
+
+ if (it6505->bstatus & BIT(0)) {
+ DRM_DEBUG_DRIVER("HDCP KSV list ready!! ...\n");
+ it6505_makeup_sha1_input(it6505);
+ SHA1_digest(it6505->shainput,
+ sizeof(it6505->shainput), (u8 *)it6505->av);
+
+ /* for SHA debug */
+#ifdef SHA_DEBUG
+ DRM_DEBUG_DRIVER("SHA_input:\n");
+ for (i = 0; i < 64; i++) {
+ if (!(i % 16))
+ DRM_DEBUG_DRIVER("\n");
+ DRM_DEBUG_DRIVER("0x%02x", it6505->shainput[i]);
+ }
+#endif
+ it6505_check_sha1_result(it6505);
+ }
+ }
+
+ if ((dpcd204 & BIT(7)) == 0x80) {
+ if ((it6505->lane == 1 && (dpcd202 & BIT(2)) != 0x04) ||
+ (it6505->lane == 2 && (dpcd202 & 0x44) != 0x44) ||
+ (it6505->lane == 4 && ((dpcd202 & 0x44) != 0x44 ||
+ (dpcd203 & 0x44) != 0x44)) ||
+ (it6505->lane == 1 && (dpcd203 & BIT(6)) != 0x40) ||
+ (it6505->lane == 2 && (dpcd203 & 0x44) != 0x44) ||
+ (it6505->lane == 4 && ((dpcd203 & 0x44) != 0x44 ||
+ (dpcd202 & 0x44) != 0x44)) ||
+ (dpcd204 & BIT(0)) != 0x01) {
+
+ DRM_DEBUG_DRIVER("Link Re-Training\n");
+ dptxset(it6505, 0xD3, 0x30, 0x30);
+ dptxset(it6505, 0xE8, 0x33, 0x00);
+ msleep(500);
+ dptx_sys_chg(it6505, SYS_HPD);
+#if ENHDCP
+ DRM_DEBUG_DRIVER("INT_MODE:Config ENHDCP\n");
+ if (it6505->cp_ready) {
+ DRM_DEBUG_DRIVER("INT_MODE:Sink cp_ready:%d\n",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Support HDCP\n");
+ while (it6505->status != SYS_ReHDCP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status
+ == SYS_UNPLUG)
+ break;
+ }
+ dptx_sys_fsm(it6505);
+ if (it6505->downstreamrepeater) {
+ DRM_DEBUG_DRIVER("This is repeater!\n");
+ HPD_IRQ(it6505);
+ }
+ } else {
+ DRM_DEBUG_DRIVER("INT_MODE:Sink cp_ready:%d\n",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Not support HDCP\n");
+ while (it6505->status != SYS_NOROP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status
+ == SYS_UNPLUG)
+ break;
+ }
+ }
+#else
+ DRM_DEBUG_DRIVER("INT_MODE:Unconfig ENHDCP\n");
+ while (it6505->status != SYS_NOROP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status
+ == SYS_UNPLUG)
+ break;
+ }
+#endif
+ }
+ }
+}
+
+void it6505_check_reg06(struct it6505 *it6505, unsigned int reg06)
+{
+ unsigned int rddata, err;
+ union extcon_property_value property;
+
+ if (reg06 & BIT(0)) {
+ /* hpd pin status change */
+ DRM_DEBUG_DRIVER("HPD Change Interrupt\n");
+ dptxrd(it6505, 0x0D, &rddata);
+ if (rddata & BIT(1)) {
+ err = extcon_get_property(it6505->port->extcon,
+ EXTCON_DISP_DP,
+ EXTCON_PROP_USB_TYPEC_POLARITY, &property);
+ if (err) {
+ DRM_DEBUG_DRIVER("%s get property fail!",
+ __func__);
+ }
+
+ it6505->laneswap = property.intval;
+ DRM_DEBUG_DRIVER("laneswap:%d", it6505->laneswap);
+ dptx_sys_chg(it6505, SYS_HPD);
+ dptx_sys_fsm(it6505);
+#if ENHDCP
+ DRM_DEBUG_DRIVER("Config ENHDCP\n");
+ if (it6505->cp_ready) {
+ DRM_DEBUG_DRIVER("Sink cp_ready:%d\n",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Support HDCP\n");
+ while (it6505->status != SYS_ReHDCP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status
+ == SYS_UNPLUG)
+ break;
+ }
+ dptx_sys_fsm(it6505);
+ if (it6505->downstreamrepeater) {
+ DRM_DEBUG_DRIVER("Is repeater");
+ HPD_IRQ(it6505);
+ }
+ } else {
+ DRM_DEBUG_DRIVER("Sink cp_ready:%d\n",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Not support HDCP\n");
+ while (it6505->status != SYS_NOROP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status
+ == SYS_UNPLUG)
+ break;
+ }
+ }
+#else
+ DRM_DEBUG_DRIVER("Not config ENHDCP\n");
+ while (it6505->status != SYS_NOROP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status == SYS_UNPLUG)
+ break;
+ }
+#endif
+ } else {
+ dptx_sys_chg(it6505, SYS_UNPLUG);
+ }
+ }
+
+ if (reg06 & BIT(1)) {
+ DRM_DEBUG_DRIVER("HPD IRQ Interrupt\n");
+ HPD_IRQ(it6505);
+ }
+
+ if (reg06 & BIT(2)) {
+ dptxrd(it6505, 0x0D, &rddata);
+
+ if ((rddata & BIT(2)) >> 2) {
+ DRM_DEBUG_DRIVER("Video Stable On Interrupt\n");
+ it6505->vidstable_done = 1;
+ DRM_DEBUG_DRIVER("Set vidstable_done = 0x%x\n",
+ it6505->vidstable_done);
+ } else {
+ DRM_DEBUG_DRIVER("Video Stable Off Interrupt");
+ it6505->vidstable_done = 0;
+ DRM_DEBUG_DRIVER("Set vidstable_done = 0x%x\n",
+ it6505->vidstable_done);
+ }
+ }
+
+#if ENHDCP
+ if (reg06 & BIT(3)) {
+ DRM_DEBUG_DRIVER("HDCP encryption Fail Interrupt\n");
+ DRM_DEBUG_DRIVER("HDCP retry! ...\n");
+ it6505->cp_done = 0;
+ DRM_DEBUG_DRIVER("Set it6505->cp_done = 0x%x ...\n",
+ it6505->cp_done);
+ dptx_sys_fsm(it6505);
+ }
+
+ if (reg06 & BIT(4)) {
+ DRM_DEBUG_DRIVER("HDCP encryption Done Interrupt\n");
+ it6505->cp_done = 1;
+ DRM_DEBUG_DRIVER("Set it6505->cp_done = 0x%x ...\n",
+ it6505->cp_done);
+ dptx_sys_chg(it6505, SYS_NOROP);
+ }
+#endif
+}
+
+void it6505_check_reg07(struct it6505 *it6505, unsigned int reg07)
+{
+ if (reg07 & BIT(0))
+ DRM_DEBUG_DRIVER("AUX PC Request Fail Interrupt\n");
+
+ if (reg07 & BIT(1)) {
+ unsigned int Ar0_low, Ar0_high, Br0_low, Br0_high;
+
+ DRM_DEBUG_DRIVER("HDCP event Interrupt\n");
+ it6505->bstatus = dptx_dpcdrd(it6505, 0x68029);
+ dptxrd(it6505, 0x3B, &Ar0_low);
+ dptxrd(it6505, 0x3C, &Ar0_high);
+ dptxrd(it6505, 0x45, &Br0_low);
+ dptxrd(it6505, 0x46, &Br0_high);
+ /*
+ * Read Bstatus to determine what happened
+ */
+ DRM_DEBUG_DRIVER("Bstatus reg0x68029:%02x!\n",
+ it6505->bstatus);
+ if (!(it6505->bstatus & BIT(0))) {
+ DRM_DEBUG_DRIVER("R0' read back by TX!\n");
+ DRM_DEBUG_DRIVER("HDCP part I complete!");
+ DRM_DEBUG_DRIVER("Ar0_low:%02x",
+ Ar0_low);
+ DRM_DEBUG_DRIVER("Ar0_high:%02x\n",
+ Ar0_high);
+ DRM_DEBUG_DRIVER("Br0_low:%02x",
+ Br0_low);
+ DRM_DEBUG_DRIVER("Br0_high:%02x\n",
+ Br0_high);
+ }
+ }
+#if ENAUD
+ if (reg07 & BIT(2)) {
+ DRM_DEBUG_DRIVER("Audio FIFO OverFlow Interrupt\n");
+ dptxset(it6505, 0xD3, 0x20, 0x20);
+ dptxset(it6505, 0xE8, 0x22, 0x00);
+
+ dptxset(it6505, 0xB8, 0x80, 0x80);
+ dptxset(it6505, 0xB8, 0x80, 0x00);
+ iTE6505_SetAudio(it6505,
+ it6505->aud_sel,
+ it6505->aud_type,
+ it6505->aud_fs,
+ it6505->aud_ch);
+ }
+#endif
+}
+
+void it6505_check_reg08(struct it6505 *it6505, unsigned int reg08)
+{
+ if (reg08 & BIT(4)) {
+ DRM_DEBUG_DRIVER("Link Training Fail Interrupt\n");
+ /* restart training */
+ dptx_sys_chg(it6505, SYS_AUTOTRAIN);
+#if ENHDCP
+ DRM_DEBUG_DRIVER("Config ENHDCP ...\n");
+ if (it6505->cp_ready) {
+ DRM_DEBUG_DRIVER("Sink cp_ready:%d",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Support HDCP\n");
+ while (it6505->status != SYS_ReHDCP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status == SYS_UNPLUG)
+ break;
+ }
+ dptx_sys_fsm(it6505);
+ if (it6505->downstreamrepeater) {
+ DRM_DEBUG_DRIVER("This is repeater!\n");
+ HPD_IRQ(it6505);
+ }
+ } else {
+ DRM_DEBUG_DRIVER("Sink cp_ready:%d",
+ it6505->cp_ready);
+ DRM_DEBUG_DRIVER("Not support HDCP\n");
+ while (it6505->status != SYS_NOROP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status == SYS_UNPLUG)
+ break;
+ }
+ }
+#else
+ DRM_DEBUG_DRIVER("Not config ENHDCP\n");
+ while (it6505->status != SYS_NOROP) {
+ dptx_sys_fsm(it6505);
+ if (it6505->status == SYS_UNPLUG)
+ break;
+ }
+#endif
+ }
+
+ if (reg08 & BIT(7)) {
+ DRM_DEBUG_DRIVER("IO Latch FIFO OverFlow Interrupt\n");
+ dptxset(it6505, 0x61, 0x02, 0x02);
+ dptxset(it6505, 0x61, 0x02, 0x00);
+ }
+}
+
+void it6505_dptx_irq(struct it6505 *it6505)
+{
+ unsigned int reg06, reg07, reg08, reg0d;
+
+ dptxrd(it6505, 0x06, &reg06);
+ dptxrd(it6505, 0x07, &reg07);
+ dptxrd(it6505, 0x08, &reg08);
+ dptxrd(it6505, 0x0D, &reg0d);
+
+ dptxwr(it6505, 0x06, reg06);
+ dptxwr(it6505, 0x07, reg07);
+ dptxwr(it6505, 0x08, reg08);
+
+ DRM_DEBUG_DRIVER("[%s] reg06 = 0x%x\n", __func__, reg06);
+ DRM_DEBUG_DRIVER("reg07 = 0x%x\n", reg07);
+ DRM_DEBUG_DRIVER("reg08 = 0x%x\n", reg08);
+ DRM_DEBUG_DRIVER("reg0d = 0x%x\n", reg0d);
+
+ if (reg06 != 0)
+ it6505_check_reg06(it6505, reg06);
+
+ if (reg07 != 0)
+ it6505_check_reg07(it6505, reg07);
+
+ if (reg08 != 0)
+ it6505_check_reg08(it6505, reg08);
+}
+
+
+static void it6505_bridge_enable(struct drm_bridge *bridge)
+{
+ struct it6505 *ctx = bridge_to_it6505(bridge);
+
+ DRM_DEBUG_DRIVER("start %s\n", __func__);
+
+ it6505_initfsm(ctx);
+ iTE6505_INT_mask(ctx);
+ dptx_sys_chg(ctx, SYS_HPD);
+
+ DRM_DEBUG_DRIVER("%s end\n", __func__);
+}
+
+static void it6505_bridge_disable(struct drm_bridge *bridge)
+{
+ DRM_DEBUG_DRIVER("start %s\n", __func__);
+ DRM_DEBUG_DRIVER("end %s\n", __func__);
+}
+
+static const struct drm_bridge_funcs it6505_bridge_funcs = {
+ .attach = it6505_bridge_attach,
+ .mode_valid = it6505_bridge_mode_valid,
+ .disable = it6505_bridge_disable,
+ .mode_set = it6505_bridge_mode_set,
+ .enable = it6505_bridge_enable,
+};
+
+static irqreturn_t it6505_intp_threaded_handler(int unused, void *data)
+{
+ struct it6505 *ctx = data;
+
+ DRM_DEBUG_DRIVER("[%s] start\n", __func__);
+
+ if (ctx->it6505_drv_hold == 0 && ctx->powered) {
+ mutex_lock(&ctx->lock);
+
+ it6505_dptx_irq(ctx);
+
+ mutex_unlock(&ctx->lock);
+ }
+
+ DRM_DEBUG_DRIVER("[%s] end\n", __func__);
+
+ return IRQ_HANDLED;
+}
+
+static int it6505_init_pdata(struct it6505 *it6505)
+{
+ struct it6505_platform_data *pdata = &it6505->pdata;
+ struct device *dev = &it6505->client->dev;
+
+ /* 1.0V digital core power regulator */
+ pdata->pwr18 = devm_regulator_get(dev, "pwr18");
+ if (IS_ERR(pdata->pwr18)) {
+ DRM_ERROR("pwr18 regulator not found\n");
+ return PTR_ERR(pdata->pwr18);
+ }
+
+ pdata->ovdd = devm_regulator_get(dev, "ovdd");
+ if (IS_ERR(pdata->ovdd)) {
+ DRM_ERROR("ovdd regulator not found\n");
+ return PTR_ERR(pdata->ovdd);
+ }
+
+ /* GPIO for HPD */
+ pdata->gpiod_hpd = devm_gpiod_get(dev, "hpd", GPIOD_IN);
+ if (IS_ERR(pdata->gpiod_hpd))
+ return PTR_ERR(pdata->gpiod_hpd);
+
+ /* GPIO for chip reset */
+ pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+
+ return PTR_ERR_OR_ZERO(pdata->gpiod_reset);
+}
+
+static int it6505_open(struct inode *inode,
+ struct file *file)
+{
+ struct it6505 *ctx = container_of(inode->i_cdev, struct it6505, cdev);
+
+ DRM_DEBUG_DRIVER("[%s]: successful", __func__);
+ if (!ctx)
+ DRM_DEBUG_DRIVER("[%s]:get it6505 struct fail!", __func__);
+ file->private_data = ctx;
+ return 0;
+}
+
+static int it6505_release(struct inode *inode,
+ struct file *file)
+{
+ struct it6505 *ctx = file->private_data;
+
+ DRM_DEBUG_DRIVER("[%s]: successful", __func__);
+ put_device(&ctx->class_dev);
+ return 0;
+}
+
+static ssize_t it6505_read(struct file *file,
+ char *buf, size_t count, loff_t *ptr)
+{
+ DRM_DEBUG_DRIVER("[%s]: successful", __func__);
+
+ DRM_DEBUG_DRIVER("it6505_drv_hold:%d",
+ ((struct it6505 *)(file->private_data))->it6505_drv_hold);
+ return count;
+}
+
+static ssize_t it6505_write(struct file *file,
+ const char *buff, size_t count, loff_t *ptr)
+{
+ unsigned int num;
+
+ DRM_DEBUG_DRIVER("[%s]:count=%d",__func__,count);
+ kstrtoint(buff, 10, &num);
+ ((struct it6505 *)(file->private_data))->it6505_drv_hold = num;
+ DRM_DEBUG_DRIVER("num:%d it6505_drv_hold:%d", num,
+ ((struct it6505 *)(file->private_data))->it6505_drv_hold);
+ DRM_DEBUG_DRIVER("[%s]: successful", __func__);
+ DRM_DEBUG_DRIVER("set it6505_drv_hold:%d",
+ ((struct it6505 *)(file->private_data))->it6505_drv_hold);
+ return count;
+}
+
+static struct class it6505_class_file = {
+ .owner = THIS_MODULE,
+ .name = IT6505_CLASS_NAME,
+};
+
+static struct file_operations it6505_fops = {
+ .owner = THIS_MODULE,
+ .read = it6505_read,
+ .write = it6505_write,
+ .open = it6505_open,
+ .release = it6505_release
+};
+
+static void it6505_release_device(struct device *dev)
+{
+ struct it6505 *ctx = container_of(dev, struct it6505, class_dev);
+
+ kfree(ctx);
+}
+
+static int it6505_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct it6505 *ctx;
+ struct it6505_platform_data *pdata;
+ int err = 0;
+
+ ctx = devm_kzalloc(&client->dev, sizeof(*ctx), GFP_KERNEL);
+ DRM_DEBUG_DRIVER("%s function~start!!\n", __func__);
+ if (!ctx)
+ return -ENOMEM;
+
+ mutex_init(&ctx->lock);
+
+ pdata = &ctx->pdata;
+
+ ctx->bridge.of_node = client->dev.of_node;
+ ctx->client = client;
+ i2c_set_clientdata(client, ctx);
+
+ err = it6505_init_pdata(ctx);
+ if (err) {
+ DRM_ERROR("Failed to initialize pdata: %d\n", err);
+ goto exit;
+ }
+
+ ctx->regmap = devm_regmap_init_i2c(client,
+ &it6505_bridge_regmap_config);
+ if (IS_ERR(ctx->regmap)) {
+ DRM_ERROR("regmap i2c init failed\n");
+ return PTR_ERR(ctx->regmap);
+ }
+
+ pdata->hpd_irq = gpiod_to_irq(pdata->gpiod_hpd);
+ DRM_DEBUG_DRIVER("get HPD IRQ: %d\n", pdata->hpd_irq);
+ if (pdata->hpd_irq < 0) {
+ DRM_ERROR("Failed to get HPD IRQ: %d\n", pdata->hpd_irq);
+ return -ENODEV;
+ }
+
+ pdata->intp_irq = client->irq;
+ DRM_DEBUG_DRIVER("get IT6505: %d\n", pdata->intp_irq);
+ if (!pdata->intp_irq) {
+ DRM_ERROR("Failed to get CABLE_DET and INTP IRQ\n");
+ return -ENODEV;
+ }
+
+ err = devm_request_threaded_irq(&client->dev, pdata->hpd_irq, NULL,
+ it6505_hpd_threaded_handler,
+ IRQF_TRIGGER_RISING
+ | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "it6505-hpd", ctx);
+ if (err) {
+ DRM_ERROR("Failed to request CABLE_DET threaded IRQ: %d\n",
+ err);
+ goto exit;
+ }
+
+ err = devm_request_threaded_irq(&client->dev, pdata->intp_irq, NULL,
+ it6505_intp_threaded_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "it6505-intp", ctx);
+ if (err) {
+ DRM_ERROR("Failed to request INTP threaded IRQ: %d\n", err);
+ goto exit;
+ }
+
+ ctx->powered = 0;
+ ctx->hpd_status = 1;
+ DRM_DEBUG_DRIVER("Set it6505->hpd_status=0x%02x\n",
+ ctx->hpd_status);
+ ctx->it6505_drv_hold = 0;
+#ifdef TEST_MODE
+ err = it6505_poweron(ctx);
+ if (err) {
+ DRM_DEBUG_DRIVER("power on fail!");
+ goto exit;
+ }
+ DRM_DEBUG_DRIVER("power on success!");
+ ctx->it6505_drv_hold = 1;
+#endif
+
+ ctx->bridge.funcs = &it6505_bridge_funcs;
+
+ drm_bridge_add(&ctx->bridge);
+ device_initialize(&ctx->class_dev);
+ ctx->class_dev.parent = &client->dev;
+ ctx->class_dev.release = it6505_release_device;
+ cdev_init(&ctx->cdev, &it6505_fops);
+ err = dev_set_name(&ctx->class_dev, "%s", IT6505_DEVICE_NAME);
+ DRM_DEBUG_DRIVER("[%s] dev_set_name:%s",
+ __func__, err ? "failed" : "success");
+ if (err) {
+ DRM_DEBUG_DRIVER("dev_set_name failed => %d", err);
+ goto failed;
+ }
+ /*
+ * Add the class device
+ * Link to the character device for creating the /dev entry
+ * in devtmpfs.
+ */
+ ctx->class_dev.devt = MKDEV(it6505_major_num, 0);
+ ctx->class_dev.class = &it6505_class_file;
+
+ /* We can now add the sysfs class, we know which parameter to show */
+ err = cdev_device_add(&ctx->cdev, &ctx->class_dev);
+ if (err) {
+ DRM_DEBUG_DRIVER("cdev_device_add failed => %d",
+ err);
+ goto failed;
+ }
+ DRM_DEBUG_DRIVER("[%s] probe~end~Suss\n", __func__);
+ return 0;
+
+exit:
+ return err;
+failed:
+ put_device(&ctx->class_dev);
+ return err;
+}
+
+static int it6505_remove(struct i2c_client *client)
+{
+ struct it6505 *ctx = i2c_get_clientdata(client);
+
+ DRM_DEBUG_DRIVER("start %s\n", __func__);
+ drm_bridge_remove(&ctx->bridge);
+ kfree(ctx->edid);
+ ctx->edid = NULL;
+ DRM_DEBUG_DRIVER("end %s\n", __func__);
+ return 0;
+}
+
+static int __init it6505_init()
+{
+ int err;
+ dev_t dev = 0;
+
+ DRM_DEBUG_DRIVER("start %s", __func__);
+ /* Register the device class */
+ err = class_register(&it6505_class_file);
+ err = alloc_chrdev_region(&dev, 0, IT6505_MAX_DEV,
+ IT6505_DEVICE_NAME);
+ it6505_major_num = MAJOR(dev);
+ if (err < 0) {
+ DRM_DEBUG_DRIVER("alloc_chrdev_region() fail!");
+ goto failed_chrdevreg;
+ }
+
+ DRM_DEBUG_DRIVER("end %s", __func__);
+ return 0;
+
+failed_chrdevreg:
+ class_unregister(&it6505_class_file);
+ return err;
+}
+
+static void __exit it6505_exit()
+{
+ DRM_DEBUG_DRIVER("start %s", __func__);
+ unregister_chrdev(it6505_major_num, IT6505_DEVICE_NAME);
+ class_unregister(&it6505_class_file);
+ DRM_DEBUG_DRIVER("end %s", __func__);
+}
+
+static const struct i2c_device_id it6505_id[] = {
+ { "it6505", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, it6505_id);
+
+static const struct of_device_id it6505_of_match[] = {
+ { .compatible = "ite,it6505"},
+ { }
+};
+
+struct i2c_driver it6505_i2c_driver = {
+ .driver = {
+ .name = "it6505_dptx",
+ .owner = THIS_MODULE,
+ .of_match_table = it6505_of_match,
+ },
+ .probe = it6505_i2c_probe,
+ .remove = it6505_remove,
+ .id_table = it6505_id,
+};
+
+module_i2c_driver(it6505_i2c_driver);
+module_init(it6505_init);
+module_exit(it6505_exit);
+
+MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>");
+MODULE_DESCRIPTION("IT6505 DisplayPort Transmitter driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index c33f95e08e1b..d54ebe8f2652 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -101,13 +101,23 @@ EXPORT_SYMBOL(drm_panel_remove);
*/
int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
{
+ int ret = 0;
+
if (panel->connector)
return -EBUSY;
panel->connector = connector;
panel->drm = connector->dev;
- return 0;
+ if (panel->funcs->attach) {
+ ret = panel->funcs->attach(panel);
+ if (ret < 0) {
+ panel->connector = NULL;
+ panel->drm = NULL;
+ }
+ }
+
+ return ret;
}
EXPORT_SYMBOL(drm_panel_attach);
@@ -125,6 +135,9 @@ EXPORT_SYMBOL(drm_panel_attach);
*/
int drm_panel_detach(struct drm_panel *panel)
{
+ if (panel->funcs->detach)
+ panel->funcs->detach(panel);
+
panel->connector = NULL;
panel->drm = NULL;
@@ -169,6 +182,29 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np)
return ERR_PTR(-EPROBE_DEFER);
}
EXPORT_SYMBOL(of_drm_find_panel);
+
+int of_drm_get_panel_orientation(const struct device_node *np, int *orientation)
+{
+ int rotation;
+
+ if (of_property_read_u32(np, "rotation", &rotation)) {
+ *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
+ return 0;
+ }
+
+ if (rotation == 0)
+ *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
+ else if (rotation == 90)
+ *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
+ else if (rotation == 180)
+ *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
+ else if (rotation == 270)
+ *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
+ else
+ return -EINVAL;
+
+ return 0;
+}
#endif
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index ebadcfed3a0a..b33fe170732b 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -32,6 +32,8 @@
#define DISP_REG_OVL_ROI_BGCLR 0x0028
#define DISP_REG_OVL_SRC_CON 0x002c
#define DISP_REG_OVL_CON(n) (0x0030 + 0x20 * (n))
+#define DISP_REG_OVL_V_FLIP_EN BIT(9)
+#define DISP_REG_OVL_H_FLIP_EN BIT(10)
#define DISP_REG_OVL_SRC_SIZE(n) (0x0038 + 0x20 * (n))
#define DISP_REG_OVL_OFFSET(n) (0x003c + 0x20 * (n))
#define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n))
@@ -228,14 +230,26 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
unsigned int fmt = pending->format;
unsigned int offset = (pending->y << 16) | pending->x;
unsigned int src_size = (pending->height << 16) | pending->width;
+ unsigned int bpp = drm_format_plane_cpp(fmt, 0);
unsigned int con;
+ DRM_DEBUG_DRIVER(
+ "layer %d enable %d fmt 0x%x (%X %X %X %X) pitch %X addr 0x%X bpp %d\n",
+ idx, pending->enable, fmt,
+ pending->x, pending->y, pending->width, pending->height, pitch,
+ pending->addr, bpp);
+
if (!pending->enable)
mtk_ovl_layer_off(comp, idx);
con = ovl_fmt_convert(ovl, fmt);
if (idx != 0)
con |= OVL_CON_AEN | OVL_CON_ALPHA;
+ if (state->base.rotation & DRM_MODE_ROTATE_180) {
+ con |= (DISP_REG_OVL_V_FLIP_EN | DISP_REG_OVL_H_FLIP_EN);
+ addr += pitch * (pending->height - 1) +
+ pending->width * bpp - 1;
+ }
writel_relaxed(con, comp->regs + DISP_REG_OVL_CON(idx));
writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index b748d63cd3f1..e03815fa9e64 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -360,11 +360,13 @@ static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
}
-static void mtk_dpi_enable_dual_edge(struct mtk_dpi *dpi)
+static void mtk_dpi_config_dual_edge(struct mtk_dpi *dpi)
{
- mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE,
- DDR_EN | DDR_4PHASE);
- mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, EDGE_SEL, EDGE_SEL);
+ if (dpi->conf->dual_edge) {
+ mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE,
+ DDR_EN | DDR_4PHASE);
+ mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, EDGE_SEL, EDGE_SEL);
+ }
}
static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
@@ -530,8 +532,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
mtk_dpi_config_color_format(dpi, dpi->color_format);
mtk_dpi_config_2n_h_fre(dpi);
mtk_dpi_config_disable_edge(dpi);
- if (dpi->conf->dual_edge)
- mtk_dpi_enable_dual_edge(dpi);
+ mtk_dpi_config_dual_edge(dpi);
mtk_dpi_sw_reset(dpi, false);
return 0;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 60e101ca9d03..7249e82bff45 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -455,14 +455,41 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
}
}
+static struct drm_connector *mtk_drm_get_connector(struct drm_crtc *crtc)
+{
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+ struct drm_connector_list_iter conn_iter;
+
+ drm_for_each_encoder(encoder, crtc->dev) {
+ if (encoder->crtc != crtc)
+ continue;
+
+ drm_connector_list_iter_begin(crtc->dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ if (connector->encoder == encoder)
+ return connector;
+ }
+ }
+
+ return NULL;
+}
+
static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_drm_private *priv = crtc->dev->dev_private;
+ struct drm_connector *connector;
unsigned int pending_planes = 0;
+ unsigned int rotation = DRM_MODE_ROTATE_0;
int i;
+ connector = mtk_drm_get_connector(crtc);
+ if (connector && connector->display_info.panel_orientation ==
+ DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP)
+ rotation = DRM_MODE_ROTATE_180;
+
if (mtk_crtc->event)
mtk_crtc->pending_needs_vblank = true;
for (i = 0; i < mtk_crtc->layer_nr; i++) {
@@ -473,6 +500,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
if (plane_state->pending.dirty) {
plane_state->pending.config = true;
plane_state->pending.dirty = false;
+ plane_state->base.rotation = rotation;
pending_planes |= BIT(i);
}
}
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 776a460a891e..3ac2d8769bf4 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -877,10 +877,25 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
DRM_ERROR("Failed to attach panel to drm\n");
goto err_connector_cleanup;
}
+
+ /*
+ * We don't need to put in accurate pixel heigh/width since we
+ * don't care about any of the panel quirks which are just x86
+ * BIOS hacks. We only care about the device tree settings which
+ * should be filled in for the connector in drm_panel_attach.
+ */
+ ret = drm_connector_init_panel_orientation_property(&dsi->conn,
+ 0, 0);
+ if (ret) {
+ DRM_ERROR("Failed to init panel orientation\n");
+ goto err_panel_detach;
+ }
}
return 0;
+err_panel_detach:
+ drm_panel_detach(dsi->panel);
err_connector_cleanup:
drm_connector_cleanup(&dsi->conn);
return ret;
@@ -948,6 +963,7 @@ static void mtk_dsi_ddp_stop(struct mtk_ddp_comp *comp)
{
struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
+ mtk_dsi_stop(dsi);
mtk_dsi_poweroff(dsi);
}
@@ -1301,6 +1317,8 @@ static int mtk_dsi_remove(struct platform_device *pdev)
struct mtk_dsi *dsi = platform_get_drvdata(pdev);
mtk_output_dsi_disable(dsi);
+ mtk_dsi_stop(dsi);
+ mtk_dsi_poweroff(dsi);
component_del(&pdev->dev, &mtk_dsi_component_ops);
return 0;
diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
index ff5a89e38fd7..b854455c9d88 100644
--- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c
+++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
@@ -61,6 +61,7 @@ struct panel_info {
struct gpio_desc *enable_gpio;
struct gpio_desc *pp33_gpio;
struct gpio_desc *pp18_gpio;
+ int orientation;
bool prepared;
bool enabled;
@@ -146,6 +147,18 @@ static int boe_panel_unprepare(struct drm_panel *panel)
return err;
}
+static int boe_panel_attach(struct drm_panel *panel)
+{
+ struct panel_info *pinfo = to_panel_info(panel);
+
+ panel->connector->display_info.width_mm = pinfo->desc->width_mm;
+ panel->connector->display_info.height_mm = pinfo->desc->height_mm;
+ panel->connector->display_info.bpc = pinfo->desc->bpc;
+ panel->connector->display_info.panel_orientation = pinfo->orientation;
+
+ return 0;
+}
+
static int boe_panel_prepare(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
@@ -226,16 +239,13 @@ static int boe_panel_get_modes(struct drm_panel *panel)
drm_mode_probed_add(panel->connector, mode);
- panel->connector->display_info.width_mm = pinfo->desc->width_mm;
- panel->connector->display_info.height_mm = pinfo->desc->height_mm;
- panel->connector->display_info.bpc = pinfo->desc->bpc;
-
return 1;
}
static const struct drm_panel_funcs panel_funcs = {
.disable = boe_panel_disable,
.unprepare = boe_panel_unprepare,
+ .attach = boe_panel_attach,
.prepare = boe_panel_prepare,
.enable = boe_panel_enable,
.get_modes = boe_panel_get_modes,
@@ -587,6 +597,285 @@ static const struct panel_desc boe_himax8279d8p_panel_desc = {
.off_cmds = default_off_cmds,
};
+/* 8 inch Positive scanning*/
+static const struct panel_cmd boe_tv080wumng0_on_cmds[] = {
+ _INIT_CMD(0x22, 0x10),
+ _INIT_CMD(0x00, 0xB0, 0x05),
+ _INIT_CMD(0x00, 0xB3, 0x52),
+ _INIT_CMD(0x00, 0xB0, 0x01),
+ _INIT_CMD(0x00, 0xC8, 0x00),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCC, 0x26),
+ _INIT_CMD(0x00, 0xCD, 0x26),
+ _INIT_CMD(0x00, 0xDC, 0x00),
+ _INIT_CMD(0x00, 0xDD, 0x00),
+ _INIT_CMD(0x00, 0xE0, 0x26),
+ _INIT_CMD(0x00, 0xE1, 0x26),
+ _INIT_CMD(0x00, 0xB0, 0x03),
+ _INIT_CMD(0x00, 0xC3, 0x2A),
+ _INIT_CMD(0x00, 0xE7, 0x2A),
+ _INIT_CMD(0x00, 0xC5, 0x2A),
+ _INIT_CMD(0x00, 0xDE, 0x2A),
+ _INIT_CMD(0x00, 0xB0, 0x00),
+ _INIT_CMD(0x00, 0xB6, 0x03),
+ _INIT_CMD(0x00, 0xBA, 0x8B),
+ _INIT_CMD(0x00, 0xBF, 0x15),
+ _INIT_CMD(0x00, 0xC0, 0x18),
+ _INIT_CMD(0x00, 0xC2, 0x14),
+ _INIT_CMD(0x00, 0xC3, 0x02),
+ _INIT_CMD(0x00, 0xC4, 0x14),
+ _INIT_CMD(0x00, 0xC5, 0x02),
+ _INIT_CMD(0x00, 0xB0, 0x06),
+ _INIT_CMD(0x00, 0xC0, 0xA5),
+ _INIT_CMD(0x00, 0xD5, 0x20),
+ _INIT_CMD(0x00, 0xC0, 0x00),
+ _INIT_CMD(0x00, 0xB0, 0x02),
+ _INIT_CMD(0x00, 0xC0, 0x00),
+ _INIT_CMD(0x00, 0xC1, 0x02),
+ _INIT_CMD(0x00, 0xC2, 0x06),
+ _INIT_CMD(0x00, 0xC3, 0x16),
+ _INIT_CMD(0x00, 0xC4, 0x0E),
+ _INIT_CMD(0x00, 0xC5, 0x18),
+ _INIT_CMD(0x00, 0xC6, 0x26),
+ _INIT_CMD(0x00, 0xC7, 0x32),
+ _INIT_CMD(0x00, 0xC8, 0x3F),
+ _INIT_CMD(0x00, 0xC9, 0x3F),
+ _INIT_CMD(0x00, 0xCA, 0x3F),
+ _INIT_CMD(0x00, 0xCB, 0x3F),
+ _INIT_CMD(0x00, 0xCC, 0x3D),
+ _INIT_CMD(0x00, 0xCD, 0x2F),
+ _INIT_CMD(0x00, 0xCE, 0x2F),
+ _INIT_CMD(0x00, 0xCF, 0x2F),
+ _INIT_CMD(0x00, 0xD0, 0x07),
+ _INIT_CMD(0x00, 0xD2, 0x00),
+ _INIT_CMD(0x00, 0xD3, 0x02),
+ _INIT_CMD(0x00, 0xD4, 0x06),
+ _INIT_CMD(0x00, 0xD5, 0x12),
+ _INIT_CMD(0x00, 0xD6, 0x0A),
+ _INIT_CMD(0x00, 0xD7, 0x14),
+ _INIT_CMD(0x00, 0xD8, 0x22),
+ _INIT_CMD(0x00, 0xD9, 0x2E),
+ _INIT_CMD(0x00, 0xDA, 0x3D),
+ _INIT_CMD(0x00, 0xDB, 0x3F),
+ _INIT_CMD(0x00, 0xDC, 0x3F),
+ _INIT_CMD(0x00, 0xDD, 0x3F),
+ _INIT_CMD(0x00, 0xDE, 0x3D),
+ _INIT_CMD(0x00, 0xDF, 0x2F),
+ _INIT_CMD(0x00, 0xE0, 0x2F),
+ _INIT_CMD(0x00, 0xE1, 0x2F),
+ _INIT_CMD(0x00, 0xE2, 0x07),
+ _INIT_CMD(0x00, 0xB0, 0x07),
+ _INIT_CMD(0x00, 0xB1, 0x18),
+ _INIT_CMD(0x00, 0xB2, 0x19),
+ _INIT_CMD(0x00, 0xB3, 0x2E),
+ _INIT_CMD(0x00, 0xB4, 0x52),
+ _INIT_CMD(0x00, 0xB5, 0x72),
+ _INIT_CMD(0x00, 0xB6, 0x8C),
+ _INIT_CMD(0x00, 0xB7, 0xBD),
+ _INIT_CMD(0x00, 0xB8, 0xEB),
+ _INIT_CMD(0x00, 0xB9, 0x47),
+ _INIT_CMD(0x00, 0xBA, 0x96),
+ _INIT_CMD(0x00, 0xBB, 0x1E),
+ _INIT_CMD(0x00, 0xBC, 0x90),
+ _INIT_CMD(0x00, 0xBD, 0x93),
+ _INIT_CMD(0x00, 0xBE, 0xFA),
+ _INIT_CMD(0x00, 0xBF, 0x56),
+ _INIT_CMD(0x00, 0xC0, 0x8C),
+ _INIT_CMD(0x00, 0xC1, 0xB7),
+ _INIT_CMD(0x00, 0xC2, 0xCC),
+ _INIT_CMD(0x00, 0xC3, 0xDF),
+ _INIT_CMD(0x00, 0xC4, 0xE8),
+ _INIT_CMD(0x00, 0xC5, 0xF0),
+ _INIT_CMD(0x00, 0xC6, 0xF8),
+ _INIT_CMD(0x00, 0xC7, 0xFA),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x5A),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x08),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x15),
+ _INIT_CMD(0x00, 0xB3, 0x2D),
+ _INIT_CMD(0x00, 0xB4, 0x51),
+ _INIT_CMD(0x00, 0xB5, 0x72),
+ _INIT_CMD(0x00, 0xB6, 0x8D),
+ _INIT_CMD(0x00, 0xB7, 0xBE),
+ _INIT_CMD(0x00, 0xB8, 0xED),
+ _INIT_CMD(0x00, 0xB9, 0x4A),
+ _INIT_CMD(0x00, 0xBA, 0x9A),
+ _INIT_CMD(0x00, 0xBB, 0x23),
+ _INIT_CMD(0x00, 0xBC, 0x95),
+ _INIT_CMD(0x00, 0xBD, 0x98),
+ _INIT_CMD(0x00, 0xBE, 0xFF),
+ _INIT_CMD(0x00, 0xBF, 0x59),
+ _INIT_CMD(0x00, 0xC0, 0x8E),
+ _INIT_CMD(0x00, 0xC1, 0xB9),
+ _INIT_CMD(0x00, 0xC2, 0xCD),
+ _INIT_CMD(0x00, 0xC3, 0xDF),
+ _INIT_CMD(0x00, 0xC4, 0xE8),
+ _INIT_CMD(0x00, 0xC5, 0xF0),
+ _INIT_CMD(0x00, 0xC6, 0xF8),
+ _INIT_CMD(0x00, 0xC7, 0xFA),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x5A),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x09),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x2C),
+ _INIT_CMD(0x00, 0xB3, 0x36),
+ _INIT_CMD(0x00, 0xB4, 0x53),
+ _INIT_CMD(0x00, 0xB5, 0x73),
+ _INIT_CMD(0x00, 0xB6, 0x8E),
+ _INIT_CMD(0x00, 0xB7, 0xC0),
+ _INIT_CMD(0x00, 0xB8, 0xEF),
+ _INIT_CMD(0x00, 0xB9, 0x4C),
+ _INIT_CMD(0x00, 0xBA, 0x9D),
+ _INIT_CMD(0x00, 0xBB, 0x25),
+ _INIT_CMD(0x00, 0xBC, 0x96),
+ _INIT_CMD(0x00, 0xBD, 0x9A),
+ _INIT_CMD(0x00, 0xBE, 0x01),
+ _INIT_CMD(0x00, 0xBF, 0x59),
+ _INIT_CMD(0x00, 0xC0, 0x8E),
+ _INIT_CMD(0x00, 0xC1, 0xB9),
+ _INIT_CMD(0x00, 0xC2, 0xCD),
+ _INIT_CMD(0x00, 0xC3, 0xDF),
+ _INIT_CMD(0x00, 0xC4, 0xE8),
+ _INIT_CMD(0x00, 0xC5, 0xF0),
+ _INIT_CMD(0x00, 0xC6, 0xF8),
+ _INIT_CMD(0x00, 0xC7, 0xFA),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x5A),
+ _INIT_CMD(0x00, 0xCC, 0xBF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x0A),
+ _INIT_CMD(0x00, 0xB1, 0x18),
+ _INIT_CMD(0x00, 0xB2, 0x19),
+ _INIT_CMD(0x00, 0xB3, 0x2E),
+ _INIT_CMD(0x00, 0xB4, 0x52),
+ _INIT_CMD(0x00, 0xB5, 0x72),
+ _INIT_CMD(0x00, 0xB6, 0x8C),
+ _INIT_CMD(0x00, 0xB7, 0xBD),
+ _INIT_CMD(0x00, 0xB8, 0xEB),
+ _INIT_CMD(0x00, 0xB9, 0x47),
+ _INIT_CMD(0x00, 0xBA, 0x96),
+ _INIT_CMD(0x00, 0xBB, 0x1E),
+ _INIT_CMD(0x00, 0xBC, 0x90),
+ _INIT_CMD(0x00, 0xBD, 0x93),
+ _INIT_CMD(0x00, 0xBE, 0xFA),
+ _INIT_CMD(0x00, 0xBF, 0x56),
+ _INIT_CMD(0x00, 0xC0, 0x8C),
+ _INIT_CMD(0x00, 0xC1, 0xB7),
+ _INIT_CMD(0x00, 0xC2, 0xCC),
+ _INIT_CMD(0x00, 0xC3, 0xDF),
+ _INIT_CMD(0x00, 0xC4, 0xE8),
+ _INIT_CMD(0x00, 0xC5, 0xF0),
+ _INIT_CMD(0x00, 0xC6, 0xF8),
+ _INIT_CMD(0x00, 0xC7, 0xFA),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x5A),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x0B),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x15),
+ _INIT_CMD(0x00, 0xB3, 0x2D),
+ _INIT_CMD(0x00, 0xB4, 0x51),
+ _INIT_CMD(0x00, 0xB5, 0x72),
+ _INIT_CMD(0x00, 0xB6, 0x8D),
+ _INIT_CMD(0x00, 0xB7, 0xBE),
+ _INIT_CMD(0x00, 0xB8, 0xED),
+ _INIT_CMD(0x00, 0xB9, 0x4A),
+ _INIT_CMD(0x00, 0xBA, 0x9A),
+ _INIT_CMD(0x00, 0xBB, 0x23),
+ _INIT_CMD(0x00, 0xBC, 0x95),
+ _INIT_CMD(0x00, 0xBD, 0x98),
+ _INIT_CMD(0x00, 0xBE, 0xFF),
+ _INIT_CMD(0x00, 0xBF, 0x59),
+ _INIT_CMD(0x00, 0xC0, 0x8E),
+ _INIT_CMD(0x00, 0xC1, 0xB9),
+ _INIT_CMD(0x00, 0xC2, 0xCD),
+ _INIT_CMD(0x00, 0xC3, 0xDF),
+ _INIT_CMD(0x00, 0xC4, 0xE8),
+ _INIT_CMD(0x00, 0xC5, 0xF0),
+ _INIT_CMD(0x00, 0xC6, 0xF8),
+ _INIT_CMD(0x00, 0xC7, 0xFA),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x5A),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x0C),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x2C),
+ _INIT_CMD(0x00, 0xB3, 0x36),
+ _INIT_CMD(0x00, 0xB4, 0x53),
+ _INIT_CMD(0x00, 0xB5, 0x73),
+ _INIT_CMD(0x00, 0xB6, 0x8E),
+ _INIT_CMD(0x00, 0xB7, 0xC0),
+ _INIT_CMD(0x00, 0xB8, 0xEF),
+ _INIT_CMD(0x00, 0xB9, 0x4C),
+ _INIT_CMD(0x00, 0xBA, 0x9D),
+ _INIT_CMD(0x00, 0xBB, 0x25),
+ _INIT_CMD(0x00, 0xBC, 0x96),
+ _INIT_CMD(0x00, 0xBD, 0x9A),
+ _INIT_CMD(0x00, 0xBE, 0x01),
+ _INIT_CMD(0x00, 0xBF, 0x59),
+ _INIT_CMD(0x00, 0xC0, 0x8E),
+ _INIT_CMD(0x00, 0xC1, 0xB9),
+ _INIT_CMD(0x00, 0xC2, 0xCD),
+ _INIT_CMD(0x00, 0xC3, 0xDF),
+ _INIT_CMD(0x00, 0xC4, 0xE8),
+ _INIT_CMD(0x00, 0xC5, 0xF0),
+ _INIT_CMD(0x00, 0xC6, 0xF8),
+ _INIT_CMD(0x00, 0xC7, 0xFA),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x5A),
+ _INIT_CMD(0x00, 0xCC, 0xBF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x04),
+ _INIT_CMD(0x00, 0xB5, 0x02),
+ _INIT_CMD(0x00, 0xB6, 0x01),
+ _INIT_CMD(0x64, 0x11),
+ _INIT_CMD(0x32, 0x29),
+ {},
+};
+
+static const struct panel_desc boe_tv080wumng0_panel_desc = {
+ .display_mode = &default_display_mode,
+ .bpc = 8,
+ .width_mm = 107,
+ .height_mm = 172,
+ .delay_t1 = 5000,
+ .reset_delay_t2 = 14000,
+ .reset_delay_t3 = 1000,
+ .reset_delay_t4 = 1000,
+ .reset_delay_t5 = 5000,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 4,
+ .on_cmds = boe_tv080wumng0_on_cmds,
+ .off_cmds = default_off_cmds,
+};
+
/* 10 inch */
static const struct panel_cmd boe_himax8279d10p_on_cmds[] = {
_INIT_CMD(0x00, 0xB0, 0x05),
@@ -910,11 +1199,664 @@ static const struct panel_desc boe_himax8279d10p_panel_desc = {
.off_cmds = default_off_cmds,
};
+/* 10 inch Positive scanning*/
+static const struct panel_cmd boe_tv101wumng0_on_cmds[] = {
+ _INIT_CMD(0x00, 0xB0, 0x05),
+ _INIT_CMD(0x00, 0xB1, 0xE5),
+ _INIT_CMD(0x00, 0xB3, 0x52),
+ _INIT_CMD(0x00, 0xB0, 0x00),
+ _INIT_CMD(0x00, 0xB3, 0x88),
+ _INIT_CMD(0x00, 0xB0, 0x04),
+ _INIT_CMD(0x00, 0xB8, 0x00),
+ _INIT_CMD(0x00, 0xB0, 0x00),
+ _INIT_CMD(0x00, 0xB6, 0x03),
+ _INIT_CMD(0x00, 0xBA, 0x8B),
+ _INIT_CMD(0x00, 0xBF, 0x1A),
+ _INIT_CMD(0x00, 0xC0, 0x0F),
+ _INIT_CMD(0x00, 0xC2, 0x0C),
+ _INIT_CMD(0x00, 0xC3, 0x02),
+ _INIT_CMD(0x00, 0xC4, 0x0C),
+ _INIT_CMD(0x00, 0xC5, 0x02),
+ _INIT_CMD(0x00, 0xB0, 0x01),
+ _INIT_CMD(0x00, 0xE0, 0x26),
+ _INIT_CMD(0x00, 0xE1, 0x26),
+ _INIT_CMD(0x00, 0xDC, 0x00),
+ _INIT_CMD(0x00, 0xDD, 0x00),
+ _INIT_CMD(0x00, 0xCC, 0x26),
+ _INIT_CMD(0x00, 0xCD, 0x26),
+ _INIT_CMD(0x00, 0xC8, 0x00),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xD2, 0x03),
+ _INIT_CMD(0x00, 0xD3, 0x03),
+ _INIT_CMD(0x00, 0xE6, 0x04),
+ _INIT_CMD(0x00, 0xE7, 0x04),
+ _INIT_CMD(0x00, 0xC4, 0x09),
+ _INIT_CMD(0x00, 0xC5, 0x09),
+ _INIT_CMD(0x00, 0xD8, 0x0A),
+ _INIT_CMD(0x00, 0xD9, 0x0A),
+ _INIT_CMD(0x00, 0xC2, 0x0B),
+ _INIT_CMD(0x00, 0xC3, 0x0B),
+ _INIT_CMD(0x00, 0xD6, 0x0C),
+ _INIT_CMD(0x00, 0xD7, 0x0C),
+ _INIT_CMD(0x00, 0xC0, 0x05),
+ _INIT_CMD(0x00, 0xC1, 0x05),
+ _INIT_CMD(0x00, 0xD4, 0x06),
+ _INIT_CMD(0x00, 0xD5, 0x06),
+ _INIT_CMD(0x00, 0xCA, 0x07),
+ _INIT_CMD(0x00, 0xCB, 0x07),
+ _INIT_CMD(0x00, 0xDE, 0x08),
+ _INIT_CMD(0x00, 0xDF, 0x08),
+ _INIT_CMD(0x00, 0xB0, 0x02),
+ _INIT_CMD(0x00, 0xC0, 0x00),
+ _INIT_CMD(0x00, 0xC1, 0x07),
+ _INIT_CMD(0x00, 0xC2, 0x0D),
+ _INIT_CMD(0x00, 0xC3, 0x18),
+ _INIT_CMD(0x00, 0xC4, 0x27),
+ _INIT_CMD(0x00, 0xC5, 0x28),
+ _INIT_CMD(0x00, 0xC6, 0x30),
+ _INIT_CMD(0x00, 0xC7, 0x2E),
+ _INIT_CMD(0x00, 0xC8, 0x2F),
+ _INIT_CMD(0x00, 0xC9, 0x1A),
+ _INIT_CMD(0x00, 0xCA, 0x20),
+ _INIT_CMD(0x00, 0xCB, 0x29),
+ _INIT_CMD(0x00, 0xCC, 0x26),
+ _INIT_CMD(0x00, 0xCD, 0x32),
+ _INIT_CMD(0x00, 0xCE, 0x33),
+ _INIT_CMD(0x00, 0xCF, 0x31),
+ _INIT_CMD(0x00, 0xD0, 0x06),
+ _INIT_CMD(0x00, 0xD2, 0x00),
+ _INIT_CMD(0x00, 0xD3, 0x07),
+ _INIT_CMD(0x00, 0xD4, 0x12),
+ _INIT_CMD(0x00, 0xD5, 0x26),
+ _INIT_CMD(0x00, 0xD6, 0x3D),
+ _INIT_CMD(0x00, 0xD7, 0x3F),
+ _INIT_CMD(0x00, 0xD8, 0x3F),
+ _INIT_CMD(0x00, 0xD9, 0x3F),
+ _INIT_CMD(0x00, 0xDA, 0x3F),
+ _INIT_CMD(0x00, 0xDB, 0x3F),
+ _INIT_CMD(0x00, 0xDC, 0x3F),
+ _INIT_CMD(0x00, 0xDD, 0x3F),
+ _INIT_CMD(0x00, 0xDE, 0x3F),
+ _INIT_CMD(0x00, 0xDF, 0x3A),
+ _INIT_CMD(0x00, 0xE0, 0x37),
+ _INIT_CMD(0x00, 0xE1, 0x35),
+ _INIT_CMD(0x00, 0xE2, 0x07),
+ _INIT_CMD(0x00, 0xB0, 0x03),
+ _INIT_CMD(0x00, 0xC8, 0x0B),
+ _INIT_CMD(0x00, 0xC9, 0x07),
+ _INIT_CMD(0x00, 0xC3, 0x00),
+ _INIT_CMD(0x00, 0xE7, 0x00),
+ _INIT_CMD(0x00, 0xC5, 0x2A),
+ _INIT_CMD(0x00, 0xDE, 0x2A),
+ _INIT_CMD(0x00, 0xCA, 0x43),
+ _INIT_CMD(0x00, 0xC9, 0x07),
+ _INIT_CMD(0x00, 0xE4, 0xC0),
+ _INIT_CMD(0x00, 0xE5, 0x0D),
+ _INIT_CMD(0x00, 0xCB, 0x00),
+ _INIT_CMD(0x00, 0xB0, 0x06),
+ _INIT_CMD(0x00, 0xB8, 0xA5),
+ _INIT_CMD(0x00, 0xC0, 0xA5),
+ _INIT_CMD(0x00, 0xC7, 0x0F),
+ _INIT_CMD(0x00, 0xD5, 0x32),
+ _INIT_CMD(0x00, 0xB8, 0x00),
+ _INIT_CMD(0x00, 0xC0, 0x00),
+ _INIT_CMD(0x00, 0xBC, 0x00),
+ _INIT_CMD(0x00, 0xB0, 0x07),
+ _INIT_CMD(0x00, 0xB1, 0x00),
+ _INIT_CMD(0x00, 0xB2, 0x07),
+ _INIT_CMD(0x00, 0xB3, 0x18),
+ _INIT_CMD(0x00, 0xB4, 0x31),
+ _INIT_CMD(0x00, 0xB5, 0x47),
+ _INIT_CMD(0x00, 0xB6, 0x56),
+ _INIT_CMD(0x00, 0xB7, 0x70),
+ _INIT_CMD(0x00, 0xB8, 0x98),
+ _INIT_CMD(0x00, 0xB9, 0xDB),
+ _INIT_CMD(0x00, 0xBA, 0x2A),
+ _INIT_CMD(0x00, 0xBB, 0xAE),
+ _INIT_CMD(0x00, 0xBC, 0x39),
+ _INIT_CMD(0x00, 0xBD, 0x3D),
+ _INIT_CMD(0x00, 0xBE, 0xC6),
+ _INIT_CMD(0x00, 0xBF, 0x2A),
+ _INIT_CMD(0x00, 0xC0, 0x59),
+ _INIT_CMD(0x00, 0xC1, 0x91),
+ _INIT_CMD(0x00, 0xC2, 0xA1),
+ _INIT_CMD(0x00, 0xC3, 0xB1),
+ _INIT_CMD(0x00, 0xC4, 0xBA),
+ _INIT_CMD(0x00, 0xC5, 0xC5),
+ _INIT_CMD(0x00, 0xC6, 0xD4),
+ _INIT_CMD(0x00, 0xC7, 0xDC),
+ _INIT_CMD(0x00, 0xC8, 0xE0),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x16),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x08),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x07),
+ _INIT_CMD(0x00, 0xB3, 0x19),
+ _INIT_CMD(0x00, 0xB4, 0x32),
+ _INIT_CMD(0x00, 0xB5, 0x48),
+ _INIT_CMD(0x00, 0xB6, 0x58),
+ _INIT_CMD(0x00, 0xB7, 0x74),
+ _INIT_CMD(0x00, 0xB8, 0x9D),
+ _INIT_CMD(0x00, 0xB9, 0xE2),
+ _INIT_CMD(0x00, 0xBA, 0x34),
+ _INIT_CMD(0x00, 0xBB, 0xBB),
+ _INIT_CMD(0x00, 0xBC, 0x4A),
+ _INIT_CMD(0x00, 0xBD, 0x4F),
+ _INIT_CMD(0x00, 0xBE, 0xD5),
+ _INIT_CMD(0x00, 0xBF, 0x3C),
+ _INIT_CMD(0x00, 0xC0, 0x70),
+ _INIT_CMD(0x00, 0xC1, 0x9F),
+ _INIT_CMD(0x00, 0xC2, 0xAF),
+ _INIT_CMD(0x00, 0xC3, 0xC2),
+ _INIT_CMD(0x00, 0xC4, 0xD2),
+ _INIT_CMD(0x00, 0xC5, 0xE1),
+ _INIT_CMD(0x00, 0xC6, 0xF0),
+ _INIT_CMD(0x00, 0xC7, 0xF9),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x16),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x09),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x05),
+ _INIT_CMD(0x00, 0xB3, 0x18),
+ _INIT_CMD(0x00, 0xB4, 0x31),
+ _INIT_CMD(0x00, 0xB5, 0x47),
+ _INIT_CMD(0x00, 0xB6, 0x57),
+ _INIT_CMD(0x00, 0xB7, 0x72),
+ _INIT_CMD(0x00, 0xB8, 0x9B),
+ _INIT_CMD(0x00, 0xB9, 0xE0),
+ _INIT_CMD(0x00, 0xBA, 0x32),
+ _INIT_CMD(0x00, 0xBB, 0xB8),
+ _INIT_CMD(0x00, 0xBC, 0x46),
+ _INIT_CMD(0x00, 0xBD, 0x4A),
+ _INIT_CMD(0x00, 0xBE, 0xD0),
+ _INIT_CMD(0x00, 0xBF, 0x35),
+ _INIT_CMD(0x00, 0xC0, 0x65),
+ _INIT_CMD(0x00, 0xC1, 0x97),
+ _INIT_CMD(0x00, 0xC2, 0xA7),
+ _INIT_CMD(0x00, 0xC3, 0xB7),
+ _INIT_CMD(0x00, 0xC4, 0xC0),
+ _INIT_CMD(0x00, 0xC5, 0xCF),
+ _INIT_CMD(0x00, 0xC6, 0xDC),
+ _INIT_CMD(0x00, 0xC7, 0xE4),
+ _INIT_CMD(0x00, 0xC8, 0xE8),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x16),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x0A),
+ _INIT_CMD(0x00, 0xB1, 0x00),
+ _INIT_CMD(0x00, 0xB2, 0x07),
+ _INIT_CMD(0x00, 0xB3, 0x18),
+ _INIT_CMD(0x00, 0xB4, 0x31),
+ _INIT_CMD(0x00, 0xB5, 0x47),
+ _INIT_CMD(0x00, 0xB6, 0x56),
+ _INIT_CMD(0x00, 0xB7, 0x70),
+ _INIT_CMD(0x00, 0xB8, 0x98),
+ _INIT_CMD(0x00, 0xB9, 0xDB),
+ _INIT_CMD(0x00, 0xBA, 0x2A),
+ _INIT_CMD(0x00, 0xBB, 0xAE),
+ _INIT_CMD(0x00, 0xBC, 0x39),
+ _INIT_CMD(0x00, 0xBD, 0x3D),
+ _INIT_CMD(0x00, 0xBE, 0xC6),
+ _INIT_CMD(0x00, 0xBF, 0x2A),
+ _INIT_CMD(0x00, 0xC0, 0x59),
+ _INIT_CMD(0x00, 0xC1, 0x91),
+ _INIT_CMD(0x00, 0xC2, 0xA1),
+ _INIT_CMD(0x00, 0xC3, 0xB1),
+ _INIT_CMD(0x00, 0xC4, 0xBA),
+ _INIT_CMD(0x00, 0xC5, 0xC5),
+ _INIT_CMD(0x00, 0xC6, 0xD4),
+ _INIT_CMD(0x00, 0xC7, 0xDC),
+ _INIT_CMD(0x00, 0xC8, 0xE0),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x16),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x0B),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x07),
+ _INIT_CMD(0x00, 0xB3, 0x19),
+ _INIT_CMD(0x00, 0xB4, 0x32),
+ _INIT_CMD(0x00, 0xB5, 0x48),
+ _INIT_CMD(0x00, 0xB6, 0x58),
+ _INIT_CMD(0x00, 0xB7, 0x74),
+ _INIT_CMD(0x00, 0xB8, 0x9D),
+ _INIT_CMD(0x00, 0xB9, 0xE2),
+ _INIT_CMD(0x00, 0xBA, 0x34),
+ _INIT_CMD(0x00, 0xBB, 0xBB),
+ _INIT_CMD(0x00, 0xBC, 0x4A),
+ _INIT_CMD(0x00, 0xBD, 0x4F),
+ _INIT_CMD(0x00, 0xBE, 0xD5),
+ _INIT_CMD(0x00, 0xBF, 0x3C),
+ _INIT_CMD(0x00, 0xC0, 0x70),
+ _INIT_CMD(0x00, 0xC1, 0x9F),
+ _INIT_CMD(0x00, 0xC2, 0xAF),
+ _INIT_CMD(0x00, 0xC3, 0xC2),
+ _INIT_CMD(0x00, 0xC4, 0xD2),
+ _INIT_CMD(0x00, 0xC5, 0xE1),
+ _INIT_CMD(0x00, 0xC6, 0xF0),
+ _INIT_CMD(0x00, 0xC7, 0xF9),
+ _INIT_CMD(0x00, 0xC8, 0xFC),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x16),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x0C),
+ _INIT_CMD(0x00, 0xB1, 0x04),
+ _INIT_CMD(0x00, 0xB2, 0x05),
+ _INIT_CMD(0x00, 0xB3, 0x18),
+ _INIT_CMD(0x00, 0xB4, 0x31),
+ _INIT_CMD(0x00, 0xB5, 0x47),
+ _INIT_CMD(0x00, 0xB6, 0x57),
+ _INIT_CMD(0x00, 0xB7, 0x72),
+ _INIT_CMD(0x00, 0xB8, 0x9B),
+ _INIT_CMD(0x00, 0xB9, 0xE0),
+ _INIT_CMD(0x00, 0xBA, 0x32),
+ _INIT_CMD(0x00, 0xBB, 0xB8),
+ _INIT_CMD(0x00, 0xBC, 0x46),
+ _INIT_CMD(0x00, 0xBD, 0x4A),
+ _INIT_CMD(0x00, 0xBE, 0xD0),
+ _INIT_CMD(0x00, 0xBF, 0x35),
+ _INIT_CMD(0x00, 0xC0, 0x65),
+ _INIT_CMD(0x00, 0xC1, 0x97),
+ _INIT_CMD(0x00, 0xC2, 0xA7),
+ _INIT_CMD(0x00, 0xC3, 0xB7),
+ _INIT_CMD(0x00, 0xC4, 0xC0),
+ _INIT_CMD(0x00, 0xC5, 0xCF),
+ _INIT_CMD(0x00, 0xC6, 0xDC),
+ _INIT_CMD(0x00, 0xC7, 0xE4),
+ _INIT_CMD(0x00, 0xC8, 0xE8),
+ _INIT_CMD(0x00, 0xC9, 0x00),
+ _INIT_CMD(0x00, 0xCA, 0x00),
+ _INIT_CMD(0x00, 0xCB, 0x16),
+ _INIT_CMD(0x00, 0xCC, 0xAF),
+ _INIT_CMD(0x00, 0xCD, 0xFF),
+ _INIT_CMD(0x00, 0xCE, 0xFF),
+ _INIT_CMD(0x00, 0xB0, 0x00),
+ _INIT_CMD(0x00, 0xB3, 0x08),
+ _INIT_CMD(0x00, 0xB0, 0x04),
+ _INIT_CMD(0x64, 0xB8, 0x68),
+ {},
+};
+
+static const struct panel_desc boe_tv101wumng0_panel_desc = {
+ .display_mode = &default_display_mode,
+ .bpc = 8,
+ .width_mm = 135,
+ .height_mm = 216,
+ .delay_t1 = 5000,
+ .reset_delay_t2 = 14000,
+ .reset_delay_t3 = 1000,
+ .reset_delay_t4 = 1000,
+ .reset_delay_t5 = 5000,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 4,
+ .on_cmds = boe_tv101wumng0_on_cmds,
+ .off_cmds = default_off_cmds,
+};
+
+/* auo,nt51021d8p */
+static const struct drm_display_mode auo_nt51021d8p_display_mode = {
+ .clock = 159420,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 80,
+ .hsync_end = 1200 + 80 + 60,
+ .htotal = 1200 + 80 + 60 + 1,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 35,
+ .vsync_end = 1920 + 35 + 25,
+ .vtotal = 1920 + 35 + 25 + 1,
+ .vrefresh = 60,
+};
+
+static const struct panel_cmd auo_nt51021d8p_on_cmds[] = {
+ _INIT_CMD(0x78, 0x11),
+ _INIT_CMD(0x14, 0x29),
+
+ {},
+};
+
+static const struct panel_cmd auo_nt51021d8p_off_cmds[] = {
+ _INIT_CMD(0x00, 0x28),
+ _INIT_CMD(0x01, 0x10),
+
+ {},
+};
+
+static const struct panel_desc auo_nt51021d8p_panel_desc = {
+ .display_mode = &auo_nt51021d8p_display_mode,
+ .bpc = 8,
+ .width_mm = 107,
+ .height_mm = 172,
+ .delay_t1 = 5000,
+ .reset_delay_t2 = 14000,
+ .reset_delay_t3 = 1000,
+ .reset_delay_t4 = 1000,
+ .reset_delay_t5 = 5000,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 4,
+ .on_cmds = auo_nt51021d8p_on_cmds,
+ .off_cmds = auo_nt51021d8p_off_cmds,
+};
+
+/* inx,ota7290d10p */
+static const struct panel_cmd inx_ota7290d10p_on_cmds[] = {
+ _INIT_CMD(0x00, 0xB0, 0x5A),
+ _INIT_CMD(0x00, 0xB1, 0x00),
+ _INIT_CMD(0x00, 0x89, 0x01),
+ _INIT_CMD(0x00, 0x91, 0x17),
+ _INIT_CMD(0x00, 0xB1, 0x03),
+ _INIT_CMD(0x00, 0x2C, 0x28),
+ _INIT_CMD(0x00, 0x00, 0xF1),
+ _INIT_CMD(0x00, 0x01, 0x78),
+ _INIT_CMD(0x00, 0x02, 0x3C),
+ _INIT_CMD(0x00, 0x03, 0x1E),
+ _INIT_CMD(0x00, 0x04, 0x8F),
+ _INIT_CMD(0x00, 0x05, 0x01),
+ _INIT_CMD(0x00, 0x06, 0x00),
+ _INIT_CMD(0x00, 0x07, 0x00),
+ _INIT_CMD(0x00, 0x08, 0x00),
+ _INIT_CMD(0x00, 0x09, 0x00),
+ _INIT_CMD(0x00, 0x0A, 0x01),
+ _INIT_CMD(0x00, 0x0B, 0x3C),
+ _INIT_CMD(0x00, 0x0C, 0x00),
+ _INIT_CMD(0x00, 0x0D, 0x00),
+ _INIT_CMD(0x00, 0x0E, 0x24),
+ _INIT_CMD(0x00, 0x0F, 0x1C),
+ _INIT_CMD(0x00, 0x10, 0xC8),
+ _INIT_CMD(0x00, 0x11, 0x60),
+ _INIT_CMD(0x00, 0x12, 0x70),
+ _INIT_CMD(0x00, 0x13, 0x01),
+ _INIT_CMD(0x00, 0x14, 0xE3),
+ _INIT_CMD(0x00, 0x15, 0xFF),
+ _INIT_CMD(0x00, 0x16, 0x3D),
+ _INIT_CMD(0x00, 0x17, 0x0E),
+ _INIT_CMD(0x00, 0x18, 0x01),
+ _INIT_CMD(0x00, 0x19, 0x00),
+ _INIT_CMD(0x00, 0x1A, 0x00),
+ _INIT_CMD(0x00, 0x1B, 0xFC),
+ _INIT_CMD(0x00, 0x1C, 0x0B),
+ _INIT_CMD(0x00, 0x1D, 0xA0),
+ _INIT_CMD(0x00, 0x1E, 0x03),
+ _INIT_CMD(0x00, 0x1F, 0x04),
+ _INIT_CMD(0x00, 0x20, 0x0C),
+ _INIT_CMD(0x00, 0x21, 0x00),
+ _INIT_CMD(0x00, 0x22, 0x04),
+ _INIT_CMD(0x00, 0x23, 0x81),
+ _INIT_CMD(0x00, 0x24, 0x1F),
+ _INIT_CMD(0x00, 0x25, 0x10),
+ _INIT_CMD(0x00, 0x26, 0x9B),
+ _INIT_CMD(0x00, 0x2D, 0x01),
+ _INIT_CMD(0x00, 0x2E, 0x84),
+ _INIT_CMD(0x00, 0x2F, 0x00),
+ _INIT_CMD(0x00, 0x30, 0x02),
+ _INIT_CMD(0x00, 0x31, 0x08),
+ _INIT_CMD(0x00, 0x32, 0x01),
+ _INIT_CMD(0x00, 0x33, 0x1C),
+ _INIT_CMD(0x00, 0x34, 0x70),
+ _INIT_CMD(0x00, 0x35, 0xFF),
+ _INIT_CMD(0x00, 0x36, 0xFF),
+ _INIT_CMD(0x00, 0x37, 0xFF),
+ _INIT_CMD(0x00, 0x38, 0xFF),
+ _INIT_CMD(0x00, 0x39, 0xFF),
+ _INIT_CMD(0x00, 0x3A, 0x05),
+ _INIT_CMD(0x00, 0x3B, 0x00),
+ _INIT_CMD(0x00, 0x3C, 0x00),
+ _INIT_CMD(0x00, 0x3D, 0x00),
+ _INIT_CMD(0x00, 0x3E, 0x0F),
+ _INIT_CMD(0x00, 0x3F, 0xA4),
+ _INIT_CMD(0x00, 0x40, 0x28),
+ _INIT_CMD(0x00, 0x41, 0xFC),
+ _INIT_CMD(0x00, 0x42, 0x01),
+ _INIT_CMD(0x00, 0x43, 0x08),
+ _INIT_CMD(0x00, 0x44, 0x05),
+ _INIT_CMD(0x00, 0x45, 0xF0),
+ _INIT_CMD(0x00, 0x46, 0x01),
+ _INIT_CMD(0x00, 0x47, 0x02),
+ _INIT_CMD(0x00, 0x48, 0x00),
+ _INIT_CMD(0x00, 0x49, 0x58),
+ _INIT_CMD(0x00, 0x4A, 0x00),
+ _INIT_CMD(0x00, 0x4B, 0x05),
+ _INIT_CMD(0x00, 0x4C, 0x03),
+ _INIT_CMD(0x00, 0x4D, 0xD0),
+ _INIT_CMD(0x00, 0x4E, 0x13),
+ _INIT_CMD(0x00, 0x4F, 0xFF),
+ _INIT_CMD(0x00, 0x50, 0x0A),
+ _INIT_CMD(0x00, 0x51, 0x53),
+ _INIT_CMD(0x00, 0x52, 0x26),
+ _INIT_CMD(0x00, 0x53, 0x22),
+ _INIT_CMD(0x00, 0x54, 0x09),
+ _INIT_CMD(0x00, 0x55, 0x22),
+ _INIT_CMD(0x00, 0x56, 0x00),
+ _INIT_CMD(0x00, 0x57, 0x1C),
+ _INIT_CMD(0x00, 0x58, 0x03),
+ _INIT_CMD(0x00, 0x59, 0x3F),
+ _INIT_CMD(0x00, 0x5A, 0x28),
+ _INIT_CMD(0x00, 0x5B, 0x01),
+ _INIT_CMD(0x00, 0x5C, 0xCC),
+ _INIT_CMD(0x00, 0x5D, 0x21),
+ _INIT_CMD(0x00, 0x5E, 0x04),
+ _INIT_CMD(0x00, 0x5F, 0x13),
+ _INIT_CMD(0x00, 0x60, 0x42),
+ _INIT_CMD(0x00, 0x61, 0x08),
+ _INIT_CMD(0x00, 0x62, 0x64),
+ _INIT_CMD(0x00, 0x63, 0xEB),
+ _INIT_CMD(0x00, 0x64, 0x10),
+ _INIT_CMD(0x00, 0x65, 0xA8),
+ _INIT_CMD(0x00, 0x66, 0x84),
+ _INIT_CMD(0x00, 0x67, 0x8E),
+ _INIT_CMD(0x00, 0x68, 0x29),
+ _INIT_CMD(0x00, 0x69, 0x11),
+ _INIT_CMD(0x00, 0x6A, 0x42),
+ _INIT_CMD(0x00, 0x6B, 0x38),
+ _INIT_CMD(0x00, 0x6C, 0x21),
+ _INIT_CMD(0x00, 0x6D, 0x84),
+ _INIT_CMD(0x00, 0x6E, 0x50),
+ _INIT_CMD(0x00, 0x6F, 0xB6),
+ _INIT_CMD(0x00, 0x70, 0x0E),
+ _INIT_CMD(0x00, 0x71, 0xA1),
+ _INIT_CMD(0x00, 0x72, 0xCE),
+ _INIT_CMD(0x00, 0x73, 0xF8),
+ _INIT_CMD(0x00, 0x74, 0xDA),
+ _INIT_CMD(0x00, 0x75, 0x1A),
+ _INIT_CMD(0x00, 0x76, 0x00),
+ _INIT_CMD(0x00, 0x77, 0x00),
+ _INIT_CMD(0x00, 0x78, 0x5F),
+ _INIT_CMD(0x00, 0x79, 0xE0),
+ _INIT_CMD(0x00, 0x7A, 0x01),
+ _INIT_CMD(0x00, 0x7B, 0xFF),
+ _INIT_CMD(0x00, 0x7C, 0xFF),
+ _INIT_CMD(0x00, 0x7D, 0xFF),
+ _INIT_CMD(0x00, 0x7E, 0xFF),
+ _INIT_CMD(0x00, 0x7F, 0xFE),
+ _INIT_CMD(0x00, 0xB1, 0x02),
+ _INIT_CMD(0x00, 0x00, 0xFF),
+ _INIT_CMD(0x00, 0x01, 0x01),
+ _INIT_CMD(0x00, 0x02, 0x00),
+ _INIT_CMD(0x00, 0x03, 0x00),
+ _INIT_CMD(0x00, 0x04, 0x00),
+ _INIT_CMD(0x00, 0x05, 0x00),
+ _INIT_CMD(0x00, 0x06, 0x00),
+ _INIT_CMD(0x00, 0x07, 0x00),
+ _INIT_CMD(0x00, 0x08, 0xC0),
+ _INIT_CMD(0x00, 0x09, 0x00),
+ _INIT_CMD(0x00, 0x0A, 0x00),
+ _INIT_CMD(0x00, 0x0B, 0x04),
+ _INIT_CMD(0x00, 0x0C, 0xE6),
+ _INIT_CMD(0x00, 0x0D, 0x0D),
+ _INIT_CMD(0x00, 0x0F, 0x08),
+ _INIT_CMD(0x00, 0x10, 0xE5),
+ _INIT_CMD(0x00, 0x11, 0xA8),
+ _INIT_CMD(0x00, 0x12, 0xEC),
+ _INIT_CMD(0x00, 0x13, 0x54),
+ _INIT_CMD(0x00, 0x14, 0x5A),
+ _INIT_CMD(0x00, 0x15, 0xD5),
+ _INIT_CMD(0x00, 0x16, 0x23),
+ _INIT_CMD(0x00, 0x17, 0x11),
+ _INIT_CMD(0x00, 0x18, 0x2F),
+ _INIT_CMD(0x00, 0x19, 0x93),
+ _INIT_CMD(0x00, 0x1A, 0xA6),
+ _INIT_CMD(0x00, 0x1B, 0x0F),
+ _INIT_CMD(0x00, 0x1C, 0xFF),
+ _INIT_CMD(0x00, 0x1D, 0xFF),
+ _INIT_CMD(0x00, 0x1E, 0xFF),
+ _INIT_CMD(0x00, 0x1F, 0xFF),
+ _INIT_CMD(0x00, 0x20, 0xFF),
+ _INIT_CMD(0x00, 0x21, 0xFF),
+ _INIT_CMD(0x00, 0x22, 0xFF),
+ _INIT_CMD(0x00, 0x23, 0xFF),
+ _INIT_CMD(0x00, 0x24, 0xFF),
+ _INIT_CMD(0x00, 0x25, 0xFF),
+ _INIT_CMD(0x00, 0x26, 0xFF),
+ _INIT_CMD(0x00, 0x27, 0x1F),
+ _INIT_CMD(0x00, 0x28, 0xC8),
+ _INIT_CMD(0x00, 0x29, 0xFF),
+ _INIT_CMD(0x00, 0x2A, 0xFF),
+ _INIT_CMD(0x00, 0x2B, 0xFF),
+ _INIT_CMD(0x00, 0x2C, 0x07),
+ _INIT_CMD(0x00, 0x2D, 0x03),
+ _INIT_CMD(0x00, 0x33, 0x09),
+ _INIT_CMD(0x00, 0x35, 0x7F),
+ _INIT_CMD(0x00, 0x36, 0x0C),
+ _INIT_CMD(0x00, 0x38, 0x7F),
+ _INIT_CMD(0x00, 0x3A, 0x80),
+ _INIT_CMD(0x00, 0x3B, 0x55),
+ _INIT_CMD(0x00, 0x3C, 0xE2),
+ _INIT_CMD(0x00, 0x3D, 0x32),
+ _INIT_CMD(0x00, 0x3E, 0x00),
+ _INIT_CMD(0x00, 0x3F, 0x58),
+ _INIT_CMD(0x00, 0x40, 0x06),
+ _INIT_CMD(0x00, 0x41, 0x80),
+ _INIT_CMD(0x00, 0x42, 0xCB),
+ _INIT_CMD(0x00, 0x43, 0x2C),
+ _INIT_CMD(0x00, 0x44, 0x61),
+ _INIT_CMD(0x00, 0x45, 0x39),
+ _INIT_CMD(0x00, 0x46, 0x00),
+ _INIT_CMD(0x00, 0x47, 0x00),
+ _INIT_CMD(0x00, 0x48, 0x8B),
+ _INIT_CMD(0x00, 0x49, 0xD2),
+ _INIT_CMD(0x00, 0x4A, 0x01),
+ _INIT_CMD(0x00, 0x4B, 0x00),
+ _INIT_CMD(0x00, 0x4C, 0x10),
+ _INIT_CMD(0x00, 0x4D, 0xC0),
+ _INIT_CMD(0x00, 0x4E, 0x0F),
+ _INIT_CMD(0x00, 0x4F, 0xF1),
+ _INIT_CMD(0x00, 0x50, 0x78),
+ _INIT_CMD(0x00, 0x51, 0x7A),
+ _INIT_CMD(0x00, 0x52, 0x34),
+ _INIT_CMD(0x00, 0x53, 0x99),
+ _INIT_CMD(0x00, 0x54, 0xA2),
+ _INIT_CMD(0x00, 0x55, 0x03),
+ _INIT_CMD(0x00, 0x56, 0x6C),
+ _INIT_CMD(0x00, 0x57, 0x1A),
+ _INIT_CMD(0x00, 0x58, 0x05),
+ _INIT_CMD(0x00, 0x59, 0x30),
+ _INIT_CMD(0x00, 0x5A, 0x1E),
+ _INIT_CMD(0x00, 0x5B, 0x8F),
+ _INIT_CMD(0x00, 0x5C, 0xC7),
+ _INIT_CMD(0x00, 0x5D, 0xE3),
+ _INIT_CMD(0x00, 0x5E, 0xF1),
+ _INIT_CMD(0x00, 0x5F, 0x78),
+ _INIT_CMD(0x00, 0x60, 0x3C),
+ _INIT_CMD(0x00, 0x61, 0x36),
+ _INIT_CMD(0x00, 0x62, 0x1E),
+ _INIT_CMD(0x00, 0x63, 0x1B),
+ _INIT_CMD(0x00, 0x64, 0x8F),
+ _INIT_CMD(0x00, 0x65, 0xC7),
+ _INIT_CMD(0x00, 0x66, 0xE3),
+ _INIT_CMD(0x00, 0x67, 0x31),
+ _INIT_CMD(0x00, 0x68, 0x14),
+ _INIT_CMD(0x00, 0x69, 0x89),
+ _INIT_CMD(0x00, 0x6A, 0x70),
+ _INIT_CMD(0x00, 0x6B, 0x8C),
+ _INIT_CMD(0x00, 0x6C, 0x8D),
+ _INIT_CMD(0x00, 0x6D, 0x8D),
+ _INIT_CMD(0x00, 0x6E, 0x8D),
+ _INIT_CMD(0x00, 0x6F, 0x8D),
+ _INIT_CMD(0x00, 0x70, 0xC7),
+ _INIT_CMD(0x00, 0x71, 0xE3),
+ _INIT_CMD(0x00, 0x72, 0xF1),
+ _INIT_CMD(0x00, 0x73, 0xD8),
+ _INIT_CMD(0x00, 0x74, 0xD8),
+ _INIT_CMD(0x00, 0x75, 0xD8),
+ _INIT_CMD(0x00, 0x76, 0x18),
+ _INIT_CMD(0x00, 0x77, 0x00),
+ _INIT_CMD(0x00, 0x78, 0x00),
+ _INIT_CMD(0x00, 0x79, 0x00),
+ _INIT_CMD(0x00, 0x7A, 0xC6),
+ _INIT_CMD(0x00, 0x7B, 0xC6),
+ _INIT_CMD(0x00, 0x7C, 0xC6),
+ _INIT_CMD(0x00, 0x7D, 0xC6),
+ _INIT_CMD(0x00, 0x7E, 0xC6),
+ _INIT_CMD(0x00, 0x7F, 0xE3),
+ _INIT_CMD(0x00, 0x0B, 0x04),
+ _INIT_CMD(0x00, 0xB1, 0x03),
+ _INIT_CMD(0x00, 0x2C, 0x2C),
+ _INIT_CMD(0x00, 0xB1, 0x00),
+ _INIT_CMD(0x00, 0x89, 0x03),
+ _INIT_CMD(0x78, 0x11),
+ _INIT_CMD(0x14, 0x29),
+
+ {},
+};
+
+static const struct panel_cmd inx_ota7290d10p_off_cmds[] = {
+ _INIT_CMD(0x00, 0x28),
+ _INIT_CMD(0x01, 0x10),
+
+ {},
+};
+
+static const struct panel_desc inx_ota7290d10p_panel_desc = {
+ .display_mode = &default_display_mode,
+ .bpc = 8,
+ .width_mm = 107,
+ .height_mm = 172,
+ .delay_t1 = 5000,
+ .reset_delay_t2 = 14000,
+ .reset_delay_t3 = 1000,
+ .reset_delay_t4 = 1000,
+ .reset_delay_t5 = 5000,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 4,
+ .on_cmds = inx_ota7290d10p_on_cmds,
+ .off_cmds = inx_ota7290d10p_off_cmds,
+};
+
static const struct of_device_id panel_of_match[] = {
{ .compatible = "boe,himax8279d8p",
.data = &boe_himax8279d8p_panel_desc
}, { .compatible = "boe,himax8279d10p",
.data = &boe_himax8279d10p_panel_desc
+ }, { .compatible = "auo,nt51021d8p",
+ .data = &auo_nt51021d8p_panel_desc
+ }, { .compatible = "inx,ota7290d10p",
+ .data = &inx_ota7290d10p_panel_desc
+ }, { .compatible = "boe,tv080wum_ng0",
+ .data = &boe_tv080wumng0_panel_desc
+ }, { .compatible = "boe,tv101wum_ng0",
+ .data = &boe_tv101wumng0_panel_desc
}, {
/* sentinel */
}
@@ -958,6 +1900,10 @@ static int panel_add(struct panel_info *pinfo)
if (IS_ERR(pinfo->backlight))
return PTR_ERR(pinfo->backlight);
+ ret = of_drm_get_panel_orientation(dev->of_node, &pinfo->orientation);
+ if (ret < 0)
+ return ret;
+
drm_panel_init(&pinfo->base);
pinfo->base.funcs = &panel_funcs;
pinfo->base.dev = &pinfo->link->dev;
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index 388ef70c11d2..d16c1d4649ce 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -79,6 +79,19 @@ config SX9500
To compile this driver as a module, choose M here: the
module will be called sx9500.
+config SX9311
+ tristate "SX9311 Semtech proximity sensor"
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Say Y here to build a driver for Semtech's SX9311 capacitive
+ proximity/button sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sx9311.
+
config SRF08
tristate "Devantech SRF02/SRF08/SRF10 ultrasonic ranger sensor"
select IIO_BUFFER
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index cac3d7d3325e..c0ac5af12015 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_RFD77402) += rfd77402.o
obj-$(CONFIG_SRF04) += srf04.o
obj-$(CONFIG_SRF08) += srf08.o
obj-$(CONFIG_SX9500) += sx9500.o
+obj-$(CONFIG_SX9311) += sx9311.o
diff --git a/drivers/iio/proximity/sx9311.c b/drivers/iio/proximity/sx9311.c
new file mode 100644
index 000000000000..408c349dd436
--- /dev/null
+++ b/drivers/iio/proximity/sx9311.c
@@ -0,0 +1,1144 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019, Google LLC.
+ *
+ * Driver for Semtech's SX9311 capacitive proximity/button solution.
+ * Datasheet available at
+ * <http://www.semtech.com/images/datasheet/sx9311.pdf>.
+ * Based on SX9310 driver and Semtech driver using the input framework
+ * <https://my.syncplicity.com/share/teouwsim8niiaud/
+ * linux-driver-SX9311_NoSmartHSensing>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regmap.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define SX9311_DRIVER_NAME "sx9311"
+#define SX9311_ACPI_NAME "STH9311"
+#define SX9311_IRQ_NAME "sx9311_event"
+
+#define SX9311_GPIO_INT "interrupt"
+
+/* Register definitions. */
+#define SX9311_REG_IRQ_SRC 0x00
+#define SX9311_REG_STAT0 0x01
+#define SX9311_REG_STAT1 0x02
+#define SX9311_REG_IRQ_MSK 0x03
+#define SX9311_REG_IRQ_FUNC 0x04
+
+#define SX9311_REG_PROX_CTRL0 0x10
+#define SX9311_REG_PROX_CTRL1 0x11
+#define SX9311_REG_PROX_CTRL2 0x12
+#define SX9311_REG_PROX_CTRL3 0x13
+#define SX9311_REG_PROX_CTRL4 0x14
+#define SX9311_REG_PROX_CTRL5 0x15
+#define SX9311_REG_PROX_CTRL6 0x16
+#define SX9311_REG_PROX_CTRL7 0x17
+#define SX9311_REG_PROX_CTRL8 0x18
+#define SX9311_REG_PROX_CTRL9 0x19
+#define SX9311_REG_PROX_CTRL10 0x1A
+#define SX9311_REG_PROX_CTRL11 0x1B
+#define SX9311_REG_PROX_CTRL12 0x1C
+#define SX9311_REG_PROX_CTRL13 0x1D
+#define SX9311_REG_PROX_CTRL14 0x1E
+#define SX9311_REG_PROX_CTRL15 0x1F
+#define SX9311_REG_PROX_CTRL16 0x20
+#define SX9311_REG_PROX_CTRL17 0x21
+#define SX9311_REG_PROX_CTRL18 0x22
+#define SX9311_REG_PROX_CTRL19 0x23
+#define SX9311_REG_SAR_CTRL0 0x2A
+#define SX9311_REG_SAR_CTRL1 0x2B
+#define SX9311_REG_SAR_CTRL2 0x2C
+
+#define SX9311_REG_SENSOR_SEL 0x30
+
+#define SX9311_REG_USE_MSB 0x31
+#define SX9311_REG_USE_LSB 0x32
+
+#define SX9311_REG_AVG_MSB 0x33
+#define SX9311_REG_AVG_LSB 0x34
+
+#define SX9311_REG_DIFF_MSB 0x35
+#define SX9311_REG_DIFF_LSB 0x36
+
+#define SX9311_REG_OFFSET_MSB 0x37
+#define SX9311_REG_OFFSET_LSB 0x38
+
+#define SX9311_REG_SAR_MSB 0x39
+#define SX9311_REG_SAR_LSB 0x3A
+
+#define SX9311_REG_I2CADDR 0x40
+#define SX9311_REG_PAUSE 0x41
+#define SX9311_REG_WHOAMI 0x42
+/* Expected content of the WHOAMI register. */
+#define SX9311_WHOAMI_VALUE 0x02
+
+#define SX9311_REG_RESET 0x7f
+/* Write this to REG_RESET to do a soft reset. */
+#define SX9311_SOFT_RESET 0xde
+
+
+/* Sensor Readback */
+
+/*
+ * These serve for identifying IRQ source in the IRQ_SRC register, and
+ * also for masking the IRQs in the IRQ_MSK register.
+ */
+#define SX9311_RESET_IRQ BIT(7)
+#define SX9311_CLOSE_IRQ BIT(6)
+#define SX9311_FAR_IRQ BIT(5)
+#define SX9311_COMPDONE_IRQ BIT(4)
+#define SX9311_CONVDONE_IRQ BIT(3)
+
+#define SX9311_SCAN_PERIOD_MASK GENMASK(7, 4)
+#define SX9311_SCAN_PERIOD_SHIFT 4
+
+#define SX9311_COMPSTAT_MASK GENMASK(3, 0)
+
+/* 4 channels, as defined in STAT0: COMB, CS2, CS1 and CS0. */
+#define SX9311_NUM_CHANNELS 4
+#define SX9311_CHAN_MASK GENMASK(2, 0)
+
+struct sx9311_data {
+ struct mutex mutex;
+ struct i2c_client *client;
+ struct iio_trigger *trig;
+ struct regmap *regmap;
+ /*
+ * Last reading of the proximity status for each channel.
+ * We only send an event to user space when this changes.
+ */
+ bool prox_stat[SX9311_NUM_CHANNELS];
+ bool event_enabled[SX9311_NUM_CHANNELS];
+ bool trigger_enabled;
+ u16 *buffer;
+ /* Remember enabled channels and sample rate during suspend. */
+ unsigned int suspend_ctrl0;
+ struct completion completion;
+ int data_rdy_users, close_far_users;
+ int channel_users[SX9311_NUM_CHANNELS];
+ unsigned int num_irqs;
+};
+
+static const struct iio_event_spec sx9311_events[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+#define SX9311_CHANNEL(idx, name, addr) \
+ { \
+ .type = IIO_PROXIMITY, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .indexed = 1, \
+ .channel = idx, \
+ .address = addr, \
+ .event_spec = sx9311_events, \
+ .num_event_specs = ARRAY_SIZE(sx9311_events), \
+ .extend_name = name, \
+ .scan_index = idx, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .shift = 0, \
+ }, \
+ }
+
+static const struct iio_chan_spec sx9311_channels[] = {
+ SX9311_CHANNEL(0, "USE_CS0", SX9311_REG_USE_MSB),
+ SX9311_CHANNEL(1, "USE_CS1", SX9311_REG_USE_MSB),
+ SX9311_CHANNEL(2, "USE_CS2", SX9311_REG_USE_MSB),
+ SX9311_CHANNEL(3, "USE_COMB", SX9311_REG_USE_MSB),
+
+ SX9311_CHANNEL(4, "DIFF_CS0", SX9311_REG_DIFF_MSB),
+ SX9311_CHANNEL(5, "DIFF_CS1", SX9311_REG_DIFF_MSB),
+ SX9311_CHANNEL(6, "DIFF_CS2", SX9311_REG_DIFF_MSB),
+ SX9311_CHANNEL(7, "DIFF_COMB", SX9311_REG_DIFF_MSB),
+
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+/*
+ * Each entry contains the integer part (val) and the fractional part, in micro
+ * seconds. It conforms to the IIO output IIO_VAL_INT_PLUS_MICRO.
+ */
+static const struct {
+ int val;
+ int val2;
+} sx9311_samp_freq_table[] = {
+ {500, 0}, /* 0000: Min (no idle time) */
+ {66, 666666}, /* 0001: 15 ms */
+ {33, 333333}, /* 0010: 30 ms (Typ.) */
+ {22, 222222}, /* 0011: 45 ms */
+ {16, 666666}, /* 0100: 60 ms */
+ {11, 111111}, /* 0101: 90 ms */
+ {8, 333333}, /* 0110: 120 ms */
+ {5, 0}, /* 0111: 200 ms */
+ {2, 500000}, /* 1000: 400 ms */
+ {1, 666666}, /* 1001: 600 ms */
+ {1, 250000}, /* 1010: 800 ms */
+ {1, 0}, /* 1011: 1 s */
+ {0, 500000}, /* 1100: 2 s */
+ {8, 333333}, /* 1101: 3 s */
+ {0, 250000}, /* 1110: 4 s */
+ {0, 200000}, /* 1111: 5 s */
+};
+static const unsigned int sx9311_scan_period_table[] = {
+ 2, 15, 30, 45, 60, 90, 120, 200, 400, 800, 1000, 2000, 3000, 4000, 5000,
+};
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
+ "500.0 66.666666 33.333333 22.222222 16.666666 "
+ "11.111111 8.333333 5.0 2.500000 1.666666 1.250000 "
+ "1.0 0.500000 8.333333 0.250000 0.200000");
+
+
+static const struct regmap_range sx9311_writable_reg_ranges[] = {
+ regmap_reg_range(SX9311_REG_IRQ_MSK, SX9311_REG_IRQ_FUNC),
+ regmap_reg_range(SX9311_REG_PROX_CTRL0, SX9311_REG_PROX_CTRL19),
+ regmap_reg_range(SX9311_REG_SAR_CTRL0, SX9311_REG_SAR_CTRL2),
+ regmap_reg_range(SX9311_REG_SENSOR_SEL, SX9311_REG_SENSOR_SEL),
+ regmap_reg_range(SX9311_REG_OFFSET_MSB, SX9311_REG_OFFSET_LSB),
+ regmap_reg_range(SX9311_REG_PAUSE, SX9311_REG_PAUSE),
+ regmap_reg_range(SX9311_REG_RESET, SX9311_REG_RESET),
+};
+
+static const struct regmap_access_table sx9311_writeable_regs = {
+ .yes_ranges = sx9311_writable_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(sx9311_writable_reg_ranges),
+};
+
+/*
+ * All allocated registers are readable, so we just list unallocated
+ * ones.
+ */
+static const struct regmap_range sx9311_non_readable_reg_ranges[] = {
+ regmap_reg_range(SX9311_REG_IRQ_FUNC + 1, SX9311_REG_PROX_CTRL0 - 1),
+ regmap_reg_range(SX9311_REG_SAR_CTRL2 + 1, SX9311_REG_SENSOR_SEL - 1),
+ regmap_reg_range(SX9311_REG_SAR_LSB + 1, SX9311_REG_I2CADDR - 1),
+ regmap_reg_range(SX9311_REG_WHOAMI + 1, SX9311_REG_RESET - 1),
+};
+
+static const struct regmap_access_table sx9311_readable_regs = {
+ .no_ranges = sx9311_non_readable_reg_ranges,
+ .n_no_ranges = ARRAY_SIZE(sx9311_non_readable_reg_ranges),
+};
+
+static const struct regmap_range sx9311_volatile_reg_ranges[] = {
+ regmap_reg_range(SX9311_REG_IRQ_SRC, SX9311_REG_STAT1),
+ regmap_reg_range(SX9311_REG_USE_MSB, SX9311_REG_DIFF_LSB),
+ regmap_reg_range(SX9311_REG_SAR_MSB, SX9311_REG_SAR_LSB),
+ regmap_reg_range(SX9311_REG_RESET, SX9311_REG_RESET),
+};
+
+static const struct regmap_access_table sx9311_volatile_regs = {
+ .yes_ranges = sx9311_volatile_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(sx9311_volatile_reg_ranges),
+};
+
+static const struct regmap_config sx9311_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = SX9311_REG_RESET,
+ .cache_type = REGCACHE_RBTREE,
+
+ .wr_table = &sx9311_writeable_regs,
+ .rd_table = &sx9311_readable_regs,
+ .volatile_table = &sx9311_volatile_regs,
+};
+
+static int sx9311_inc_users(struct sx9311_data *data, int *counter,
+ unsigned int reg, unsigned int bitmask)
+{
+ ++(*counter);
+ if (*counter != 1)
+ /* Bit is already active, nothing to do. */
+ return 0;
+
+ return regmap_update_bits(data->regmap, reg, bitmask, bitmask);
+}
+
+static int sx9311_dec_users(struct sx9311_data *data, int *counter,
+ unsigned int reg, unsigned int bitmask)
+{
+ --(*counter);
+ if (*counter != 0)
+ /* There are more users, do not deactivate. */
+ return 0;
+
+ return regmap_update_bits(data->regmap, reg, bitmask, 0);
+}
+
+static int sx9311_inc_chan_users(struct sx9311_data *data, int chan)
+{
+ return sx9311_inc_users(data, &data->channel_users[chan],
+ SX9311_REG_PROX_CTRL0, BIT(chan));
+}
+
+static int sx9311_dec_chan_users(struct sx9311_data *data, int chan)
+{
+ return sx9311_dec_users(data, &data->channel_users[chan],
+ SX9311_REG_PROX_CTRL0, BIT(chan));
+}
+
+static int sx9311_inc_data_rdy_users(struct sx9311_data *data)
+{
+ return sx9311_inc_users(data, &data->data_rdy_users,
+ SX9311_REG_IRQ_MSK, SX9311_CONVDONE_IRQ);
+}
+
+static int sx9311_dec_data_rdy_users(struct sx9311_data *data)
+{
+ return sx9311_dec_users(data, &data->data_rdy_users,
+ SX9311_REG_IRQ_MSK, SX9311_CONVDONE_IRQ);
+}
+
+static int sx9311_inc_close_far_users(struct sx9311_data *data)
+{
+ return sx9311_inc_users(data, &data->close_far_users,
+ SX9311_REG_IRQ_MSK,
+ SX9311_CLOSE_IRQ | SX9311_FAR_IRQ);
+}
+
+static int sx9311_dec_close_far_users(struct sx9311_data *data)
+{
+ return sx9311_dec_users(data, &data->close_far_users,
+ SX9311_REG_IRQ_MSK,
+ SX9311_CLOSE_IRQ | SX9311_FAR_IRQ);
+}
+
+static int sx9311_read_prox_data(struct sx9311_data *data,
+ const struct iio_chan_spec *chan,
+ int *val)
+{
+ int ret;
+ __be16 regval;
+
+ ret = regmap_write(data->regmap, SX9311_REG_SENSOR_SEL, chan->channel);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_bulk_read(data->regmap, chan->address, &regval, 2);
+ if (ret < 0)
+ return ret;
+
+ *val = sign_extend32(be16_to_cpu(regval),
+ (chan->address == SX9311_REG_DIFF_MSB ? 11 : 15));
+
+ return 0;
+}
+
+/*
+ * If we have no interrupt support, we have to wait for a scan period
+ * after enabling a channel to get a result.
+ */
+static int sx9311_wait_for_sample(struct sx9311_data *data)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(data->regmap, SX9311_REG_PROX_CTRL0, &val);
+ if (ret < 0)
+ return ret;
+
+ val = (val & SX9311_SCAN_PERIOD_MASK) >> SX9311_SCAN_PERIOD_SHIFT;
+
+ msleep(sx9311_scan_period_table[val]);
+
+ return 0;
+}
+
+static int sx9311_read_proximity(struct sx9311_data *data,
+ const struct iio_chan_spec *chan,
+ int *val)
+{
+ int ret;
+
+ mutex_lock(&data->mutex);
+
+ ret = sx9311_inc_chan_users(data, chan->channel & SX9311_CHAN_MASK);
+ if (ret < 0)
+ goto out;
+
+ ret = sx9311_inc_data_rdy_users(data);
+ if (ret < 0)
+ goto out_dec_chan;
+
+ mutex_unlock(&data->mutex);
+
+ if (data->client->irq > 0)
+ ret = wait_for_completion_interruptible(&data->completion);
+ else
+ ret = sx9311_wait_for_sample(data);
+
+ mutex_lock(&data->mutex);
+
+ if (ret < 0)
+ goto out_dec_data_rdy;
+
+ ret = sx9311_read_prox_data(data, chan, val);
+ if (ret < 0)
+ goto out_dec_data_rdy;
+
+ ret = sx9311_dec_data_rdy_users(data);
+ if (ret < 0)
+ goto out_dec_chan;
+
+ ret = sx9311_dec_chan_users(data, chan->channel & SX9311_CHAN_MASK);
+ if (ret < 0)
+ goto out;
+
+ ret = IIO_VAL_INT;
+
+ goto out;
+
+out_dec_data_rdy:
+ sx9311_dec_data_rdy_users(data);
+out_dec_chan:
+ sx9311_dec_chan_users(data, chan->channel & SX9311_CHAN_MASK);
+out:
+ mutex_unlock(&data->mutex);
+ reinit_completion(&data->completion);
+
+ return ret;
+}
+
+static int sx9311_read_samp_freq(struct sx9311_data *data,
+ int *val, int *val2)
+{
+ int ret;
+ unsigned int regval;
+
+ mutex_lock(&data->mutex);
+ ret = regmap_read(data->regmap, SX9311_REG_PROX_CTRL0, &regval);
+
+ mutex_unlock(&data->mutex);
+ if (ret < 0)
+ return ret;
+
+ regval = (regval & SX9311_SCAN_PERIOD_MASK) >> SX9311_SCAN_PERIOD_SHIFT;
+ *val = sx9311_samp_freq_table[regval].val;
+ *val2 = sx9311_samp_freq_table[regval].val2;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int sx9311_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&indio_dev->mlock);
+
+ if (iio_buffer_enabled(indio_dev)) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+ ret = sx9311_read_proximity(data, chan, val);
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return sx9311_read_samp_freq(data, val, val2);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int sx9311_set_samp_freq(struct sx9311_data *data,
+ int val, int val2)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(sx9311_samp_freq_table); i++)
+ if (val == sx9311_samp_freq_table[i].val &&
+ val2 == sx9311_samp_freq_table[i].val2)
+ break;
+
+ if (i == ARRAY_SIZE(sx9311_samp_freq_table))
+ return -EINVAL;
+
+ mutex_lock(&data->mutex);
+
+ ret = regmap_update_bits(data->regmap, SX9311_REG_PROX_CTRL0,
+ SX9311_SCAN_PERIOD_MASK,
+ i << SX9311_SCAN_PERIOD_SHIFT);
+
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int sx9311_write_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int val, int val2, long mask)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return sx9311_set_samp_freq(data, val, val2);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t sx9311_irq_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct sx9311_data *data = iio_priv(indio_dev);
+
+ if (data->trigger_enabled)
+ iio_trigger_poll(data->trig);
+
+ /*
+ * Even if no event is enabled, we need to wake the thread to
+ * clear the interrupt state by reading SX9311_REG_IRQ_SRC. It
+ * is not possible to do that here because regmap_read takes a
+ * mutex.
+ */
+ return IRQ_WAKE_THREAD;
+}
+
+static void sx9311_push_events(struct iio_dev *indio_dev)
+{
+ int ret;
+ unsigned int val, chan;
+ struct sx9311_data *data = iio_priv(indio_dev);
+
+ ret = regmap_read(data->regmap, SX9311_REG_STAT0, &val);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "i2c transfer error in irq\n");
+ return;
+ }
+
+ for (chan = 0; chan < SX9311_NUM_CHANNELS; chan++) {
+ int dir;
+ u64 ev;
+ bool new_prox = val & BIT(chan);
+
+ if (!data->event_enabled[chan])
+ continue;
+ if (new_prox == data->prox_stat[chan])
+ /* No change on this channel. */
+ continue;
+
+ dir = new_prox ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING;
+ ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan,
+ IIO_EV_TYPE_THRESH, dir);
+ iio_push_event(indio_dev, ev, iio_get_time_ns(indio_dev));
+ data->prox_stat[chan] = new_prox;
+ }
+}
+
+static irqreturn_t sx9311_irq_thread_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret;
+ unsigned int val;
+
+ mutex_lock(&data->mutex);
+
+ ret = regmap_read(data->regmap, SX9311_REG_IRQ_SRC, &val);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "i2c transfer error in irq\n");
+ goto out;
+ }
+
+ if (val & (SX9311_CLOSE_IRQ | SX9311_FAR_IRQ))
+ sx9311_push_events(indio_dev);
+
+ if (val & SX9311_CONVDONE_IRQ)
+ complete(&data->completion);
+
+out:
+ mutex_unlock(&data->mutex);
+
+ return IRQ_HANDLED;
+}
+
+static int sx9311_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+
+ if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH ||
+ dir != IIO_EV_DIR_EITHER)
+ return -EINVAL;
+
+ return data->event_enabled[chan->channel & SX9311_CHAN_MASK];
+}
+
+static int sx9311_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ int state)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret, sx_channel = chan->channel & SX9311_CHAN_MASK;
+
+ if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH ||
+ dir != IIO_EV_DIR_EITHER)
+ return -EINVAL;
+
+ mutex_lock(&data->mutex);
+
+ if (state == 1) {
+ ret = sx9311_inc_chan_users(data, sx_channel);
+ if (ret < 0)
+ goto out_unlock;
+ ret = sx9311_inc_close_far_users(data);
+ if (ret < 0)
+ goto out_undo_chan;
+ } else {
+ ret = sx9311_dec_chan_users(data, sx_channel);
+ if (ret < 0)
+ goto out_unlock;
+ ret = sx9311_dec_close_far_users(data);
+ if (ret < 0)
+ goto out_undo_chan;
+ }
+
+ data->event_enabled[sx_channel] = state;
+ goto out_unlock;
+
+out_undo_chan:
+ if (state == 1)
+ sx9311_dec_chan_users(data, sx_channel);
+ else
+ sx9311_inc_chan_users(data, sx_channel);
+out_unlock:
+ mutex_unlock(&data->mutex);
+ return ret;
+}
+
+static int sx9311_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+
+ mutex_lock(&data->mutex);
+ kfree(data->buffer);
+ data->buffer = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
+ mutex_unlock(&data->mutex);
+
+ if (data->buffer == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static struct attribute *sx9311_attributes[] = {
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group sx9311_attribute_group = {
+ .attrs = sx9311_attributes,
+};
+
+static const struct iio_info sx9311_info = {
+ .attrs = &sx9311_attribute_group,
+ .read_raw = &sx9311_read_raw,
+ .write_raw = &sx9311_write_raw,
+ .read_event_config = &sx9311_read_event_config,
+ .write_event_config = &sx9311_write_event_config,
+ .update_scan_mode = &sx9311_update_scan_mode,
+};
+
+static int sx9311_set_trigger_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&data->mutex);
+
+ if (state)
+ ret = sx9311_inc_data_rdy_users(data);
+ else
+ ret = sx9311_dec_data_rdy_users(data);
+ if (ret < 0)
+ goto out;
+
+ data->trigger_enabled = state;
+
+out:
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static const struct iio_trigger_ops sx9311_trigger_ops = {
+ .set_trigger_state = sx9311_set_trigger_state,
+};
+
+static irqreturn_t sx9311_trigger_handler(int irq, void *private)
+{
+ struct iio_poll_func *pf = private;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int val, bit, ret, i = 0;
+
+ mutex_lock(&data->mutex);
+
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ ret = sx9311_read_prox_data(data, &indio_dev->channels[bit],
+ &val);
+ if (ret < 0)
+ goto out;
+
+ data->buffer[i++] = val;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ iio_get_time_ns(indio_dev));
+
+out:
+ mutex_unlock(&data->mutex);
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int sx9311_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret = 0, i;
+
+ mutex_lock(&data->mutex);
+
+ for (i = 0; i < SX9311_NUM_CHANNELS; i++)
+ if (test_bit(i, indio_dev->active_scan_mask)) {
+ ret = sx9311_inc_chan_users(data, i);
+ if (ret)
+ break;
+ }
+
+ if (ret)
+ for (i = i - 1; i >= 0; i--)
+ if (test_bit(i, indio_dev->active_scan_mask))
+ sx9311_dec_chan_users(data, i);
+
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int sx9311_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret = 0, i;
+
+ iio_triggered_buffer_predisable(indio_dev);
+
+ mutex_lock(&data->mutex);
+
+ for (i = 0; i < SX9311_NUM_CHANNELS; i++)
+ if (test_bit(i, indio_dev->active_scan_mask)) {
+ ret = sx9311_dec_chan_users(data, i);
+ if (ret)
+ break;
+ }
+
+ if (ret)
+ for (i = i - 1; i >= 0; i--)
+ if (test_bit(i, indio_dev->active_scan_mask))
+ sx9311_inc_chan_users(data, i);
+
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static const struct iio_buffer_setup_ops sx9311_buffer_setup_ops = {
+ .preenable = sx9311_buffer_preenable,
+ .postenable = iio_triggered_buffer_postenable,
+ .predisable = sx9311_buffer_predisable,
+};
+
+struct sx9311_reg_config {
+ const char *register_name;
+ u8 reg;
+ u8 def;
+};
+
+#define SX9311_REG_CONFIG(_name, _reg, _def) \
+{ \
+ .register_name = SX9311_ACPI_NAME ",reg_" _name, \
+ .reg = SX9311_REG_##_reg, \
+ .def = _def \
+}
+
+static const struct sx9311_reg_config sx9311_default_regs[] = {
+ {
+ .register_name = NULL,
+ .reg = SX9311_REG_IRQ_MSK,
+ .def = 0x60,
+ },
+ {
+ .register_name = NULL,
+ .reg = SX9311_REG_IRQ_FUNC,
+ .def = 0x00,
+ },
+ /*
+ * The lower 4 bits should not be set as it enable sensors measurements.
+ * Turning the detection on before the configuration values are set to
+ * good values can cause the device to return erroneous readings.
+ */
+ SX9311_REG_CONFIG("prox_ctrl0", PROX_CTRL0, 0x23),
+ SX9311_REG_CONFIG("prox_ctrl1", PROX_CTRL1, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl2", PROX_CTRL2, 0x0B),
+ SX9311_REG_CONFIG("prox_ctrl3", PROX_CTRL3, 0x0F),
+ SX9311_REG_CONFIG("prox_ctrl4", PROX_CTRL4, 0x0D),
+ SX9311_REG_CONFIG("prox_ctrl5", PROX_CTRL5, 0xC3),
+ SX9311_REG_CONFIG("prox_ctrl6", PROX_CTRL6, 0x20),
+ SX9311_REG_CONFIG("prox_ctrl7", PROX_CTRL7, 0x4C),
+ SX9311_REG_CONFIG("prox_ctrl8", PROX_CTRL8, 0x68),
+ SX9311_REG_CONFIG("prox_ctrl9", PROX_CTRL9, 0x68),
+ SX9311_REG_CONFIG("prox_ctrl10", PROX_CTRL10, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl11", PROX_CTRL11, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl12", PROX_CTRL12, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl13", PROX_CTRL13, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl14", PROX_CTRL14, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl15", PROX_CTRL15, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl16", PROX_CTRL16, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl17", PROX_CTRL17, 0x04),
+ SX9311_REG_CONFIG("prox_ctrl18", PROX_CTRL18, 0x00),
+ SX9311_REG_CONFIG("prox_ctrl19", PROX_CTRL19, 0x00),
+ SX9311_REG_CONFIG("sar_ctrl0", SAR_CTRL0, 0x00),
+ SX9311_REG_CONFIG("sar_ctrl1", SAR_CTRL1, 0x80),
+ SX9311_REG_CONFIG("sar_ctrl2", SAR_CTRL2, 0x0C),
+};
+
+static int sx9311_read_register_property(struct acpi_device *adev,
+ const struct sx9311_reg_config *cfg,
+ u8 *value)
+{
+ /* FIXME: only ACPI supported. */
+ const union acpi_object *acpi_value = NULL;
+ int ret;
+
+ if ((adev == NULL) || (cfg->register_name == NULL)) {
+ *value = cfg->def;
+ return 0;
+ }
+
+ ret = acpi_dev_get_property(adev, cfg->register_name,
+ ACPI_TYPE_INTEGER, &acpi_value);
+ switch (ret) {
+ case -EPROTO:
+ break;
+ case -EINVAL:
+ break;
+ }
+
+ *value = acpi_value ? (u8)acpi_value->integer.value : cfg->def;
+ return 0;
+}
+
+static int sx9311_load_config(struct device *dev, struct regmap *regmap)
+{
+ u8 val;
+ int i, ret;
+ const struct sx9311_reg_config *cfg;
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+
+ if (adev == NULL)
+ dev_warn(dev, "ACPI configuration missing\n");
+
+ for (i = 0; i < ARRAY_SIZE(sx9311_default_regs); ++i) {
+ cfg = &sx9311_default_regs[i];
+ ret = sx9311_read_register_property(adev, cfg, &val);
+ if (ret < 0)
+ return ret;
+ ret = regmap_write(regmap, cfg->reg, val);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Activate all channels and perform an initial compensation. */
+static int sx9311_init_compensation(struct iio_dev *indio_dev)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int i, ret;
+ unsigned int val;
+ unsigned int ctrl0;
+
+ ret = regmap_read(data->regmap, SX9311_REG_PROX_CTRL0, &ctrl0);
+ if (ret < 0)
+ return ret;
+
+ /* run the compensation phase on all channels */
+ ret = regmap_write(data->regmap, SX9311_REG_PROX_CTRL0, ctrl0 | 0xF);
+ if (ret < 0)
+ return ret;
+
+ for (i = 100; i >= 0; i--) {
+ usleep_range(10000, 20000);
+ ret = regmap_read(data->regmap, SX9311_REG_STAT1, &val);
+ if (ret < 0)
+ goto out;
+ if (!(val & SX9311_COMPSTAT_MASK))
+ break;
+ }
+
+ if (i < 0) {
+ dev_err(&data->client->dev,
+ "initial compensation timed out: 0x%02x", val);
+ ret = -ETIMEDOUT;
+ }
+
+out:
+ regmap_write(data->regmap, SX9311_REG_PROX_CTRL0, ctrl0);
+ return ret;
+}
+
+static int sx9311_init_device(struct iio_dev *indio_dev)
+{
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret;
+ unsigned int val;
+
+ ret = regmap_write(data->regmap, SX9311_REG_IRQ_MSK, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write(data->regmap, SX9311_REG_RESET,
+ SX9311_SOFT_RESET);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(1000, 2000); /* power-up time is ~1ms. */
+
+ ret = regmap_write(data->regmap, SX9311_REG_RESET, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(data->regmap, SX9311_REG_IRQ_SRC, &val);
+ if (ret < 0)
+ return ret;
+
+ ret = sx9311_load_config(&indio_dev->dev, data->regmap);
+ if (ret < 0)
+ return ret;
+
+ return sx9311_init_compensation(indio_dev);
+}
+
+static int sx9311_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ struct iio_dev *indio_dev;
+ struct sx9311_data *data;
+ unsigned int whoami;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ mutex_init(&data->mutex);
+ init_completion(&data->completion);
+ data->trigger_enabled = false;
+
+ data->regmap = devm_regmap_init_i2c(client, &sx9311_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ ret = regmap_read(data->regmap, SX9311_REG_WHOAMI, &whoami);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "error in reading WHOAMI register: %d", ret);
+ return -ENODEV;
+ }
+ if (whoami != SX9311_WHOAMI_VALUE) {
+ dev_err(&client->dev, "unexpected WHOAMI response: %u", whoami);
+ return -ENODEV;
+ }
+
+ ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(&client->dev));
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = SX9311_DRIVER_NAME;
+ indio_dev->channels = sx9311_channels;
+ indio_dev->num_channels = ARRAY_SIZE(sx9311_channels);
+ indio_dev->info = &sx9311_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ i2c_set_clientdata(client, indio_dev);
+
+ ret = sx9311_init_device(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ if (client->irq <= 0)
+ dev_warn(&client->dev, "no valid irq found\n");
+ else {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ sx9311_irq_handler, sx9311_irq_thread_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ SX9311_IRQ_NAME, indio_dev);
+ if (ret < 0)
+ return ret;
+
+ data->trig = devm_iio_trigger_alloc(&client->dev,
+ "%s-dev%d", indio_dev->name, indio_dev->id);
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->dev.parent = &client->dev;
+ data->trig->ops = &sx9311_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+
+ ret = iio_trigger_register(data->trig);
+ if (ret)
+ return ret;
+ }
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
+ NULL, sx9311_trigger_handler,
+ &sx9311_buffer_setup_ops);
+ if (ret < 0)
+ goto out_trigger_unregister;
+
+ ret = devm_iio_device_register(&client->dev, indio_dev);
+ if (ret < 0)
+ goto out_trigger_unregister;
+
+ return 0;
+
+out_trigger_unregister:
+ if (client->irq > 0)
+ iio_trigger_unregister(data->trig);
+
+ return ret;
+}
+
+static int sx9311_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct sx9311_data *data = iio_priv(indio_dev);
+
+ if (client->irq > 0)
+ iio_trigger_unregister(data->trig);
+ kfree(data->buffer);
+ return 0;
+}
+
+static int __maybe_unused sx9311_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret;
+
+ disable_irq_nosync(data->client->irq);
+
+ mutex_lock(&data->mutex);
+ ret = regmap_write(data->regmap, SX9311_REG_PAUSE, 0);
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int __maybe_unused sx9311_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct sx9311_data *data = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&data->mutex);
+ ret = regmap_write(data->regmap, SX9311_REG_PAUSE, 1);
+ mutex_unlock(&data->mutex);
+
+ enable_irq(data->client->irq);
+
+ return ret;
+}
+
+static const struct dev_pm_ops sx9311_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(sx9311_suspend, sx9311_resume)
+};
+
+static const struct acpi_device_id sx9311_acpi_match[] = {
+ {SX9311_ACPI_NAME, 0},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, sx9311_acpi_match);
+
+static const struct of_device_id sx9311_of_match[] = {
+ { .compatible = "semtech," SX9311_DRIVER_NAME, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sx9311_of_match);
+
+static const struct i2c_device_id sx9311_id[] = {
+ {SX9311_DRIVER_NAME, 0},
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, sx9311_id);
+
+static struct i2c_driver sx9311_driver = {
+ .driver = {
+ .name = SX9311_DRIVER_NAME,
+ .acpi_match_table = ACPI_PTR(sx9311_acpi_match),
+ .of_match_table = of_match_ptr(sx9311_of_match),
+ .pm = &sx9311_pm_ops,
+ },
+ .probe = sx9311_probe,
+ .remove = sx9311_remove,
+ .id_table = sx9311_id,
+};
+module_i2c_driver(sx9311_driver);
+
+MODULE_AUTHOR("Phoenix Wu <wujing6@huaqin.corp-partner.google.com>");
+MODULE_DESCRIPTION("Driver for Semtech SX9311 proximity sensor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index b91f2679945c..6a4eaddaa530 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2460,7 +2460,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_hif_stop;
}
- status = ath10k_hif_swap_mailbox(ar);
+ status = ath10k_hif_swap_mailbox(ar, mode);
if (status) {
ath10k_err(ar, "failed to swap mailbox: %d\n", status);
goto err_hif_stop;
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 5f7f1e08866f..5c342a1a2b9a 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -59,7 +59,7 @@ struct ath10k_hif_ops {
*/
void (*stop)(struct ath10k *ar);
- int (*swap_mailbox)(struct ath10k *ar);
+ int (*swap_mailbox)(struct ath10k *ar, enum ath10k_firmware_mode mode);
int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
u8 *ul_pipe, u8 *dl_pipe);
@@ -141,10 +141,10 @@ static inline void ath10k_hif_stop(struct ath10k *ar)
return ar->hif.ops->stop(ar);
}
-static inline int ath10k_hif_swap_mailbox(struct ath10k *ar)
+static inline int ath10k_hif_swap_mailbox(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
if (ar->hif.ops->swap_mailbox)
- return ar->hif.ops->swap_mailbox(ar);
+ return ar->hif.ops->swap_mailbox(ar, mode);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 7beac869bf58..e16691b75a3b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1640,7 +1640,7 @@ static int ath10k_sdio_hif_diag_write_mem(struct ath10k *ar, u32 address,
return 0;
}
-static int ath10k_sdio_hif_swap_mailbox(struct ath10k *ar)
+static int ath10k_sdio_hif_swap_mailbox(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
u32 addr, val;
@@ -1663,7 +1663,8 @@ static int ath10k_sdio_hif_swap_mailbox(struct ath10k *ar)
"sdio mailbox swap service disabled\n");
ar_sdio->swap_mbox = false;
}
-
+ if(mode == ATH10K_FIRMWARE_MODE_UTF)
+ ar_sdio->swap_mbox = false;
return 0;
}
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index 3eaa37cefb90..b8adb9c53c69 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -621,7 +621,6 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
temp = raw_to_mcelsius(mt,
conf->bank_data[bank->id].sensors[i],
raw);
-
/*
* The first read of a sensor often contains very high bogus
* temperature value. Filter these out so that the system does
@@ -633,7 +632,6 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
if (temp > max)
max = temp;
}
-
return max;
}
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 8c738c0e6e9f..e136e3a3c996 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -37,6 +37,8 @@ struct display_timing;
* struct drm_panel_funcs - perform operations on a given panel
* @disable: disable panel (turn off back light, etc.)
* @unprepare: turn off panel
+ * @detach: detach panel->connector (clear internal state, etc.)
+ * @attach: attach panel->connector (update internal state, etc.)
* @prepare: turn on panel and perform set up
* @enable: enable panel (turn on back light, etc.)
* @get_modes: add modes to the connector that the panel is attached to and
@@ -70,6 +72,8 @@ struct display_timing;
struct drm_panel_funcs {
int (*disable)(struct drm_panel *panel);
int (*unprepare)(struct drm_panel *panel);
+ void (*detach)(struct drm_panel *panel);
+ int (*attach)(struct drm_panel *panel);
int (*prepare)(struct drm_panel *panel);
int (*enable)(struct drm_panel *panel);
int (*get_modes)(struct drm_panel *panel);
@@ -197,11 +201,18 @@ int drm_panel_detach(struct drm_panel *panel);
#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL)
struct drm_panel *of_drm_find_panel(const struct device_node *np);
+int of_drm_get_panel_orientation(const struct device_node *np,
+ int *orientation);
#else
static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
{
return ERR_PTR(-ENODEV);
}
+int of_drm_get_panel_orientation(const struct device_node *np,
+ int *orientation)
+{
+ return -ENODEV;
+}
#endif
#endif
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index 9aac1fda94c8..cfecbdaa5853 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -69,12 +69,54 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
return 0;
}
+static const char * const ext_spk_text[] = {
+ "Off", "On"
+};
+
+static const struct soc_enum ext_spk_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(ext_spk_text), ext_spk_text);
+
+
+static const struct snd_kcontrol_new ext_spk_mux =
+ SOC_DAPM_ENUM("Ext Spk Switch Mux", ext_spk_enum);
+
+
+static int max98357a_enable_spk_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct max98357a_priv *max98357a = snd_soc_component_get_drvdata(cmpnt);
+
+ if (!max98357a->sdmode)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ queue_delayed_work(system_power_efficient_wq,
+ &max98357a->enable_sdmode_work,
+ msecs_to_jiffies(max98357a->sdmode_delay));
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ cancel_delayed_work(&max98357a->enable_sdmode_work);
+ gpiod_set_value(max98357a->sdmode, 0);
+ break;
+ }
+ return 0;
+}
+
static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("Speaker"),
+ SND_SOC_DAPM_SPK("Spk PA", max98357a_enable_spk_pa),
+ SND_SOC_DAPM_MUX("Spk PA Switch", SND_SOC_NOPM, 0, 0,
+ &ext_spk_mux),
};
static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
{"Speaker", NULL, "HiFi Playback"},
+ {"Speaker", NULL, "Spk PA"},
+ {"Spk PA", NULL, "Spk PA Switch"},
+ {"Spk PA Switch", "On", "HiFi Playback1"},
};
static int max98357a_component_probe(struct snd_soc_component *component)
@@ -119,23 +161,43 @@ static const struct snd_soc_dai_ops max98357a_dai_ops = {
.trigger = max98357a_daiops_trigger,
};
-static struct snd_soc_dai_driver max98357a_dai_driver = {
- .name = "HiFi",
- .playback = {
- .stream_name = "HiFi Playback",
- .formats = SNDRV_PCM_FMTBIT_S16 |
- SNDRV_PCM_FMTBIT_S24 |
- SNDRV_PCM_FMTBIT_S32,
- .rates = SNDRV_PCM_RATE_8000 |
- SNDRV_PCM_RATE_16000 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_96000,
- .rate_min = 8000,
- .rate_max = 96000,
- .channels_min = 1,
- .channels_max = 2,
+static struct snd_soc_dai_driver max98357a_dai_driver[] = {
+ {
+ .name = "HiFi",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .formats = SNDRV_PCM_FMTBIT_S16 |
+ SNDRV_PCM_FMTBIT_S24 |
+ SNDRV_PCM_FMTBIT_S32,
+ .rates = SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &max98357a_dai_ops,
+ },
+ {
+ .name = "max98357a-hifi",
+ .playback = {
+ .stream_name = "HiFi Playback1",
+ .formats = SNDRV_PCM_FMTBIT_S16 |
+ SNDRV_PCM_FMTBIT_S24 |
+ SNDRV_PCM_FMTBIT_S32,
+ .rates = SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = NULL,
},
- .ops = &max98357a_dai_ops,
};
static int max98357a_platform_probe(struct platform_device *pdev)
@@ -161,7 +223,7 @@ static int max98357a_platform_probe(struct platform_device *pdev)
return devm_snd_soc_register_component(&pdev->dev,
&max98357a_component_driver,
- &max98357a_dai_driver, 1);
+ max98357a_dai_driver, ARRAY_SIZE(max98357a_dai_driver));
}
static int max98357a_platform_remove(struct platform_device *pdev)
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
old mode 100644
new mode 100755
index c978938292bb..f9eb3229a578
--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
@@ -22,7 +22,7 @@ static struct snd_soc_dai_link_component
mt8183_da7219_max98357_external_codecs[] = {
{
.name = "max98357a",
- .dai_name = "HiFi",
+ .dai_name = "max98357a-hifi",
},
{
.name = "da7219.5-001a",
--
2.20.1