| 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, ®06);
|
| + dptxrd(it6505, 0x07, ®07);
|
| + dptxrd(it6505, 0x08, ®08);
|
| + dptxrd(it6505, 0x0d, ®0d);
|
| + dptxrd(it6505, 0x0e, ®0e);
|
| +
|
| + 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, ®0D);
|
| + 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, ®0D);
|
| + 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, ®0D);
|
| + if (reg0D & BIT(1))
|
| + dptx_sys_chg(ctx, SYS_HPD);
|
| + else
|
| + dptx_sys_chg(ctx, SYS_UNPLUG);
|
| +
|
| + dptxrd(ctx, 0x9F, ®9F);
|
| + 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, ®0D);
|
| +
|
| + 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, ®9F);
|
| + 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, ®55);
|
| + 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, ®55);
|
| + 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, ®06);
|
| + dptxrd(it6505, 0x07, ®07);
|
| + dptxrd(it6505, 0x08, ®08);
|
| + dptxrd(it6505, 0x0D, ®0d);
|
| +
|
| + 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, ®val, 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, ®val); |
| + |
| + 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 |
| |