diff --git a/config/boards/clockworkpi-a06.conf b/config/boards/clockworkpi-a06.conf new file mode 100644 index 000000000..9414544b8 --- /dev/null +++ b/config/boards/clockworkpi-a06.conf @@ -0,0 +1,7 @@ +# Rockchip RK3399 hexa core 4GB RAM SoC WiFi/BT +BOARD_NAME="Clockworkpi A06" +BOARDFAMILY="rockchip64" +BOOTCONFIG="clockworkpi-a06-rk3399_defconfig" +KERNEL_TARGET="legacy,current,edge" +FULL_DESKTOP="yes" +BOOT_LOGO="no" diff --git a/config/kernel/linux-rockchip64-current.config b/config/kernel/linux-rockchip64-current.config index d5c63f5b2..5c3cb6e93 100644 --- a/config/kernel/linux-rockchip64-current.config +++ b/config/kernel/linux-rockchip64-current.config @@ -4574,8 +4574,8 @@ CONFIG_MFD_AAT2870_CORE=y # CONFIG_MFD_BCM590XX is not set # CONFIG_MFD_BD9571MWV is not set CONFIG_MFD_AC100=m -CONFIG_MFD_AXP20X=m -# CONFIG_MFD_AXP20X_I2C is not set +CONFIG_MFD_AXP20X=y +CONFIG_MFD_AXP20X_I2C=y CONFIG_MFD_AXP20X_RSB=m CONFIG_MFD_CROS_EC_DEV=y # CONFIG_MFD_MADERA is not set @@ -4700,7 +4700,7 @@ CONFIG_REGULATOR_AAT2870=m CONFIG_REGULATOR_AS3711=m CONFIG_REGULATOR_AS3722=m CONFIG_REGULATOR_ATC260X=m -CONFIG_REGULATOR_AXP20X=m +CONFIG_REGULATOR_AXP20X=y CONFIG_REGULATOR_BD71815=m CONFIG_REGULATOR_BD71828=m CONFIG_REGULATOR_BD957XMUF=m @@ -5686,6 +5686,7 @@ CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m # CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set CONFIG_DRM_PANEL_WIDECHIPS_WS2401=m CONFIG_DRM_PANEL_XINPENG_XPP055C272=m +CONFIG_DRM_PANEL_CWD686=m # end of Display Panels CONFIG_DRM_BRIDGE=y @@ -5873,6 +5874,7 @@ CONFIG_BACKLIGHT_GPIO=m # CONFIG_BACKLIGHT_ARCXCNN is not set CONFIG_BACKLIGHT_RAVE_SP=m CONFIG_BACKLIGHT_LED=m +CONFIG_BACKLIGHT_OCP8178=m # end of Backlight & LCD device support CONFIG_VIDEOMODE_HELPERS=y @@ -6173,6 +6175,7 @@ CONFIG_SND_SOC_HDMI_CODEC=m CONFIG_SND_SOC_ES7134=m CONFIG_SND_SOC_ES7241=m CONFIG_SND_SOC_ES8316=m +CONFIG_SND_SOC_ES8323=m CONFIG_SND_SOC_ES8328=m CONFIG_SND_SOC_ES8328_I2C=m CONFIG_SND_SOC_ES8328_SPI=m diff --git a/config/sources/families/include/rockchip64_common.inc b/config/sources/families/include/rockchip64_common.inc index 0485cbcfb..d7361ded1 100644 --- a/config/sources/families/include/rockchip64_common.inc +++ b/config/sources/families/include/rockchip64_common.inc @@ -17,7 +17,7 @@ PACKAGE_LIST_FAMILY="ethtool" RKBIN_DIR="$SRC/cache/sources/rkbin-tools" #BOOT_SOC=`expr $BOOTCONFIG : '.*\(rk[[:digit:]]\+.*\)_.*'` -BOOT_SOC=${BOOT_SOC:=`expr $BOOTCONFIG : '.*\(rk[[:digit:]]\+.*\)_.*'`} +BOOT_SOC=${BOOT_SOC:=$(expr $BOOTCONFIG : '.*\(rk[[:digit:]]\+.*\)_.*')} CPUMIN=${CPUMIN:="408000"} @@ -89,29 +89,28 @@ fi case $BRANCH in - current) +current) - KERNELBRANCH="branch:linux-5.15.y" - KERNELBRANCH="tag:v5.15.35" - KERNELPATCHDIR='rockchip64-'$BRANCH - LINUXFAMILY=rockchip64 - LINUXCONFIG='linux-rockchip64-'$BRANCH + KERNELBRANCH="branch:linux-5.15.y" + KERNELBRANCH="tag:v5.15.35" + KERNELPATCHDIR='rockchip64-'$BRANCH + LINUXFAMILY=rockchip64 + LINUXCONFIG='linux-rockchip64-'$BRANCH ;; - edge) +edge) - KERNELPATCHDIR='rockchip64-'$BRANCH - KERNELBRANCH="branch:linux-5.17.y" - KERNELBRANCH="tag:v5.17.5" - LINUXFAMILY=rockchip64 - LINUXCONFIG='linux-rockchip64-'$BRANCH + KERNELPATCHDIR='rockchip64-'$BRANCH + KERNELBRANCH="branch:linux-5.17.y" + KERNELBRANCH="tag:v5.17.5" + LINUXFAMILY=rockchip64 + LINUXCONFIG='linux-rockchip64-'$BRANCH ;; esac -prepare_boot_configuration() -{ +prepare_boot_configuration() { if [[ $BOOT_SCENARIO == "blobless" ]]; then UBOOT_TARGET_MAP="BL31=bl31.bin idbloader.img u-boot.itb;;idbloader.img u-boot.itb" @@ -150,8 +149,7 @@ prepare_boot_configuration() fi } -uboot_custom_postprocess() -{ +uboot_custom_postprocess() { if [[ $BOOT_SCENARIO == "blobless" || $BOOT_SCENARIO == "tpl-spl-blob" ]]; then : @@ -163,7 +161,7 @@ uboot_custom_postprocess() local tempfile=$(mktemp) tools/mkimage -n $BOOT_SOC -T rksd -d $RKBIN_DIR/$DDR_BLOB idbloader.bin - cat $RKBIN_DIR/$MINILOADER_BLOB >> idbloader.bin + cat $RKBIN_DIR/$MINILOADER_BLOB >>idbloader.bin $PKG_PREFIX$RKBIN_DIR/tools/loaderimage --pack --uboot ./u-boot-dtb.bin uboot.img 0x200000 $PKG_PREFIX$RKBIN_DIR/tools/trust_merger --replace bl31.elf $RKBIN_DIR/$BL31_BLOB trust.ini @@ -180,8 +178,7 @@ uboot_custom_postprocess() fi } -write_uboot_platform() -{ +write_uboot_platform() { if [[ -f $1/rksd_loader.img ]]; then # legacy rk3399 loader dd if=$1/rksd_loader.img of=$2 seek=64 conv=notrunc status=none >/dev/null 2>&1 @@ -204,8 +201,7 @@ write_uboot_platform() fi } -write_uboot_platform_mtd() -{ +write_uboot_platform_mtd() { if [[ -f $1/rkspi_loader.img ]]; then dd if=$1/rkspi_loader.img of=$2 conv=notrunc status=none >/dev/null 2>&1 @@ -218,8 +214,7 @@ write_uboot_platform_mtd() fi } -setup_write_uboot_platform() -{ +setup_write_uboot_platform() { if grep -q "ubootpart" /proc/cmdline; then @@ -234,8 +229,7 @@ setup_write_uboot_platform() } -family_tweaks() -{ +family_tweaks() { if [[ $BOARD == z28pro ]]; then @@ -245,7 +239,7 @@ family_tweaks() # rename USB based network to lan0 mkdir -p $SDCARD/etc/udev/rules.d/ - echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="r8152", KERNEL=="eth1", NAME="lan0"' > $SDCARD/etc/udev/rules.d/70-rename-lan.rules + echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="r8152", KERNEL=="eth1", NAME="lan0"' >$SDCARD/etc/udev/rules.d/70-rename-lan.rules elif [[ $BOARD == helios64 ]]; then @@ -268,8 +262,8 @@ family_tweaks() if [[ $BOARD == pinebook-pro ]]; then - chroot $SDCARD /bin/bash -c "echo SuspendState=freeze >> /etc/systemd/sleep.conf" - chroot $SDCARD /bin/bash -c "echo HandlePowerKey=ignore >> /etc/systemd/login.d" + chroot $SDCARD /bin/bash -c "echo SuspendState=freeze >> /etc/systemd/sleep.conf" + chroot $SDCARD /bin/bash -c "echo HandlePowerKey=ignore >> /etc/systemd/login.d" fi if [[ $BOARD == station* ]]; then @@ -281,29 +275,59 @@ family_tweaks() cp $SRC/packages/blobs/rtl8723bt_fw/rtl8723ds_fw.bin $SDCARD/lib/firmware/rtlbt/rtl8723d_fw install -m 755 $SRC/packages/bsp/rk3328/m1/rtk_hciattach $SDCARD/usr/bin/rtk_hciattach sed -e 's/exit 0//g' -i $SDCARD/etc/rc.local - echo "su -c '/usr/bin/rtk_hciattach -n -s 115200 /dev/ttyS2 rtk_h5 &'" >> $SDCARD/etc/rc.local - echo "exit 0" >> $SDCARD/etc/rc.local + echo "su -c '/usr/bin/rtk_hciattach -n -s 115200 /dev/ttyS2 rtk_h5 &'" >>$SDCARD/etc/rc.local + echo "exit 0" >>$SDCARD/etc/rc.local fi fi } - -family_tweaks_bsp() -{ +family_tweaks_bsp() { if [[ $BOOTCONFIG == *3328* ]] && [[ $BRANCH != legacy ]]; then mkdir -p "$destination"/etc/X11/xorg.conf.d - cat <<-EOF > "$destination"/etc/X11/xorg.conf.d/02-driver.conf - # set fbdev as default driver. - Section "Device" - Identifier "NOGPU" - Driver "fbdev" - EndSection + cat <<-EOF >"$destination"/etc/X11/xorg.conf.d/02-driver.conf + # set fbdev as default driver. + Section "Device" + Identifier "NOGPU" + Driver "fbdev" + EndSection EOF fi + if [[ $BOARD == clockworkpi-a06 ]]; then + # rotate screen & disable dpms + mkdir -p "$destination"/etc/X11/xorg.conf.d + cat <<-EOF >"$destination"/etc/X11/xorg.conf.d/10-monitor.conf + # set monitor + Section "Monitor" + Identifier "DSI-1" + Option "Rotate" "right" + Option "DPMS" "false" + EndSection + + Section "ServerLayout" + Identifier "ServerLayout0" + Option "BlankTime" "0" + Option "StandbyTime" "0" + Option "SuspendTime" "0" + Option "OffTime" "0" + EndSection + EOF + # fan support + install -Dm644 $SRC/packages/bsp/clockworkpi-a06/temp_fan_daemon_a06.py $destination/usr/share/clockworkpi-a06-fan-daemon/bin/temp_fan_daemon_a06.py + cp $SRC/packages/bsp/clockworkpi-a06/clockworkpi-a06-fan-daemon.service $destination/lib/systemd/system/ + + # alsa-ucm-conf profile for DevTerm A06 + mkdir -p $destination/usr/share/alsa/ucm2/Rockchip/es8388 + install -Dm644 $SRC/packages/bsp/clockworkpi-a06/es8388.conf $destination/usr/share/alsa/ucm2/Rockchip/es8388/es8388.conf + install -Dm644 $SRC/packages/bsp/clockworkpi-a06/HiFi.conf $destination/usr/share/alsa/ucm2/Rockchip/es8388/HiFi.conf + mkdir -p $destination/usr/share/alsa/ucm2/conf.d/simple-card + ln -sfv /usr/share/alsa/ucm2/Rockchip/es8388/es8388.conf \ + $destination/usr/share/alsa/ucm2/conf.d/simple-card/rockchip,es8388-codec.conf + fi + if [[ $BOARD == z28pro ]]; then mkdir -p $destination/usr/local/bin @@ -372,7 +396,7 @@ family_tweaks_bsp() # special keys mkdir -p "${destination}"/etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/ - cp $SRC/packages/bsp/pinebook-pro/pointers.xml "${destination}"/etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/ + cp $SRC/packages/bsp/pinebook-pro/pointers.xml "${destination}"/etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/ # touchpad and keyboard tweaks mkdir -p "${destination}"/etc/X11/xorg.conf.d/ diff --git a/config/targets.conf b/config/targets.conf index bfc7f5e72..0c9113dad 100644 --- a/config/targets.conf +++ b/config/targets.conf @@ -34,6 +34,11 @@ bananapim64 current focal cli s bananapim64 current focal desktop stable adv xfce config_base 3dsupport,browsers,chat,desktop_tools,editors,email,internet,multimedia,office,programming,remote_desktop bananapim64 edge jammy cli stable yes +# clockworkpi-a06 +clockworkpi-a06 current bullseye cli stable yes +clockworkpi-a06 current jammy cli stable yes +clockworkpi-a06 current bullseye desktop stable adv xfce config_base browsers,chat,desktop_tools,editors,email,internet,multimedia,office,programming,remote_desktop +clockworkpi-a06 current jammy desktop stable adv xfce config_base 3dsupport,browsers,chat,desktop_tools,editors,email,internet,multimedia,office,programming,remote_desktop # EspressoBIN espressobin current bullseye cli stable adv diff --git a/packages/bsp/clockworkpi-a06/HiFi.conf b/packages/bsp/clockworkpi-a06/HiFi.conf new file mode 100644 index 000000000..994317f1a --- /dev/null +++ b/packages/bsp/clockworkpi-a06/HiFi.conf @@ -0,0 +1,48 @@ +SectionDevice."Speaker" { + Comment "Speaker" + + ConflictingDevice [ + "Headphones" + ] + + EnableSequence [ + cset "name='Speaker Switch' on" + ] + + DisableSequence [ + cset "name='Speaker Switch' off" + ] + + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId},0" + } +} + +SectionDevice."Mic" { + Comment "Headphone Mic" + + EnableSequence [ + cset "name='Differential Mux' 'Line 2'" + ] + + Value { + CapturePriority 100 + CapturePCM "hw:${CardId},0" + } +} + +SectionDevice."Headphones" { + Comment "Headphones" + + ConflictingDevice [ + "Speaker" + ] + + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId},0" + JackControl "Headphones Jack" + JackHWMute "Speaker" + } +} diff --git a/packages/bsp/clockworkpi-a06/clockworkpi-a06-fan-daemon.service b/packages/bsp/clockworkpi-a06/clockworkpi-a06-fan-daemon.service new file mode 100644 index 000000000..dca0751bb --- /dev/null +++ b/packages/bsp/clockworkpi-a06/clockworkpi-a06-fan-daemon.service @@ -0,0 +1,9 @@ +[Unit] +Description=ClockworkPi DevTerm A06 fan control daemon + +[Service] +Type=simple +ExecStart=/usr/bin/python3 /usr/share/clockworkpi-a06-fan-daemon/bin/temp_fan_daemon_a06.py + +[Install] +WantedBy=multi-user.target diff --git a/packages/bsp/clockworkpi-a06/es8388.conf b/packages/bsp/clockworkpi-a06/es8388.conf new file mode 100644 index 000000000..303e38bcf --- /dev/null +++ b/packages/bsp/clockworkpi-a06/es8388.conf @@ -0,0 +1,44 @@ +Syntax 3 + +SectionUseCase."HiFi" { + File "/Rockchip/es8388/HiFi.conf" + Comment "Play HiFi quality Music" +} + +BootSequence [ + # Disable all outputs + cset "name='Speaker Switch' off" + + # Set Route to Stereo + cset "name='Route' Stereo" + + # Set vol to 0 dB (28/32) + cset "name='Output 1 Playback Volume' 28" + cset "name='Output 2 Playback Volume' 28" + # Set mixer vol to 0 dB + cset "name='Left Mixer Left Bypass Volume' 6" + cset "name='Left Mixer Right Bypass Volume' 6" + cset "name='Right Mixer Left Bypass Volume' 6" + cset "name='Right Mixer Right Bypass Volume' 6" + # Set DAC vol to 0 dB (192/192) + cset "name='PCM Volume' 192" + + cset "name='Capture ZC Switch' off" + cset "name='DAC Deemphasis Switch' off" + # Set ADC vol to 0 dB (192/192) + cset "name='Capture Digital Volume' 192" + # Set Mic amplifier to +15 dB + cset "name='Mic PGA Volume' 5" + + # Set Line Muxes to PGA + cset "name='Left Line Mux' PGA" + cset "name='Right Line Mux' PGA" + + # Set PGA Muxes to Differential + cset "name='Left PGA Mux' Differential" + cset "name='Right PGA Mux' Differential" + + # Setup muxes / switches + cset "name='Left Mixer Playback Switch' on" + cset "name='Right Mixer Playback Switch' on" +] diff --git a/packages/bsp/clockworkpi-a06/temp_fan_daemon_a06.py b/packages/bsp/clockworkpi-a06/temp_fan_daemon_a06.py new file mode 100755 index 000000000..1a753721e --- /dev/null +++ b/packages/bsp/clockworkpi-a06/temp_fan_daemon_a06.py @@ -0,0 +1,135 @@ +#!/usr/bin/python3 +# source: https://github.com/clockworkpi/DevTerm/tree/main/Code/devterm_fan_daemon_cpi_a06 + +import glob +import os +import sys +import getopt +import subprocess +import time + +cpus = [] +mid_freq = 0 +max_freq = 0 + +# Replace fan-on temperature w/ 55C, rather than 70C which doesn't seem to be enough to avoid overheating +MAX_TEMP = 55000 +ONCE_TIME = 30 + + +def init_fan_gpio(): + os.popen("gpio mode 41 out") + + +def fan_on(): + init_fan_gpio() + os.popen("gpio write 41 1") + time.sleep(ONCE_TIME) + + +def fan_off(): + init_fan_gpio() + os.popen("gpio write 41 0") + + +def isDigit(x): + try: + float(x) + return True + except ValueError: + return False + + +def cpu_infos(): + global cpus + global mid_freq + global max_freq + + cpus = glob.glob('/sys/devices/system/cpu/cpu[0-9]') + cpus.sort() +# /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies +# /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor + + scaling_available_freq = open(os.path.join( + cpus[0], "cpufreq/scaling_available_frequencies"), "r").read() + scaling_available_freq = scaling_available_freq.strip("\n") + scaling_available_freqs = scaling_available_freq.split(" ") + + for var in scaling_available_freqs: + if isDigit(var): + if(int(var) > 1000000): + if(mid_freq == 0): + mid_freq = int(var) + max_freq = int(var) + + +def set_gov(gov): + global cpus + for var in cpus: + gov_f = os.path.join(var, "cpufreq/scaling_governor") + # print(gov_f) + subprocess.run("echo %s | sudo tee %s" % (gov, gov_f), shell=True) + + +def set_performance(scale): + global cpus + global mid_freq + global max_freq + + freq = mid_freq + if scale == "mid": + freq = mid_freq + elif scale == "max": + freq = max_freq + + for var in cpus: + _f = os.path.join(var, "cpufreq/scaling_max_freq") + # print(_f) + subprocess.run("echo %s | sudo tee %s" % (freq, _f), shell=True) + + +def fan_loop(): + while True: + temps = glob.glob('/sys/class/thermal/thermal_zone[0-9]/') + temps.sort() + for var in temps: + _f = os.path.join(var, "temp") + #print( open(_f).read().strip("\n") ) + _t = open(_f).read().strip("\n") + if isDigit(_t): + if int(_t) > MAX_TEMP: + fan_on() + fan_off() + + time.sleep(5) + + +def main(argv): + global cpus + scale = 'mid' + gov = 'powersave' + try: + opts, args = getopt.getopt(argv, "hs:g:", ["scale=", "governor="]) + except getopt.GetoptError: + print('test.py -s -g ') + sys.exit(2) + for opt, arg in opts: + if opt == '-h': + print('test.py -s ') + sys.exit() + elif opt in ("-s", "--scale"): + scale = arg + elif opt in ("-g", "--governor"): + gov = arg + + print('Scale is ', scale, "Gov is ", gov) + + init_fan_gpio() + cpu_infos() + set_gov(gov) + set_performance(scale) + fan_loop() + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0001-dts.patch b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0001-dts.patch new file mode 100644 index 000000000..ea6de238b --- /dev/null +++ b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0001-dts.patch @@ -0,0 +1,995 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-clockworkpi-a06.dts b/arch/arm64/boot/dts/rockchip/rk3399-clockworkpi-a06.dts +new file mode 100644 +index 000000000000..1c8fb451a27e +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-clockworkpi-a06.dts +@@ -0,0 +1,989 @@ ++/* ++ * SPDX-License-Identifier: (GPL-2.0+ or MIT) ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. ++ * Copyright (c) 2018 Akash Gajjar ++ * Copyright (c) 2020 Armbian (chwe17, piter75) ++ * Copyright (c) 2021 Clockwork Tech LLC ++ * Copyright (c) 2021 Max Fierke ++ * Copyright (c) 2022 CXM ++ * ++ */ ++ ++/dts-v1/; ++#include ++#include ++#include ++#include "rk3399.dtsi" ++#include "rk3399-opp.dtsi" ++ ++/ { ++ model = "Clockworkpi A06"; ++ compatible = "clockwork,devterm-a06", "rockchip,rk3399"; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ aliases { ++ spi1 = &spi1; ++ }; ++ ++ usb_vbus: usb-vbus { ++ compatible = "regulator-fixed"; ++ regulator-name = "usb_vbus"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ usb3_vbus: usb3-vbus { ++ compatible = "regulator-fixed"; ++ regulator-name = "usb3_vbus"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc3v0_sd: vcc3v0-sd { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_pwr_h>; ++ regulator-name = "vcc3v0_sd"; ++ regulator-always-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ vin-supply = <&vcc3v3_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_sys>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vdd_log: vdd-log { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm2 0 25000 1>; ++ regulator-name = "vdd_log"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc3v3_sys>; ++ }; ++ ++ dw_hdmi_audio: dw-hdmi-audio { ++ status = "disable"; ++ compatible = "rockchip,dw-hdmi-audio"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ hdmi_sound: hdmi-sound { ++ status = "okay"; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ clocks = <&rk808 1>; ++ clock-names = "ext_clock"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; ++ }; ++ ++ es8388-sound { ++ status = "okay"; ++ compatible = "simple-audio-card"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hp_det>; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "rockchip,es8388-codec"; ++ simple-audio-card,mclk-fs = <256>; ++ simple-audio-card,widgets = ++ "Headphone Mic", "Mic Jack", ++ "Headphone", "Headphones", ++ "Speaker", "Speaker"; ++ simple-audio-card,routing = ++ "LINPUT2", "Mic Jack", ++ "RINPUT2", "Mic Jack", ++ "Mic Jack", "Mic Bias", ++ "Headphones", "LOUT2", ++ "Headphones", "ROUT2", ++ "Speaker Amplifier INL", "LOUT2", ++ "Speaker Amplifier INR", "ROUT2", ++ "Speaker", "Speaker Amplifier OUTL", ++ "Speaker", "Speaker Amplifier OUTR"; ++ ++ simple-audio-card,hp-det-gpio = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>; ++ simple-audio-card,aux-devs = <&speaker_amp>; ++ simple-audio-card,pin-switches = "Speaker"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ system-clock-frequency = <11289600>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&es8388>; ++ system-clock-frequency = <11289600>; ++ }; ++ }; ++ ++ speaker_amp: speaker-amplifier { ++ compatible = "simple-audio-amplifier"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pa_en>; ++ enable-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>; ++ sound-name-prefix = "Speaker Amplifier"; ++ VCC-supply = <&vcc5v0_sys>; ++ }; ++ ++ battery: battery@0 { ++ compatible = "simple-battery"; ++ constant-charge-current-max-microamp = <2100000>; ++ voltage-min-design-microvolt = <3300000>; ++ }; ++ ++ ocp8178_backlight: backlight@0 { ++ compatible = "ocp8178-backlight"; ++ backlight-control-gpios = <&gpio4 RK_PD6 GPIO_ACTIVE_HIGH>; ++ default-brightness = <5>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&backlight_control>; ++ }; ++ ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l1 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l2 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l3 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_b1 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&vopl { ++ status = "okay"; ++}; ++ ++&vopl_mmu { ++ status = "okay"; ++}; ++ ++&vpu { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_gpu>; ++}; ++ ++&rga { ++ status = "disabled"; ++}; ++ ++&hdmi_in_vopb { ++ status = "okay"; ++}; ++ ++&hdmi_in_vopl { ++ status = "disable"; ++}; ++ ++&mipi_in_vopb { ++ status = "disable"; ++}; ++ ++&mipi_in_vopl { ++ status = "okay"; ++}; ++ ++&hdmi { ++ /* remove the hdmi_i2c_xfer */ ++ pinctrl-0 = <&hdmi_cec>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; ++ status = "okay"; ++ ddc-i2c-bus = <&i2c3>; ++ rockchip,defaultmode = <16>; /* CEA 1920x1080@60Hz */ ++}; ++ ++&mipi_dsi { ++ status = "okay"; ++ ++ ports { ++ mipi_out: port@1 { ++ reg = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ mipi_dsi_out: endpoint { ++ remote-endpoint = <&panel_in>; ++ }; ++ }; ++ }; ++ ++ dsi_panel: panel { ++ compatible = "cw,cwd686"; ++ reg = <0>; ++ backlight = <&ocp8178_backlight>; ++ reset-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>; ++ rotation = <90>; ++ dsi,lanes = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&panel_reset>; ++ status = "okay"; ++ ++ port { ++ panel_in: endpoint { ++ remote-endpoint = <&mipi_dsi_out>; ++ }; ++ }; ++ }; ++ ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm4345c5"; ++ clocks = <&rk808 1>; ++ clock-names = "lpo"; ++ device-wakeup-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>; ++ host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; ++ shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; ++ max-speed = <1500000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_host_wake &bt_wake &bt_reset>; ++ }; ++ ++}; ++ ++/* ++&uart2 { ++ status = "okay"; ++}; ++*/ ++ ++&i2c0 { ++ clock-frequency = <400000>; ++ i2c-scl-rising-time-ns = <168>; ++ i2c-scl-falling-time-ns = <4>; ++ status = "okay"; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <21 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk808-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ wakeup-source; ++ ++ vcc1-supply = <&vcc3v3_sys>; ++ vcc2-supply = <&vcc3v3_sys>; ++ vcc3-supply = <&vcc3v3_sys>; ++ vcc4-supply = <&vcc3v3_sys>; ++ vcc6-supply = <&vcc3v3_sys>; ++ vcc7-supply = <&vcc3v3_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc3v3_sys>; ++ vcc10-supply = <&vcc3v3_sys>; ++ vcc11-supply = <&vcc3v3_sys>; ++ vcc12-supply = <&vcc3v3_sys>; ++ vcc13-supply = <&vcc3v3_sys>; ++ vcc14-supply = <&vcc3v3_sys>; ++ vddio-supply = <&vcc_3v0>; ++ ++ regulators { ++ vdd_center: DCDC_REG1 { ++ regulator-name = "vdd_center"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_l: DCDC_REG2 { ++ regulator-name = "vdd_cpu_l"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc1v8: vcc1v8_s3: vcca1v8_s3: DCDC_REG4 { ++ regulator-name = "vcc1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc1v8_dvp: LDO_REG1 { ++ regulator-name = "vcc1v8_dvp"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v0_touch: LDO_REG2 { ++ regulator-name = "vcc3v0_touch"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc1v8_pmu: LDO_REG3 { ++ regulator-name = "vcc1v8_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc_sdio: LDO_REG4 { ++ regulator-name = "vcc_sdio"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-init-microvolt = <3000000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcca3v0_codec: LDO_REG5 { ++ regulator-name = "vcca3v0_codec"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v5: LDO_REG6 { ++ regulator-name = "vcc_1v5"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1500000>; ++ }; ++ }; ++ ++ vcca1v8_codec: LDO_REG7 { ++ regulator-name = "vcca1v8_codec"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v0: LDO_REG8 { ++ regulator-name = "vcc_3v0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc3v3_s3: vcc_lan: SWITCH_REG1 { ++ regulator-name = "vcc3v3_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_s0: SWITCH_REG2 { ++ regulator-name = "vcc3v3_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++ ++ vdd_cpu_b: regulator@40 { ++ compatible = "silergy,syr827"; ++ reg = <0x40>; ++ fcs,suspend-voltage-selector = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vsel1_gpio>; ++ vsel-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>; ++ regulator-compatible = "fan53555-reg"; ++ regulator-name = "vdd_cpu_b"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc3v3_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: regulator@41 { ++ compatible = "silergy,syr828"; ++ reg = <0x41>; ++ fcs,suspend-voltage-selector = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vsel2_gpio>; ++ vsel-gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>; ++ regulator-compatible = "fan53555-reg"; ++ regulator-name = "vdd_gpu"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc3v3_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ i2c-scl-rising-time-ns = <300>; ++ i2c-scl-falling-time-ns = <15>; ++ ++ es8388: es8388@11 { ++ compatible = "everest,es8388", "everest,es8328"; ++ status = "okay"; ++ reg = <0x11>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_switch>; ++ DVDD-supply = <&vcca1v8_codec>; ++ AVDD-supply = <&vcca3v0_codec>; ++ HPVDD-supply = <&vcca3v0_codec>; ++ PVDD-supply = <&vcca1v8_codec>; ++ clock-names = "mclk"; ++ clocks = <&cru SCLK_I2S_8CH_OUT>; ++ #sound-dai-cells = <0>; ++ }; ++}; ++ ++&i2c2 { ++ status = "okay"; ++}; ++ ++&i2c3 { ++ status = "okay"; ++}; ++ ++&i2c5 { ++ status = "okay"; ++ i2c-scl-rising-time-ns = <300>; ++ i2c-scl-falling-time-ns = <15>; ++ ++ axp22x: pmic@34 { ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ compatible = "x-powers,axp221"; ++ reg = <0x34>; ++ interrupt-parent = <&gpio3>; ++ interrupts = <8 8>; ++ irq-gpios = <&gpio3 8 0>; ++ ++ regulators { ++ ++ x-powers,dcdc-freq = <3000>; ++ ++ reg_aldo1: aldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "audio-vdd"; ++ }; ++ ++ reg_aldo2: aldo2 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "display-vcc"; ++ }; ++ ++ reg_aldo3: aldo3 { ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "wifi-vdd"; ++ }; ++ ++ reg_dldo1: dldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "wifi-vcc1"; ++ }; ++ ++ reg_dldo2: dldo2 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "dldo2"; ++ }; ++ ++ reg_dldo3: dldo3 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "dldo3"; ++ }; ++ ++ reg_dldo4: dldo4 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "dldo4"; ++ }; ++ ++ reg_eldo1: eldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "wifi-vcc2"; ++ }; ++ ++ reg_eldo2: eldo2 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "wifi-vcc3"; ++ }; ++ ++ reg_eldo3: eldo3 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "wifi-vcc4"; ++ }; ++ ++ }; ++ ++ battery_power_supply: battery-power-supply { ++ compatible = "x-powers,axp221-battery-power-supply"; ++ monitored-battery = <&battery>; ++ }; ++ ++ ac_power_supply: ac_power_supply { ++ compatible = "x-powers,axp221-ac-power-supply"; ++ }; ++ ++ }; ++}; ++ ++&spi4 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi4_clk &spi4_tx>; ++ ++ spidev0: spidev@0 { ++ compatible = "rockchip,spidev"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ status = "okay"; ++ }; ++}; ++ ++/* <4 RK_PA0 &pcfg_pull_none> is used as i2s_8ch_mclk_pin */ ++&i2s0_8ch_bus { ++ rockchip,pins = ++ <3 RK_PD0 1 &pcfg_pull_none>, ++ <3 RK_PD1 1 &pcfg_pull_none>, ++ <3 RK_PD2 1 &pcfg_pull_none>, ++ <3 RK_PD3 1 &pcfg_pull_none>, ++ <3 RK_PD4 1 &pcfg_pull_none>, ++ <3 RK_PD5 1 &pcfg_pull_none>, ++ <3 RK_PD6 1 &pcfg_pull_none>, ++ <3 RK_PD7 1 &pcfg_pull_none>; ++}; ++ ++&i2s0 { ++ rockchip,i2s-broken-burst-len; ++ rockchip,playback-channels = <8>; ++ rockchip,capture-channels = <8>; ++ pinctrl-0 = <&i2s0_2ch_bus>; ++ status = "okay"; ++}; ++ ++&i2s1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_8ch_mclk_pin>, <&i2s1_2ch_bus>; ++ rockchip,playback-channels = <2>; ++ rockchip,capture-channels = <2>; ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&i2s2 { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ bt656-supply = <&vcc1v8_dvp>; /* bt656_gpio2ab_ms */ ++ audio-supply = <&vcca1v8_codec>; /* audio_gpio3d4a_ms */ ++ sdmmc-supply = <&vcc_sdio>; /* sdmmc_gpio4b_ms */ ++ gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */ ++}; ++ ++&pmu_io_domains { ++ status = "okay"; ++ pmu1830-supply = <&vcc_3v0>; ++}; ++ ++&sdio0 { ++ clock-frequency = <50000000>; ++ clock-freq-min-max = <200000 50000000>; ++ supports-sdio; ++ bus-width = <4>; ++ disable-wp; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ keep-power-in-suspend; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; ++ sd-uhs-sdr104; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc0_det_l>; ++// sd-uhs-sdr104; ++ vmmc-supply = <&vcc3v0_sd>; ++ vqmmc-supply = <&vcc_sdio>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ /* tshut mode 0:CRU 1:GPIO */ ++ rockchip,hw-tshut-mode = <1>; ++ /* tshut polarity 0:LOW 1:HIGH */ ++ rockchip,hw-tshut-polarity = <1>; ++ status = "okay"; ++}; ++ ++&tcphy0 { ++ status = "okay"; ++}; ++ ++&tcphy1 { ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ status = "okay"; ++ ++ u2phy0_otg: otg-port { ++ status = "okay"; ++ }; ++ ++ u2phy0_host: host-port { ++ phy-supply = <&usb3_vbus>; ++ status = "okay"; ++ }; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++ ++ u2phy1_otg: otg-port { ++ status = "okay"; ++ }; ++ ++ u2phy1_host: host-port { ++ phy-supply = <&usb_vbus>; ++ status = "okay"; ++ }; ++}; ++ ++&usbdrd3_0 { ++ status = "okay"; ++}; ++ ++&usbdrd3_1 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_0 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_1 { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ ++ hdmi { ++ /delete-node/ hdmi-i2c-xfer; ++ }; ++ ++ i2s1 { ++ i2s_8ch_mclk_pin: i2s-8ch-mclk-pin { ++ rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ vsel1_gpio: vsel1-gpio { ++ rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ vsel2_gpio: vsel2-gpio { ++ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ sdmmc { ++ sdmmc0_det_l: sdmmc0-det-l { ++ rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ sdmmc0_pwr_h: sdmmc0-pwr-h { ++ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ wireless-bluetooth { ++ uart0_gpios: uart0-gpios { ++ rockchip,pins = <2 19 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ rockchip-key { ++ power_key: power-key { ++ rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ spi1 { ++ spi1_gpio: spi1-gpio { ++ rockchip,pins = ++ <1 7 RK_FUNC_GPIO &pcfg_output_low>, ++ <1 8 RK_FUNC_GPIO &pcfg_output_low>, ++ <1 9 RK_FUNC_GPIO &pcfg_output_low>, ++ <1 10 RK_FUNC_GPIO &pcfg_output_low>; ++ }; ++ }; ++ ++ bt { ++ bt_host_wake: bt-host-wake { ++ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_reset: bt-reset { ++ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_wake: bt-wake { ++ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ panel { ++ panel_reset: panel-reset { ++ rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_output_low>; ++ }; ++ }; ++ ++ backlight { ++ backlight_control: backlight-control { ++ rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_output_low>; ++ }; ++ }; ++ ++ audio { ++ audio_switch: audio-switch { ++ rockchip,pins = <4 RK_PD3 RK_FUNC_GPIO &pcfg_output_high>; ++ }; ++ ++ hp_det: hp-det { ++ rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ pa_en: pa-en { ++ rockchip,pins = <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; diff --git a/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0002-power.patch b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0002-power.patch new file mode 100644 index 000000000..5e7a4dcf8 --- /dev/null +++ b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0002-power.patch @@ -0,0 +1,124 @@ +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index 8161a5dc68e8..ec615b6463cb 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -1000,6 +1000,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) + return ret; + } + ++ pm_power_off = 0; + if (!pm_power_off) { + axp20x_pm_power_off = axp20x; + pm_power_off = axp20x_power_off; +diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c +index 77ccd31ca1d9..2515007b6cad 100644 +--- a/drivers/mfd/rk808.c ++++ b/drivers/mfd/rk808.c +@@ -555,6 +555,12 @@ static void rk808_pm_power_off(void) + dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); + } + ++static void rk808_pm_power_off_prepare(void) ++{ ++ struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); ++ regmap_update_bits(rk808->regmap, RK808_LDO_EN_REG, 0x08, 0x00); ++} ++ + static void rk8xx_shutdown(struct i2c_client *client) + { + struct rk808 *rk808 = i2c_get_clientdata(client); +@@ -724,6 +730,8 @@ static int rk808_probe(struct i2c_client *client, + rk808_i2c_client = client; + pm_power_off = rk808_pm_power_off; + } ++ rk808_i2c_client = client; ++ pm_power_off_prepare = rk808_pm_power_off_prepare; + + return 0; + +diff --git a/drivers/power/supply/axp20x_ac_power.c b/drivers/power/supply/axp20x_ac_power.c +index ac360016b08a..c11024f3c6a1 100644 +--- a/drivers/power/supply/axp20x_ac_power.c ++++ b/drivers/power/supply/axp20x_ac_power.c +@@ -53,6 +53,9 @@ static irqreturn_t axp20x_ac_power_irq(int irq, void *devid) + { + struct axp20x_ac_power *power = devid; + ++ regmap_update_bits(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, 0x03, 0x00); ++ regmap_update_bits(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, 0x03, 0x03); ++ + power_supply_changed(power->supply); + + return IRQ_HANDLED; +diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c +index 335e12cc5e2f..87da705a5831 100644 +--- a/drivers/power/supply/axp20x_battery.c ++++ b/drivers/power/supply/axp20x_battery.c +@@ -325,6 +325,42 @@ static int axp20x_battery_get_prop(struct power_supply *psy, + /* IIO framework gives mV but Power Supply framework gives uV */ + val->intval *= 1000; + break; ++ ++ case POWER_SUPPLY_PROP_ENERGY_FULL: ++ case POWER_SUPPLY_PROP_ENERGY_NOW: ++ /* When no battery is present, return 0 */ ++ ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE, ++ ®); ++ if (ret) ++ return ret; ++ ++ if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) { ++ val->intval = 0; ++ return 0; ++ } ++ ++ if(psp == POWER_SUPPLY_PROP_ENERGY_FULL) { ++ val->intval = 8000000; ++ return 0; ++ } ++ ++ ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, ®); ++ if (ret) ++ return ret; ++ ++ if (axp20x_batt->data->has_fg_valid && !(reg & AXP22X_FG_VALID)) ++ return -EINVAL; ++ ++ val1 = reg & AXP209_FG_PERCENT; ++ if (val1 > 90) ++ val1 = 80; ++ else if (val1 < 10) ++ val1 = 0; ++ else ++ val1 -= 10; ++ ++ val->intval = val1 * 100000; ++ break; + + default: + return -EINVAL; +@@ -497,6 +533,8 @@ static enum power_supply_property axp20x_battery_props[] = { + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_CAPACITY, ++ POWER_SUPPLY_PROP_ENERGY_FULL, ++ POWER_SUPPLY_PROP_ENERGY_NOW, + }; + + static int axp20x_battery_prop_writeable(struct power_supply *psy, +@@ -642,6 +680,12 @@ static int axp20x_power_probe(struct platform_device *pdev) + axp20x_get_constant_charge_current(axp20x_batt, + &axp20x_batt->max_ccc); + ++ regmap_update_bits(axp20x_batt->regmap, AXP20X_VBUS_IPSOUT_MGMT, 0x03, 0x03); ++ regmap_update_bits(axp20x_batt->regmap, AXP20X_OFF_CTRL, 0x08, 0x08); ++ regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL2, 0x30, 0x20); ++ regmap_update_bits(axp20x_batt->regmap, AXP20X_PEK_KEY, 0x0f, 0x0b); ++ regmap_update_bits(axp20x_batt->regmap, AXP20X_GPIO0_CTRL, 0x07, 0x00); ++ + return 0; + } + +-- +2.25.1 + diff --git a/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0003-audio.patch b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0003-audio.patch new file mode 100644 index 000000000..52d03e08b --- /dev/null +++ b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0003-audio.patch @@ -0,0 +1,1326 @@ +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 47e675e8bd00..10ffaae1e4a5 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -92,6 +92,7 @@ config SND_SOC_ALL_CODECS + imply SND_SOC_DA9055 + imply SND_SOC_DMIC + imply SND_SOC_ES8316 ++ imply SND_SOC_ES8323 + imply SND_SOC_ES8328_SPI + imply SND_SOC_ES8328_I2C + imply SND_SOC_ES7134 +@@ -825,6 +826,10 @@ config SND_SOC_ES8316 + tristate "Everest Semi ES8316 CODEC" + depends on I2C + ++config SND_SOC_ES8323 ++ tristate "Everest Semi ES8323 CODEC" ++ depends on I2C ++ + config SND_SOC_ES8328 + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 8dcea2c4604a..2d69c4e132eb 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -90,6 +90,7 @@ snd-soc-dmic-objs := dmic.o + snd-soc-es7134-objs := es7134.o + snd-soc-es7241-objs := es7241.o + snd-soc-es8316-objs := es8316.o ++snd-soc-es8323-objs := es8323.o + snd-soc-es8328-objs := es8328.o + snd-soc-es8328-i2c-objs := es8328-i2c.o + snd-soc-es8328-spi-objs := es8328-spi.o +@@ -421,6 +422,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o + obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o + obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o + obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o ++obj-$(CONFIG_SND_SOC_ES8323) += snd-soc-es8323.o + obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o + obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o + obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o +diff --git a/sound/soc/codecs/es8323.c b/sound/soc/codecs/es8323.c +new file mode 100755 +index 000000000000..41ba0e4d3c6a +--- /dev/null ++++ b/sound/soc/codecs/es8323.c +@@ -0,0 +1,1127 @@ ++/* ++ * es8323.c -- es8323 ALSA SoC audio driver ++ * ++ * Copyright (c) 2016 Rockchip Electronics Co. Ltd. ++ * ++ * Author: Mark Brown ++ * Author: Jianqun Xu ++ * Author: Nickey Yang ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "es8323.h" ++ ++#define INVALID_GPIO -1 ++#define ES8323_CODEC_SET_SPK 1 ++#define ES8323_CODEC_SET_HP 2 ++#define MUTED_TYPE_OFF 0 ++#define MUTED_TYPE_ON 1 ++#define ES8323_DEF_VOL 0x1e ++ ++/* codec private data */ ++struct es8323_priv { ++ struct regmap *regmap; ++ unsigned int sysclk; ++ struct clk *mclk; ++ struct snd_pcm_hw_constraint_list *sysclk_constraints; ++ struct snd_soc_jack hp_jack; ++ ++ int audio_switch_gpio; ++ int spk_ctl_gpio; ++ int hp_ctl_gpio; ++ int hp_det_gpio; ++ int aux_det_gpio; ++ int aux_det_irq; ++ ++ bool muted; ++ bool hp_inserted; ++ bool spk_gpio_level; ++ bool hp_gpio_level; ++ bool hp_det_level; ++ bool line_in_status; ++}; ++ ++static struct es8323_priv *es8323_private; ++static struct snd_soc_component *es8323_component; ++ ++static void aux_det_work_func(struct work_struct *work); ++static DECLARE_DELAYED_WORK(aux_det_work, aux_det_work_func); ++ ++static int es8323_set_gpio(int gpio, bool level) ++{ ++ struct es8323_priv *es8323 = es8323_private; ++ ++ if (!es8323) { ++ return 0; ++ } ++ ++ if ((gpio & ES8323_CODEC_SET_HP) && es8323 ++ && es8323->hp_ctl_gpio != INVALID_GPIO) { ++ gpio_set_value(es8323->hp_ctl_gpio, level); ++ } ++ ++ if ((gpio & ES8323_CODEC_SET_SPK) && es8323 ++ && es8323->spk_ctl_gpio != INVALID_GPIO) { ++ gpio_set_value(es8323->spk_ctl_gpio, level); ++ } ++ ++ return 0; ++} ++ ++static void spk_detect_do_switch(int flags) ++{ ++ struct es8323_priv *es8323 = es8323_private; ++ ++ switch (flags) { ++ case MUTED_TYPE_ON: ++ if (es8323->hp_det_level == es8323->hp_inserted) { ++ es8323_set_gpio(ES8323_CODEC_SET_HP, es8323->hp_gpio_level); ++ es8323_set_gpio(ES8323_CODEC_SET_SPK, !es8323->spk_gpio_level); ++ } else { ++ es8323_set_gpio(ES8323_CODEC_SET_HP, !es8323->hp_gpio_level); ++ es8323_set_gpio(ES8323_CODEC_SET_SPK, es8323->spk_gpio_level); ++ } ++ break; ++ case MUTED_TYPE_OFF: ++ es8323_set_gpio(ES8323_CODEC_SET_HP, !es8323->hp_gpio_level); ++ es8323_set_gpio(ES8323_CODEC_SET_SPK, !es8323->spk_gpio_level); ++ break; ++ default: ++ break; ++ } ++} ++ ++static irqreturn_t hp_det_irq_handler(int irq, void *dev_id) ++{ ++ struct es8323_priv *es8323 = es8323_private; ++ ++ if (!gpio_get_value(es8323->hp_det_gpio)) { ++ es8323->hp_inserted = 0; ++ snd_soc_jack_report(&es8323->hp_jack, 0, SND_JACK_HEADPHONE); ++ } else { ++ es8323->hp_inserted = 1; ++ snd_soc_jack_report(&es8323->hp_jack, SND_JACK_HEADPHONE, SND_JACK_HEADPHONE); ++ } ++ ++ if (!es8323->line_in_status) ++ spk_detect_do_switch(!es8323->muted); ++ else ++ spk_detect_do_switch(1); ++ ++ return IRQ_HANDLED; ++} ++ ++static void es8323_set_linein(unsigned int flags) ++{ ++ struct es8323_priv *es8323 = es8323_private; ++ ++ if (flags) { ++ snd_soc_component_write(es8323_component, 0x26, 0x00); ++ snd_soc_component_write(es8323_component, 0x27, 0x40); ++ snd_soc_component_write(es8323_component, 0x2a, 0x40); ++ snd_soc_component_write(es8323_component, 0x0b, 0x02); ++ snd_soc_component_write(es8323_component, 0x04, 0x0c); ++ spk_detect_do_switch(1); ++ } else { ++ snd_soc_component_write(es8323_component, 0x26, 0x12); ++ snd_soc_component_write(es8323_component, 0x27, 0xb8); ++ snd_soc_component_write(es8323_component, 0x2a, 0xb8); ++ snd_soc_component_write(es8323_component, 0x0b, 0x82); ++ snd_soc_component_write(es8323_component, 0x04, 0x3c); ++ spk_detect_do_switch(!es8323->muted); ++ } ++} ++ ++static void aux_det_work_func(struct work_struct *work) ++{ ++ struct es8323_priv *es8323 = es8323_private; ++ ++ es8323->line_in_status = !gpio_get_value(es8323->aux_det_gpio); ++ ++ es8323_set_linein(es8323->line_in_status); ++ enable_irq(es8323->aux_det_irq); ++} ++ ++static irqreturn_t aux_det_isr(int irq, void *data) ++{ ++ disable_irq_nosync(irq); ++ schedule_delayed_work(&aux_det_work, msecs_to_jiffies(250)); ++ ++ return IRQ_HANDLED; ++} ++ ++static int es8323_reset(struct snd_soc_component *component) ++{ ++ snd_soc_component_write(component, ES8323_CONTROL1, 0x80); ++ return snd_soc_component_write(component, ES8323_CONTROL1, 0x00); ++} ++ ++static const char *es8323_line_texts[] = { ++ "Line 1", "Line 2", "PGA" ++}; ++ ++static const unsigned int es8323_line_values[] = { ++ 0, 1, 3 ++}; ++static const char *es8323_pga_sel[] = { "Line 1", "Line 2", "Differential" }; ++static const char *stereo_3d_txt[] = ++ { "No 3D ", "Level 1", "Level 2", "Level 3", "Level 4", "Level 5", ++"Level 6", "Level 7" }; ++static const char *alc_func_txt[] = { "Off", "Right", "Left", "Stereo" }; ++static const char *ng_type_txt[] = { "Constant PGA Gain", "Mute ADC Output" }; ++static const char *deemph_txt[] = { "None", "32Khz", "44.1Khz", "48Khz" }; ++static const char *adcpol_txt[] = ++ { "Normal", "L Invert", "R Invert", "L + R Invert" }; ++static const char *es8323_mono_mux[] = ++ { "Stereo", "Mono (Left)", "Mono (Right)" }; ++static const char *es8323_diff_sel[] = { "Line 1", "Line 2" }; ++ ++static const struct soc_enum es8323_enum[] = { ++ SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 3, 7, ARRAY_SIZE(es8323_line_texts), es8323_line_texts, es8323_line_values), /* LLINE */ ++ SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 0, 7, ARRAY_SIZE(es8323_line_texts), es8323_line_texts, es8323_line_values), /* RLINE */ ++ SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 6, 3, ARRAY_SIZE(es8323_pga_sel), es8323_pga_sel, es8323_line_values), /* Left PGA Mux */ ++ SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 4, 3, ARRAY_SIZE(es8323_pga_sel), es8323_pga_sel, es8323_line_values), /* Right PGA Mux */ ++ SOC_ENUM_SINGLE(ES8323_DACCONTROL7, 2, 8, stereo_3d_txt), /* stereo-3d */ ++ SOC_ENUM_SINGLE(ES8323_ADCCONTROL10, 6, 4, alc_func_txt), /* alc func */ ++ SOC_ENUM_SINGLE(ES8323_ADCCONTROL14, 1, 2, ng_type_txt), /* noise gate type */ ++ SOC_ENUM_SINGLE(ES8323_DACCONTROL6, 6, 4, deemph_txt), /* Playback De-emphasis */ ++ SOC_ENUM_SINGLE(ES8323_ADCCONTROL6, 6, 4, adcpol_txt), ++ SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 3, 3, es8323_mono_mux), ++ SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 7, 2, es8323_diff_sel), ++}; ++ ++static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0); ++static const DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 50, 1); ++static const DECLARE_TLV_DB_SCALE(dac_tlv, -9600, 50, 1); ++static const DECLARE_TLV_DB_SCALE(out_tlv, -4500, 150, 0); ++static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); ++ ++static const struct snd_kcontrol_new es8323_snd_controls[] = { ++ SOC_ENUM("3D Mode", es8323_enum[4]), ++ SOC_SINGLE("ALC Capture Target Volume", ES8323_ADCCONTROL11, 4, 15, 0), ++ SOC_SINGLE("ALC Capture Max PGA", ES8323_ADCCONTROL10, 3, 7, 0), ++ SOC_SINGLE("ALC Capture Min PGA", ES8323_ADCCONTROL10, 0, 7, 0), ++ SOC_ENUM("ALC Capture Function", es8323_enum[5]), ++ SOC_SINGLE("ALC Capture ZC Switch", ES8323_ADCCONTROL13, 6, 1, 0), ++ SOC_SINGLE("ALC Capture Hold Time", ES8323_ADCCONTROL11, 0, 15, 0), ++ SOC_SINGLE("ALC Capture Decay Time", ES8323_ADCCONTROL12, 4, 15, 0), ++ SOC_SINGLE("ALC Capture Attack Time", ES8323_ADCCONTROL12, 0, 15, 0), ++ SOC_SINGLE("ALC Capture NG Threshold", ES8323_ADCCONTROL14, 3, 31, 0), ++ SOC_ENUM("ALC Capture NG Type", es8323_enum[6]), ++ SOC_SINGLE("ALC Capture NG Switch", ES8323_ADCCONTROL14, 0, 1, 0), ++ SOC_SINGLE("ZC Timeout Switch", ES8323_ADCCONTROL13, 6, 1, 0), ++ SOC_DOUBLE_R_TLV("Capture Digital Volume", ES8323_ADCCONTROL8, ++ ES8323_ADCCONTROL9, 0, 255, 1, adc_tlv), ++ SOC_SINGLE("Capture Mute", ES8323_ADCCONTROL7, 2, 1, 0), ++ SOC_SINGLE_TLV("Left Channel Capture Volume", ES8323_ADCCONTROL1, 4, 15, ++ 0, bypass_tlv), ++ SOC_SINGLE_TLV("Right Channel Capture Volume", ES8323_ADCCONTROL1, 0, ++ 15, 0, bypass_tlv), ++ SOC_ENUM("Playback De-emphasis", es8323_enum[7]), ++ SOC_ENUM("Capture Polarity", es8323_enum[8]), ++ SOC_DOUBLE_R_TLV("PCM Volume", ES8323_DACCONTROL4, ES8323_DACCONTROL5, ++ 0, 255, 1, dac_tlv), ++ SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", ES8323_DACCONTROL17, 3, ++ 7, 1, bypass_tlv), ++ SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", ES8323_DACCONTROL20, ++ 3, 7, 1, bypass_tlv), ++ SOC_DOUBLE_R_TLV("Output 1 Playback Volume", ES8323_DACCONTROL24, ++ ES8323_DACCONTROL25, 0, 64, 0, out_tlv), ++ SOC_DOUBLE_R_TLV("Output 2 Playback Volume", ES8323_DACCONTROL26, ++ ES8323_DACCONTROL27, 0, 64, 0, out_tlv), ++}; ++ ++static const struct snd_kcontrol_new es8323_left_line_controls = ++SOC_DAPM_ENUM("Route", es8323_enum[0]); ++ ++static const struct snd_kcontrol_new es8323_right_line_controls = ++SOC_DAPM_ENUM("Route", es8323_enum[1]); ++ ++/* Left PGA Mux */ ++static const struct snd_kcontrol_new es8323_left_pga_controls = ++SOC_DAPM_ENUM("Route", es8323_enum[2]); ++ ++/* Right PGA Mux */ ++static const struct snd_kcontrol_new es8323_right_pga_controls = ++SOC_DAPM_ENUM("Route", es8323_enum[3]); ++ ++/* Left Mixer */ ++static const struct snd_kcontrol_new es8323_left_mixer_controls[] = { ++ SOC_DAPM_SINGLE("Left Playback Switch", ES8323_DACCONTROL17, 7, 1, 0), ++ SOC_DAPM_SINGLE("Left Bypass Switch", ES8323_DACCONTROL17, 6, 1, 0), ++}; ++ ++/* Right Mixer */ ++static const struct snd_kcontrol_new es8323_right_mixer_controls[] = { ++ SOC_DAPM_SINGLE("Right Playback Switch", ES8323_DACCONTROL20, 7, 1, 0), ++ SOC_DAPM_SINGLE("Right Bypass Switch", ES8323_DACCONTROL20, 6, 1, 0), ++}; ++ ++/* Differential Mux */ ++static const struct snd_kcontrol_new es8323_diffmux_controls = ++SOC_DAPM_ENUM("Route", es8323_enum[10]); ++ ++/* Mono ADC Mux */ ++static const struct snd_kcontrol_new es8323_monomux_controls = ++SOC_DAPM_ENUM("Route", es8323_enum[9]); ++ ++static const struct snd_soc_dapm_widget es8323_dapm_widgets[] = { ++ SND_SOC_DAPM_INPUT("LINPUT1"), ++ SND_SOC_DAPM_INPUT("LINPUT2"), ++ SND_SOC_DAPM_INPUT("RINPUT1"), ++ SND_SOC_DAPM_INPUT("RINPUT2"), ++ ++ SND_SOC_DAPM_MICBIAS("Mic Bias", ES8323_ADCPOWER, 3, 1), ++ ++ SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, ++ &es8323_diffmux_controls), ++ ++ SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, ++ &es8323_monomux_controls), ++ SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, ++ &es8323_monomux_controls), ++ ++ SND_SOC_DAPM_MUX("Left PGA Mux", ES8323_ADCPOWER, 7, 1, ++ &es8323_left_pga_controls), ++ SND_SOC_DAPM_MUX("Right PGA Mux", ES8323_ADCPOWER, 6, 1, ++ &es8323_right_pga_controls), ++ ++ SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, ++ &es8323_left_line_controls), ++ SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, ++ &es8323_right_line_controls), ++ ++ SND_SOC_DAPM_ADC("Right ADC", "Right Capture", ES8323_ADCPOWER, 4, 1), ++ SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ES8323_ADCPOWER, 5, 1), ++ ++ /* gModify.Cmmt Implement when suspend/startup */ ++ SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ES8323_DACPOWER, 6, 1), ++ SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8323_DACPOWER, 7, 1), ++ ++ SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, ++ &es8323_left_mixer_controls[0], ++ ARRAY_SIZE(es8323_left_mixer_controls)), ++ SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, ++ &es8323_right_mixer_controls[0], ++ ARRAY_SIZE(es8323_right_mixer_controls)), ++ ++ SND_SOC_DAPM_PGA("Right Out 2", ES8323_DACPOWER, 2, 0, NULL, 0), ++ SND_SOC_DAPM_PGA("Left Out 2", ES8323_DACPOWER, 3, 0, NULL, 0), ++ SND_SOC_DAPM_PGA("Right Out 1", ES8323_DACPOWER, 4, 0, NULL, 0), ++ SND_SOC_DAPM_PGA("Left Out 1", ES8323_DACPOWER, 5, 0, NULL, 0), ++ SND_SOC_DAPM_PGA("LAMP", ES8323_ADCCONTROL1, 4, 0, NULL, 0), ++ SND_SOC_DAPM_PGA("RAMP", ES8323_ADCCONTROL1, 0, 0, NULL, 0), ++ ++ SND_SOC_DAPM_OUTPUT("LOUT1"), ++ SND_SOC_DAPM_OUTPUT("ROUT1"), ++ SND_SOC_DAPM_OUTPUT("LOUT2"), ++ SND_SOC_DAPM_OUTPUT("ROUT2"), ++ SND_SOC_DAPM_OUTPUT("VREF"), ++}; ++ ++static const struct snd_soc_dapm_route es8323_dapm_routes[] = { ++ ++ { "Left Line Mux", "Line 1", "LINPUT1" }, ++ { "Left Line Mux", "Line 2", "LINPUT2" }, ++ { "Left Line Mux", "PGA", "Left PGA Mux" }, ++ ++ { "Right Line Mux", "Line 1", "RINPUT1" }, ++ { "Right Line Mux", "Line 2", "RINPUT2" }, ++ { "Right Line Mux", "PGA", "Right PGA Mux" }, ++ ++ { "Left PGA Mux", "Line 1", "LINPUT1" }, ++ { "Left PGA Mux", "Line 2", "LINPUT2" }, ++ { "Left PGA Mux", "Differential", "Differential Mux" }, ++ ++ { "Right PGA Mux", "Line 1", "RINPUT1" }, ++ { "Right PGA Mux", "Line 2", "RINPUT2" }, ++ { "Right PGA Mux", "Differential", "Differential Mux" }, ++ ++ { "Differential Mux", "Line 1", "LINPUT1" }, ++ { "Differential Mux", "Line 1", "RINPUT1" }, ++ { "Differential Mux", "Line 2", "LINPUT2" }, ++ { "Differential Mux", "Line 2", "RINPUT2" }, ++ ++ {"Left ADC Mux", "Stereo", "Left PGA Mux"}, ++ {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"}, ++ ++ {"Right ADC Mux", "Stereo", "Right PGA Mux"}, ++ {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, ++ ++ {"Left ADC", NULL, "Left ADC Mux"}, ++ {"Right ADC", NULL, "Right ADC Mux"}, ++ ++ {"Left Mixer", "Left Playback Switch", "Left DAC"}, ++ {"Left Mixer", "Left Bypass Switch", "Left Line Mux"}, ++ ++ {"Right Mixer", "Right Playback Switch", "Right DAC"}, ++ {"Right Mixer", "Right Bypass Switch", "Right Line Mux"}, ++ ++ {"Left Out 1", NULL, "Left Mixer"}, ++ {"LOUT1", NULL, "Left Out 1"}, ++ {"Right Out 1", NULL, "Right Mixer"}, ++ {"ROUT1", NULL, "Right Out 1"}, ++ ++ {"Left Out 2", NULL, "Left Mixer"}, ++ {"LOUT2", NULL, "Left Out 2"}, ++ {"Right Out 2", NULL, "Right Mixer"}, ++ {"ROUT2", NULL, "Right Out 2"}, ++}; ++ ++struct _coeff_div { ++ u32 mclk; ++ u32 rate; ++ u16 fs; ++ u8 sr:4; ++ u8 usb:1; ++}; ++ ++/* codec hifi mclk clock divider coefficients */ ++static const struct _coeff_div coeff_div[] = { ++ /* 8k */ ++ {12288000, 8000, 1536, 0xa, 0x0}, ++ {11289600, 8000, 1408, 0x9, 0x0}, ++ {18432000, 8000, 2304, 0xc, 0x0}, ++ {16934400, 8000, 2112, 0xb, 0x0}, ++ {12000000, 8000, 1500, 0xb, 0x1}, ++ ++ /* 11.025k */ ++ {11289600, 11025, 1024, 0x7, 0x0}, ++ {16934400, 11025, 1536, 0xa, 0x0}, ++ {12000000, 11025, 1088, 0x9, 0x1}, ++ ++ /* 16k */ ++ {12288000, 16000, 768, 0x6, 0x0}, ++ {18432000, 16000, 1152, 0x8, 0x0}, ++ {12000000, 16000, 750, 0x7, 0x1}, ++ ++ /* 22.05k */ ++ {11289600, 22050, 512, 0x4, 0x0}, ++ {16934400, 22050, 768, 0x6, 0x0}, ++ {12000000, 22050, 544, 0x6, 0x1}, ++ ++ /* 32k */ ++ {12288000, 32000, 384, 0x3, 0x0}, ++ {18432000, 32000, 576, 0x5, 0x0}, ++ {12000000, 32000, 375, 0x4, 0x1}, ++ ++ /* 44.1k */ ++ {11289600, 44100, 256, 0x2, 0x0}, ++ {16934400, 44100, 384, 0x3, 0x0}, ++ {12000000, 44100, 272, 0x3, 0x1}, ++ ++ /* 48k */ ++ {12288000, 48000, 256, 0x2, 0x0}, ++ {18432000, 48000, 384, 0x3, 0x0}, ++ {12000000, 48000, 250, 0x2, 0x1}, ++ ++ /* 88.2k */ ++ {11289600, 88200, 128, 0x0, 0x0}, ++ {16934400, 88200, 192, 0x1, 0x0}, ++ {12000000, 88200, 136, 0x1, 0x1}, ++ ++ /* 96k */ ++ {12288000, 96000, 128, 0x0, 0x0}, ++ {18432000, 96000, 192, 0x1, 0x0}, ++ {12000000, 96000, 125, 0x0, 0x1}, ++}; ++ ++static inline int get_coeff(int mclk, int rate) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { ++ if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) ++ return i; ++ } ++ ++ return -EINVAL; ++} ++ ++/* The set of rates we can generate from the above for each SYSCLK */ ++static unsigned int rates_12288[] = { ++ 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, ++}; ++ ++static struct snd_pcm_hw_constraint_list constraints_12288 = { ++ .count = ARRAY_SIZE(rates_12288), ++ .list = rates_12288, ++}; ++ ++static unsigned int rates_112896[] = { ++ 8000, 11025, 22050, 44100, ++}; ++ ++static struct snd_pcm_hw_constraint_list constraints_112896 = { ++ .count = ARRAY_SIZE(rates_112896), ++ .list = rates_112896, ++}; ++ ++static unsigned int rates_12[] = { ++ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, ++ 48000, 88235, 96000, ++}; ++ ++static struct snd_pcm_hw_constraint_list constraints_12 = { ++ .count = ARRAY_SIZE(rates_12), ++ .list = rates_12, ++}; ++ ++/* ++ * Note that this should be called from init rather than from hw_params. ++ */ ++static int es8323_set_dai_sysclk(struct snd_soc_dai *codec_dai, ++ int clk_id, unsigned int freq, int dir) ++{ ++ struct snd_soc_component *component = codec_dai->component; ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ ++ switch (freq) { ++ case 11289600: ++ case 18432000: ++ case 22579200: ++ case 36864000: ++ es8323->sysclk_constraints = &constraints_112896; ++ es8323->sysclk = freq; ++ return 0; ++ ++ case 12288000: ++ case 16934400: ++ case 24576000: ++ case 33868800: ++ es8323->sysclk_constraints = &constraints_12288; ++ es8323->sysclk = freq; ++ return 0; ++ ++ case 12000000: ++ case 24000000: ++ es8323->sysclk_constraints = &constraints_12; ++ es8323->sysclk = freq; ++ return 0; ++ default: ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++static int es8323_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) ++{ ++ struct snd_soc_component *component = codec_dai->component; ++ u8 iface = 0; ++ u8 adciface = 0; ++ u8 daciface = 0; ++ ++ iface = snd_soc_component_read(component, ES8323_IFACE); ++ adciface = snd_soc_component_read(component, ES8323_ADC_IFACE); ++ daciface = snd_soc_component_read(component, ES8323_DAC_IFACE); ++ ++ /* set master/slave audio interface */ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBM_CFM: /* MASTER MODE */ ++ iface |= 0x80; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFS: /* SLAVE MODE */ ++ iface &= 0x7F; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* interface format */ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ adciface &= 0xFC; ++ daciface &= 0xF9; ++ break; ++ case SND_SOC_DAIFMT_RIGHT_J: ++ break; ++ case SND_SOC_DAIFMT_LEFT_J: ++ break; ++ case SND_SOC_DAIFMT_DSP_A: ++ break; ++ case SND_SOC_DAIFMT_DSP_B: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* clock inversion */ ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ iface &= 0xDF; ++ adciface &= 0xDF; ++ daciface &= 0xBF; ++ break; ++ case SND_SOC_DAIFMT_IB_IF: ++ iface |= 0x20; ++ adciface |= 0x20; ++ daciface |= 0x40; ++ break; ++ case SND_SOC_DAIFMT_IB_NF: ++ iface |= 0x20; ++ adciface &= 0xDF; ++ daciface &= 0xBF; ++ break; ++ case SND_SOC_DAIFMT_NB_IF: ++ iface &= 0xDF; ++ adciface |= 0x20; ++ daciface |= 0x40; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ snd_soc_component_write(component, ES8323_IFACE, iface); ++ snd_soc_component_write(component, ES8323_ADC_IFACE, adciface); ++ snd_soc_component_write(component, ES8323_DAC_IFACE, daciface); ++ ++ return 0; ++} ++ ++static int es8323_pcm_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ ++ /* The set of sample rates that can be supported depends on the ++ * MCLK supplied to the CODEC - enforce this. ++ */ ++ if (!es8323->sysclk) { ++ dev_err(component->dev, ++ "No MCLK configured, call set_sysclk() on init\n"); ++ return -EINVAL; ++ } ++ ++ snd_pcm_hw_constraint_list(substream->runtime, 0, ++ SNDRV_PCM_HW_PARAM_RATE, ++ es8323->sysclk_constraints); ++ ++ return 0; ++} ++ ++static int es8323_pcm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ u16 srate = snd_soc_component_read(component, ES8323_IFACE) & 0x80; ++ u16 adciface = snd_soc_component_read(component, ES8323_ADC_IFACE) & 0xE3; ++ u16 daciface = snd_soc_component_read(component, ES8323_DAC_IFACE) & 0xC7; ++ int coeff; ++ ++ coeff = get_coeff(es8323->sysclk, params_rate(params)); ++ if (coeff < 0) { ++ coeff = get_coeff(es8323->sysclk / 2, params_rate(params)); ++ srate |= 0x40; ++ } ++ if (coeff < 0) { ++ dev_err(component->dev, ++ "Unable to configure sample rate %dHz with %dHz MCLK\n", ++ params_rate(params), es8323->sysclk); ++ return coeff; ++ } ++ ++ /* bit size */ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ adciface |= 0x000C; ++ daciface |= 0x0018; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ adciface |= 0x0004; ++ daciface |= 0x0008; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ adciface |= 0x0010; ++ daciface |= 0x0020; ++ break; ++ } ++ ++ /* set iface & srate */ ++ snd_soc_component_write(component, ES8323_DAC_IFACE, daciface); ++ snd_soc_component_write(component, ES8323_ADC_IFACE, adciface); ++ ++ if (coeff >= 0) { ++ snd_soc_component_write(component, ES8323_IFACE, srate); ++ snd_soc_component_write(component, ES8323_ADCCONTROL5, ++ coeff_div[coeff].sr | (coeff_div[coeff]. ++ usb) << 4); ++ snd_soc_component_write(component, ES8323_DACCONTROL2, ++ coeff_div[coeff].sr | (coeff_div[coeff]. ++ usb) << 4); ++ } ++ ++ return 0; ++} ++ ++static int es8323_mute(struct snd_soc_dai *dai, int mute, int direction) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ ++ es8323->muted = mute; ++ if (mute) { ++ es8323_set_gpio(ES8323_CODEC_SET_SPK, !es8323->spk_gpio_level); ++ usleep_range(18000, 20000); ++ snd_soc_component_write(component, ES8323_DACCONTROL3, 0x06); ++ } else { ++ snd_soc_component_write(component, ES8323_DACCONTROL3, 0x02); ++ snd_soc_component_write(component, 0x30, ES8323_DEF_VOL); ++ snd_soc_component_write(component, 0x31, ES8323_DEF_VOL); ++ msleep(50); ++ if (!es8323->hp_inserted) ++ es8323_set_gpio(ES8323_CODEC_SET_SPK, es8323->spk_gpio_level); ++ usleep_range(18000, 20000); ++ } ++ ++ if (!es8323->line_in_status) ++ spk_detect_do_switch(!es8323->muted); ++ else ++ spk_detect_do_switch(1); ++ ++ return 0; ++} ++ ++static int es8323_set_bias_level(struct snd_soc_component *component, ++ enum snd_soc_bias_level level) ++{ ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ int ret; ++ ++ switch (level) { ++ case SND_SOC_BIAS_ON: ++ dev_dbg(component->dev, "%s on\n", __func__); ++ break; ++ case SND_SOC_BIAS_PREPARE: ++ dev_dbg(component->dev, "%s prepare\n", __func__); ++ snd_soc_component_write(component, ES8323_ANAVOLMANAG, 0x7C); ++ snd_soc_component_write(component, ES8323_CHIPLOPOW1, 0x00); ++ snd_soc_component_write(component, ES8323_CHIPLOPOW2, 0x00); ++ snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00); ++ snd_soc_component_write(component, ES8323_ADCPOWER, 0x59); ++ break; ++ case SND_SOC_BIAS_STANDBY: ++ dev_dbg(component->dev, "%s standby\n", __func__); ++ snd_soc_component_write(component, ES8323_ANAVOLMANAG, 0x7C); ++ snd_soc_component_write(component, ES8323_CHIPLOPOW1, 0x00); ++ snd_soc_component_write(component, ES8323_CHIPLOPOW2, 0x00); ++ snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00); ++ snd_soc_component_write(component, ES8323_ADCPOWER, 0x59); ++ break; ++ case SND_SOC_BIAS_OFF: ++ dev_dbg(component->dev, "%s off\n", __func__); ++ snd_soc_component_write(component, ES8323_ADCPOWER, 0xFF); ++ snd_soc_component_write(component, ES8323_DACPOWER, 0xC0); ++ snd_soc_component_write(component, ES8323_CHIPLOPOW1, 0xFF); ++ snd_soc_component_write(component, ES8323_CHIPLOPOW2, 0xFF); ++ snd_soc_component_write(component, ES8323_CHIPPOWER, 0xFF); ++ snd_soc_component_write(component, ES8323_ANAVOLMANAG, 0x7B); ++ break; ++ } ++ return 0; ++} ++ ++#define ES8323_RATES SNDRV_PCM_RATE_8000_96000 ++#define ES8323_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |SNDRV_PCM_FMTBIT_S24_LE) ++ ++static struct snd_soc_dai_ops es8323_ops = { ++ .startup = es8323_pcm_startup, ++ .hw_params = es8323_pcm_hw_params, ++ .set_fmt = es8323_set_dai_fmt, ++ .set_sysclk = es8323_set_dai_sysclk, ++ .mute_stream = es8323_mute, ++}; ++ ++static struct snd_soc_dai_driver es8323_dai = { ++ .name = "ES8323 HiFi", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = ES8323_RATES, ++ .formats = ES8323_FORMATS, ++ }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = ES8323_RATES, ++ .formats = ES8323_FORMATS, ++ }, ++ .ops = &es8323_ops, ++ .symmetric_rate = 1, ++}; ++ ++static int es8323_suspend(struct snd_soc_component *component) ++{ ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ ++ if (!IS_ERR(es8323->mclk)) ++ clk_disable_unprepare(es8323->mclk); ++ snd_soc_component_write(component, 0x19, 0x06); ++ snd_soc_component_write(component, 0x30, 0x00); ++ snd_soc_component_write(component, 0x31, 0x00); ++ snd_soc_component_write(component, ES8323_ADCPOWER, 0xFF); ++ snd_soc_component_write(component, ES8323_DACPOWER, 0xc0); ++ snd_soc_component_write(component, ES8323_CHIPPOWER, 0xF3); ++ snd_soc_component_write(component, 0x00, 0x00); ++ snd_soc_component_write(component, 0x01, 0x58); ++ snd_soc_component_write(component, 0x2b, 0x9c); ++ usleep_range(18000, 20000); ++ return 0; ++} ++ ++static int es8323_resume(struct snd_soc_component *component) ++{ ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ ++ if (!IS_ERR(es8323->mclk)) ++ clk_prepare_enable(es8323->mclk); ++ snd_soc_component_write(component, 0x2b, 0x80); ++ snd_soc_component_write(component, 0x01, 0x50); ++ snd_soc_component_write(component, 0x00, 0x32); ++ snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00); ++ snd_soc_component_write(component, ES8323_DACPOWER, 0x0c); ++ snd_soc_component_write(component, ES8323_ADCPOWER, 0x59); ++ snd_soc_component_write(component, 0x31, ES8323_DEF_VOL); ++ snd_soc_component_write(component, 0x30, ES8323_DEF_VOL); ++ snd_soc_component_write(component, 0x19, 0x02); ++ return 0; ++} ++ ++static int es8323_hp_jack_change(struct notifier_block *nb, ++ unsigned long flags, void *data) ++{ ++ if ( !(int)flags ) ++ snd_soc_component_write(es8323_component, 0x0b, 0x82); ++ else ++ snd_soc_component_write(es8323_component, 0x0b, 0x02); ++ ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block es8323_hp_jack_nb = { ++ .notifier_call = es8323_hp_jack_change, ++}; ++ ++static void es8323_jack_init(struct snd_soc_component *component) ++{ ++ struct es8323_priv *es8323 = es8323_private; ++ ++ snd_soc_card_jack_new(component->card, ++ "Headphone Jack", SND_JACK_HEADPHONE, ++ &es8323->hp_jack, NULL, 0); ++ snd_soc_jack_notifier_register(&es8323->hp_jack, &es8323_hp_jack_nb); ++} ++ ++static int es8323_probe(struct snd_soc_component *component) ++{ ++ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); ++ int ret = 0, hp_irq; ++ ++ if (component == NULL) { ++ dev_err(component->dev, "Codec device not registered\n"); ++ return -ENODEV; ++ } ++ ++ es8323->mclk = devm_clk_get(component->dev, "mclk"); ++ if (IS_ERR(es8323->mclk)) { ++ dev_err(component->dev, "%s mclk is missing or invalid\n", __func__); ++ return PTR_ERR(es8323->mclk); ++ } ++ ret = clk_prepare_enable(es8323->mclk); ++ if (ret) ++ return ret; ++ ++ if (es8323->hp_det_gpio != INVALID_GPIO) { ++ if (gpio_get_value(es8323->hp_det_gpio) == es8323->hp_det_level) ++ es8323->hp_inserted = 1; ++ } ++ ++ if (es8323->aux_det_gpio != INVALID_GPIO) ++ schedule_delayed_work(&aux_det_work, msecs_to_jiffies(500)); ++ ++ es8323_component = component; ++ es8323_jack_init(component); ++ ++ hp_irq = gpio_to_irq(es8323->hp_det_gpio); ++ if (hp_irq) { ++ ret = devm_request_threaded_irq(component->dev, hp_irq, NULL, hp_det_irq_handler, ++ IRQ_TYPE_EDGE_BOTH | IRQF_ONESHOT, "ES8323", NULL); ++ if (ret < 0) { ++ dev_err(component->dev, "request_irq failed: %d\n", ret); ++ return ret; ++ } ++ } ++ ++ ret = es8323_reset(component); ++ if (ret < 0) { ++ dev_err(component->dev, "Failed to issue reset\n"); ++ return ret; ++ } ++ ++ usleep_range(18000, 20000); ++ snd_soc_component_write(component, 0x02, 0xf3); ++ snd_soc_component_write(component, 0x2B, 0x80); ++ snd_soc_component_write(component, 0x08, 0x00); /* ES8323 salve */ ++ snd_soc_component_write(component, 0x00, 0x35); ++ snd_soc_component_write(component, 0x01, 0x50); /* PLAYBACK & RECORD Mode,EnRefr=1 */ ++ snd_soc_component_write(component, 0x03, 0x59); /* pdn_ana=0,ibiasgen_pdn=0 */ ++ snd_soc_component_write(component, 0x05, 0x00); /* pdn_ana=0,ibiasgen_pdn=0 */ ++ snd_soc_component_write(component, 0x06, 0x00); /* pdn_ana=0,ibiasgen_pdn=0 */ ++ snd_soc_component_write(component, 0x07, 0x7c); ++ snd_soc_component_write(component, 0x09, 0x88); /* ADC L/R PGA = +24dB */ ++ snd_soc_component_write(component, 0x0a, 0xf0); /* ADC INPUT=LIN2/RIN2 */ ++ snd_soc_component_write(component, 0x0b, 0x82); /* ADC INPUT=LIN2/RIN2 */ ++ snd_soc_component_write(component, 0x0b, 0x02); ++ snd_soc_component_write(component, 0x0C, 0x4c); /* I2S-24BIT */ ++ snd_soc_component_write(component, 0x0d, 0x02); /* MCLK/LRCK=256 */ ++ snd_soc_component_write(component, 0x10, 0x00); /* ADC Left Volume=0db */ ++ snd_soc_component_write(component, 0x11, 0x00); /* ADC Right Volume=0db */ ++ snd_soc_component_write(component, 0x12, 0xea); /* ALC stereo MAXGAIN: 35.5dB, MINGAIN: +6dB (Record Volume increased!) */ ++ snd_soc_component_write(component, 0x13, 0xc0); ++ snd_soc_component_write(component, 0x14, 0x05); ++ snd_soc_component_write(component, 0x15, 0x06); ++ snd_soc_component_write(component, 0x16, 0x53); ++ snd_soc_component_write(component, 0x17, 0x18); /* I2S-16BIT */ ++ snd_soc_component_write(component, 0x18, 0x02); ++ snd_soc_component_write(component, 0x1A, 0x0A); /* DAC VOLUME=0DB */ ++ snd_soc_component_write(component, 0x1B, 0x0A); ++ snd_soc_component_write(component, 0x26, 0x12); /* Left DAC TO Left IXER */ ++ snd_soc_component_write(component, 0x27, 0xb8); /* Left DAC TO Left MIXER */ ++ snd_soc_component_write(component, 0x28, 0x38); ++ snd_soc_component_write(component, 0x29, 0x38); ++ snd_soc_component_write(component, 0x2A, 0xb8); ++ snd_soc_component_write(component, 0x02, 0x00); /* START DLL and state-machine,START DSM */ ++ snd_soc_component_write(component, 0x19, 0x02); /* SOFT RAMP RATE=32LRCKS/STEP,Enable ZERO-CROSS CHECK,DAC MUTE */ ++ snd_soc_component_write(component, 0x04, 0x0c); /* pdn_ana=0,ibiasgen_pdn=0 */ ++ usleep_range(18000, 20000); ++ snd_soc_component_write(component, 0x2e, 0x00); ++ snd_soc_component_write(component, 0x2f, 0x00); ++ snd_soc_component_write(component, 0x30, 0x08); ++ snd_soc_component_write(component, 0x31, 0x08); ++ usleep_range(18000, 20000); ++ snd_soc_component_write(component, 0x30, 0x0f); ++ snd_soc_component_write(component, 0x31, 0x0f); ++ usleep_range(18000, 20000); ++ snd_soc_component_write(component, 0x30, 0x18); ++ snd_soc_component_write(component, 0x31, 0x18); ++ usleep_range(18000, 20000); ++ snd_soc_component_write(component, 0x04, 0x2c); /* pdn_ana=0,ibiasgen_pdn=0 */ ++ ++ es8323_set_bias_level(component, SND_SOC_BIAS_STANDBY); ++ ++ return 0; ++} ++ ++static void es8323_remove(struct snd_soc_component *component) ++{ ++ es8323_set_bias_level(component, SND_SOC_BIAS_OFF); ++} ++ ++static const struct regmap_config es8323_regmap_config = { ++ .name = "es8323", ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = ES8323_CACHEREGNUM, ++ .cache_type = REGCACHE_RBTREE, ++ .use_single_read = true, ++ .use_single_write = true, ++}; ++ ++static struct snd_soc_component_driver soc_codec_dev_es8323 = { ++ .probe = es8323_probe, ++ .remove = es8323_remove, ++ .suspend = es8323_suspend, ++ .resume = es8323_resume, ++ .controls = es8323_snd_controls, ++ .num_controls = ARRAY_SIZE(es8323_snd_controls), ++ .dapm_widgets = es8323_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(es8323_dapm_widgets), ++ .dapm_routes = es8323_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(es8323_dapm_routes), ++ .set_bias_level = es8323_set_bias_level, ++}; ++ ++static int es8323_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ struct es8323_priv *es8323; ++ int ret = -1; ++ int hp_irq = 0; ++ enum of_gpio_flags flags; ++ struct i2c_adapter *adapter = to_i2c_adapter(i2c->dev.parent); ++ char reg; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { ++ dev_warn(&adapter->dev, ++ "I2C-Adapter doesn't support I2C_FUNC_I2C\n"); ++ return -EIO; ++ } ++ ++ es8323 = devm_kzalloc(&i2c->dev, sizeof(struct es8323_priv), GFP_KERNEL); ++ if (es8323 == NULL) ++ return -ENOMEM; ++ ++ es8323->regmap = devm_regmap_init_i2c(i2c, &es8323_regmap_config); ++ dev_set_drvdata(&i2c->dev, es8323); ++ es8323_private = es8323; ++ ++ es8323->spk_ctl_gpio = of_get_named_gpio_flags(i2c->dev.of_node, "spk-ctl-gpio", 0, &flags); ++ if (es8323->spk_ctl_gpio < 0) { ++ dev_info(&i2c->dev, "Can not read property spk_ctl_gpio\n"); ++ es8323->spk_ctl_gpio = INVALID_GPIO; ++ } else { ++ es8323->spk_gpio_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ret = devm_gpio_request_one(&i2c->dev, es8323->spk_ctl_gpio, GPIOF_DIR_OUT, NULL); ++ if (ret != 0) { ++ dev_err(&i2c->dev, "Failed to request spk_ctl_gpio\n"); ++ return ret; ++ } ++ es8323_set_gpio(ES8323_CODEC_SET_SPK, !es8323->spk_gpio_level); ++ } ++ ++ es8323->hp_ctl_gpio = of_get_named_gpio_flags(i2c->dev.of_node, "hp-ctl-gpio", 0, &flags); ++ if (es8323->hp_ctl_gpio < 0) { ++ dev_info(&i2c->dev, "Can not read property hp_ctl_gpio\n"); ++ es8323->hp_ctl_gpio = INVALID_GPIO; ++ } else { ++ es8323->hp_gpio_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ret = devm_gpio_request_one(&i2c->dev, es8323->hp_ctl_gpio, GPIOF_DIR_OUT, "hp_ctl_gpio"); ++ if (ret != 0) { ++ dev_err(&i2c->dev, "Failed to request hp_ctl_gpio\n"); ++ return ret; ++ } ++ es8323_set_gpio(ES8323_CODEC_SET_HP, !es8323->hp_gpio_level); ++ } ++ ++ es8323->audio_switch_gpio = of_get_named_gpio_flags(i2c->dev.of_node, "audio-switch-gpio", 0, &flags); ++ if (es8323->audio_switch_gpio < 0) { ++ dev_info(&i2c->dev, "Can not read property audio_switch_gpio\n"); ++ es8323->audio_switch_gpio = INVALID_GPIO; ++ } else { ++ ret = devm_gpio_request_one(&i2c->dev, es8323->audio_switch_gpio, GPIOF_DIR_OUT, NULL); ++ if (ret != 0) { ++ dev_err(&i2c->dev, "Failed to request audio_switch_gpio\n"); ++ return ret; ++ } ++ gpio_set_value(es8323_private->audio_switch_gpio, 1); ++ } ++ ++ es8323->hp_det_gpio = of_get_named_gpio_flags(i2c->dev.of_node, "hp-det-gpio", 0, &flags); ++ if (es8323->hp_det_gpio < 0) { ++ dev_info(&i2c->dev, "Can not read property hp_det_gpio\n"); ++ es8323->hp_det_gpio = INVALID_GPIO; ++ } else { ++ es8323->hp_det_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ ret = devm_gpio_request_one(&i2c->dev, es8323->hp_det_gpio, GPIOF_IN, NULL); ++ if (ret != 0) { ++ dev_err(&i2c->dev, "Failed to request hp_det_gpio\n"); ++ return ret; ++ } ++ } ++ ++ es8323->aux_det_gpio = of_get_named_gpio_flags(i2c->dev.of_node, "aux-det-gpio", 0, &flags); ++ if (es8323->aux_det_gpio < 0) { ++ dev_info(&i2c->dev, "Can not read property aux_det_gpio\n"); ++ es8323->aux_det_gpio = INVALID_GPIO; ++ } else { ++ ret = devm_gpio_request_one(&i2c->dev, es8323->aux_det_gpio, GPIOF_IN, NULL); ++ if (ret != 0) { ++ dev_err(&i2c->dev, "Failed to request aux_det_gpio\n"); ++ return ret; ++ } ++ es8323->aux_det_irq = gpio_to_irq(es8323->aux_det_gpio); ++ ++ if (es8323->aux_det_irq) { ++ ret = devm_request_threaded_irq(&i2c->dev, es8323->aux_det_irq, NULL, aux_det_isr, ++ IRQ_TYPE_EDGE_BOTH | IRQF_ONESHOT, "ES8323", NULL); ++ if (ret < 0) { ++ dev_err(&i2c->dev, "request_irq failed: %d\n", ret); ++ return ret; ++ } ++ disable_irq(es8323->aux_det_irq); ++ } ++ } ++ ++ ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_es8323, &es8323_dai, 1); ++ ++ return ret; ++} ++ ++static const struct i2c_device_id es8323_i2c_id[] = { ++ {"es8323", 0}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(i2c, es8323_i2c_id); ++ ++void es8323_i2c_shutdown(struct i2c_client *client) ++{ ++ struct es8323_priv *es8323 = es8323_private; ++ ++ es8323_set_gpio(ES8323_CODEC_SET_SPK, !es8323->spk_gpio_level); ++ es8323_set_gpio(ES8323_CODEC_SET_HP, !es8323->hp_gpio_level); ++ mdelay(20); ++ snd_soc_component_write(es8323_component, ES8323_CONTROL2, 0x58); ++ snd_soc_component_write(es8323_component, ES8323_CONTROL1, 0x32); ++ snd_soc_component_write(es8323_component, ES8323_CHIPPOWER, 0xf3); ++ snd_soc_component_write(es8323_component, ES8323_DACPOWER, 0xc0); ++ mdelay(50); ++ snd_soc_component_write(es8323_component, ES8323_DACCONTROL26, 0x00); ++ snd_soc_component_write(es8323_component, ES8323_DACCONTROL27, 0x00); ++ mdelay(50); ++ snd_soc_component_write(es8323_component, ES8323_CONTROL1, 0x30); ++ snd_soc_component_write(es8323_component, ES8323_CONTROL1, 0x34); ++} ++ ++static const struct of_device_id es8323_of_match[] = { ++ { .compatible = "everest,es8323", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, es8323_of_match); ++ ++static struct i2c_driver es8323_i2c_driver = { ++ .driver = { ++ .name = "ES8323", ++ .of_match_table = of_match_ptr(es8323_of_match), ++ }, ++ .shutdown = es8323_i2c_shutdown, ++ .probe = es8323_i2c_probe, ++ .id_table = es8323_i2c_id, ++}; ++module_i2c_driver(es8323_i2c_driver); ++ ++MODULE_DESCRIPTION("ASoC es8323 driver"); ++MODULE_AUTHOR("Mark Brown "); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/codecs/es8323.h b/sound/soc/codecs/es8323.h +new file mode 100755 +index 000000000000..22dafdc9c50c +--- /dev/null ++++ b/sound/soc/codecs/es8323.h +@@ -0,0 +1,144 @@ ++/* ++ * Copyright 2005 Openedhand Ltd. ++ * ++ * Author: Richard Purdie ++ * ++ * Based on ES8323.h ++ * ++ * 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. ++ * ++ */ ++ ++#ifndef _ES8323_H ++#define _ES8323_H ++ ++/* ES8323 register space */ ++ ++#define ES8323_CONTROL1 0x00 ++#define ES8323_CONTROL2 0x01 ++#define ES8323_CHIPPOWER 0x02 ++#define ES8323_ADCPOWER 0x03 ++#define ES8323_DACPOWER 0x04 ++#define ES8323_CHIPLOPOW1 0x05 ++#define ES8323_CHIPLOPOW2 0x06 ++#define ES8323_ANAVOLMANAG 0x07 ++#define ES8323_MASTERMODE 0x08 ++#define ES8323_ADCCONTROL1 0x09 ++#define ES8323_ADCCONTROL2 0x0a ++#define ES8323_ADCCONTROL3 0x0b ++#define ES8323_ADCCONTROL4 0x0c ++#define ES8323_ADCCONTROL5 0x0d ++#define ES8323_ADCCONTROL6 0x0e ++#define ES8323_ADCCONTROL7 0x0f ++#define ES8323_ADCCONTROL8 0x10 ++#define ES8323_ADCCONTROL9 0x11 ++#define ES8323_ADCCONTROL10 0x12 ++#define ES8323_ADCCONTROL11 0x13 ++#define ES8323_ADCCONTROL12 0x14 ++#define ES8323_ADCCONTROL13 0x15 ++#define ES8323_ADCCONTROL14 0x16 ++ ++#define ES8323_DACCONTROL1 0x17 ++#define ES8323_DACCONTROL2 0x18 ++#define ES8323_DACCONTROL3 0x19 ++#define ES8323_DACCONTROL4 0x1a ++#define ES8323_DACCONTROL5 0x1b ++#define ES8323_DACCONTROL6 0x1c ++#define ES8323_DACCONTROL7 0x1d ++#define ES8323_DACCONTROL8 0x1e ++#define ES8323_DACCONTROL9 0x1f ++#define ES8323_DACCONTROL10 0x20 ++#define ES8323_DACCONTROL11 0x21 ++#define ES8323_DACCONTROL12 0x22 ++#define ES8323_DACCONTROL13 0x23 ++#define ES8323_DACCONTROL14 0x24 ++#define ES8323_DACCONTROL15 0x25 ++#define ES8323_DACCONTROL16 0x26 ++#define ES8323_DACCONTROL17 0x27 ++#define ES8323_DACCONTROL18 0x28 ++#define ES8323_DACCONTROL19 0x29 ++#define ES8323_DACCONTROL20 0x2a ++#define ES8323_DACCONTROL21 0x2b ++#define ES8323_DACCONTROL22 0x2c ++#define ES8323_DACCONTROL23 0x2d ++#define ES8323_DACCONTROL24 0x2e ++#define ES8323_DACCONTROL25 0x2f ++#define ES8323_DACCONTROL26 0x30 ++#define ES8323_DACCONTROL27 0x31 ++#define ES8323_DACCONTROL28 0x32 ++#define ES8323_DACCONTROL29 0x33 ++#define ES8323_DACCONTROL30 0x34 ++ ++#define ES8323_LADC_VOL ES8323_ADCCONTROL8 ++#define ES8323_RADC_VOL ES8323_ADCCONTROL9 ++ ++#define ES8323_LDAC_VOL ES8323_DACCONTROL4 ++#define ES8323_RDAC_VOL ES8323_DACCONTROL5 ++ ++#define ES8323_LOUT1_VOL ES8323_DACCONTROL24 ++#define ES8323_ROUT1_VOL ES8323_DACCONTROL25 ++#define ES8323_LOUT2_VOL ES8323_DACCONTROL26 ++#define ES8323_ROUT2_VOL ES8323_DACCONTROL27 ++ ++#define ES8323_ADC_MUTE ES8323_ADCCONTROL7 ++#define ES8323_DAC_MUTE ES8323_DACCONTROL3 ++ ++#define ES8323_IFACE ES8323_MASTERMODE ++ ++#define ES8323_ADC_IFACE ES8323_ADCCONTROL4 ++#define ES8323_ADC_SRATE ES8323_ADCCONTROL5 ++ ++#define ES8323_DAC_IFACE ES8323_DACCONTROL1 ++#define ES8323_DAC_SRATE ES8323_DACCONTROL2 ++ ++#define ES8323_CACHEREGNUM 53 ++#define ES8323_SYSCLK 0 ++ ++#define ES8323_PLL1 0 ++#define ES8323_PLL2 1 ++ ++/* clock inputs */ ++#define ES8323_MCLK 0 ++#define ES8323_PCMCLK 1 ++ ++/* clock divider id's */ ++#define ES8323_PCMDIV 0 ++#define ES8323_BCLKDIV 1 ++#define ES8323_VXCLKDIV 2 ++ ++/* PCM clock dividers */ ++#define ES8323_PCM_DIV_1 (0 << 6) ++#define ES8323_PCM_DIV_3 (2 << 6) ++#define ES8323_PCM_DIV_5_5 (3 << 6) ++#define ES8323_PCM_DIV_2 (4 << 6) ++#define ES8323_PCM_DIV_4 (5 << 6) ++#define ES8323_PCM_DIV_6 (6 << 6) ++#define ES8323_PCM_DIV_8 (7 << 6) ++ ++/* BCLK clock dividers */ ++#define ES8323_BCLK_DIV_1 (0 << 7) ++#define ES8323_BCLK_DIV_2 (1 << 7) ++#define ES8323_BCLK_DIV_4 (2 << 7) ++#define ES8323_BCLK_DIV_8 (3 << 7) ++ ++/* VXCLK clock dividers */ ++#define ES8323_VXCLK_DIV_1 (0 << 6) ++#define ES8323_VXCLK_DIV_2 (1 << 6) ++#define ES8323_VXCLK_DIV_4 (2 << 6) ++#define ES8323_VXCLK_DIV_8 (3 << 6) ++#define ES8323_VXCLK_DIV_16 (4 << 6) ++ ++#define ES8323_DAI_HIFI 0 ++#define ES8323_DAI_VOICE 1 ++ ++#define ES8323_1536FS 1536 ++#define ES8323_1024FS 1024 ++#define ES8323_768FS 768 ++#define ES8323_512FS 512 ++#define ES8323_384FS 384 ++#define ES8323_256FS 256 ++#define ES8323_128FS 128 ++ ++#endif diff --git a/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0004-panel.patch b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0004-panel.patch new file mode 100644 index 000000000..7a8a6068f --- /dev/null +++ b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0004-panel.patch @@ -0,0 +1,338 @@ +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index af1402d83d51..d3d2f0e32ace 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -619,4 +619,17 @@ config DRM_PANEL_XINPENG_XPP055C272 + Say Y here if you want to enable support for the Xinpeng + XPP055C272 controller for 720x1280 LCD panels with MIPI/RGB/SPI + system interfaces. ++ ++config DRM_PANEL_CWD686 ++ tristate "CWD686 panel" ++ depends on OF ++ depends on DRM_MIPI_DSI ++ depends on BACKLIGHT_CLASS_DEVICE ++ help ++ Say Y here if you want to enable support for CWD686 panel. ++ The panel has a 480x1280 resolution and uses 24 bit RGB per pixel. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called panel-cwd686. ++ + endmenu +diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile +index c8132050bcec..fe1cfdb68186 100644 +--- a/drivers/gpu/drm/panel/Makefile ++++ b/drivers/gpu/drm/panel/Makefile +@@ -64,3 +64,4 @@ obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o + obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o + obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o + obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o ++obj-$(CONFIG_DRM_PANEL_CWD686) += panel-cwd686.o +diff --git a/drivers/gpu/drm/panel/panel-cwd686.c b/drivers/gpu/drm/panel/panel-cwd686.c +new file mode 100644 +index 000000000000..6a0eabf929b9 +--- /dev/null ++++ b/drivers/gpu/drm/panel/panel-cwd686.c +@@ -0,0 +1,301 @@ ++/* ++ * SPDX-License-Identifier: GPL-2.0+ ++ * Copyright (c) 2021 Clockwork Tech LLC ++ * Copyright (c) 2021 Max Fierke ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct cwd686 { ++ struct device *dev; ++ struct drm_panel panel; ++ struct regulator *supply; ++ struct gpio_desc *enable_gpio; ++ struct gpio_desc *reset_gpio; ++ struct backlight_device *backlight; ++ bool prepared; ++ bool enabled; ++ enum drm_panel_orientation orientation; ++}; ++ ++static const struct drm_display_mode default_mode = { ++ .clock = 54465, ++ .hdisplay = 480, ++ .hsync_start = 480 + 150, ++ .hsync_end = 480 + 150 + 24, ++ .htotal = 480 + 150 + 24 + 40, ++ .vdisplay = 1280, ++ .vsync_start = 1280 + 12, ++ .vsync_end = 1280 + 12 + 6, ++ .vtotal = 1280 + 12 + 6 + 10, ++}; ++ ++static inline struct cwd686 *panel_to_cwd686(struct drm_panel *panel) ++{ ++ return container_of(panel, struct cwd686, panel); ++} ++ ++#define dcs_write_seq(seq...) \ ++({ \ ++ static const u8 d[] = { seq }; \ ++ mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \ ++}) ++ ++static void cwd686_init_sequence(struct cwd686 *ctx) ++{ ++ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); ++ ++ dcs_write_seq(0xF0,0x5A,0x5A); // Password1 (Enable Level 2 registers) ++ dcs_write_seq(0xF1,0xA5,0xA5); // Password2 (Enable Level 2 registers) ++ dcs_write_seq(0xB6,0x0D,0x0D); // PWRCON_VCOM (-0.495V ?, -0.495V ?) ++ dcs_write_seq(0xB4,0x0A,0x08,0x12,0x10,0x0E,0x0C,0x00,0x00,0x00,0x03,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x06); // CGOUTR (set ASG Output signals) ++ dcs_write_seq(0xB3,0x0B,0x09,0x13,0x11,0x0F,0x0D,0x00,0x00,0x00,0x03,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x07); // CGOUTL (set ASG Output signals) ++ dcs_write_seq(0xB0,0x54,0x32,0x23,0x45,0x44,0x44,0x44,0x44,0x90,0x01,0x90,0x01); // ??? ++ dcs_write_seq(0xB1,0x32,0x84,0x02,0x83,0x30,0x01,0x6B,0x01); // ??? ++ dcs_write_seq(0xB2,0x73); // ??? ++ dcs_write_seq(0xBD,0x4E,0x0E,0x50,0x50,0x26,0x1D,0x00,0x14,0x42,0x03); // PWRCON_REG ++ dcs_write_seq(0xB7,0x01,0x01,0x09,0x11,0x0D,0x55,0x19,0x19,0x21,0x1D,0x00,0x00,0x00,0x00,0x02,0xFF,0x3C); // PWRCON_SEQ ++ dcs_write_seq(0xB8,0x23,0x01,0x30,0x34,0x63); // PWRCON_CLK ++ dcs_write_seq(0xB9,0xA0,0x22,0x00,0x44); // PWRCON_BAT (Disable abnormal power-off?) ++ dcs_write_seq(0xBA,0x12,0x63); // PWRCON_MODE ++ dcs_write_seq(0xC1,0x0C,0x16,0x04,0x0C,0x10,0x04); // TCON (Set VBP, VFP, VSW, HBP, HFP, HSW) ++ dcs_write_seq(0xC2,0x11,0x41); // TCON2 (Set resolution) ++ dcs_write_seq(0xC3,0x22,0x31,0x04); // TCON3 (Set frame blanking) ++ dcs_write_seq(0xC7,0x05,0x23,0x6B,0x49,0x00); // SRCCON ++ dcs_write_seq(0xC5,0x00); // ??? ++ dcs_write_seq(0xD0,0x37,0xFF,0xFF); // ABNO_CTR (Set MIPI abnormal state) ++ dcs_write_seq(0xD2,0x63,0x0B,0x08,0x88); // ??? ++ dcs_write_seq(0xD3,0x01,0x00,0x00,0x01,0x01,0x37,0x25,0x38,0x31,0x06,0x07); // ??? ++ dcs_write_seq(0xC8,0x7C,0x6A,0x5D,0x53,0x53,0x45,0x4B,0x35,0x4D,0x4A,0x49,0x66,0x53,0x57,0x4A,0x48,0x3B,0x2A,0x06,0x7C,0x6A,0x5D,0x53,0x53,0x45,0x4B,0x35,0x4D,0x4A,0x49,0x66,0x53,0x57,0x4A,0x48,0x3B,0x2A,0x06); // GAMMA2.2 ++ dcs_write_seq(0xC6,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00); // SRC_TIM (Set source timing) ++ dcs_write_seq(0xF4,0x08,0x77); // ??? ++ dcs_write_seq(0x36,0x14); // MADCTL (Set display direction) ++ dcs_write_seq(0x35,0x00); // TEON (Disable tearing effect ?) ++ dcs_write_seq(0xF1,0x5A,0x5A); // Password1 (Enable Level 2 registers), again for some reason ?? ++ dcs_write_seq(0xF0,0xA5,0xA5); // Password2 (Enable Level 2 registers), again for some reason ?? ++} ++ ++static int cwd686_disable(struct drm_panel *panel) ++{ ++ struct cwd686 *ctx = panel_to_cwd686(panel); ++ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); ++ int ret; ++ ++ if (!ctx->enabled) ++ return 0; ++ ++ backlight_disable(ctx->backlight); ++ ++ ctx->enabled = false; ++ ++ return 0; ++} ++ ++static int cwd686_unprepare(struct drm_panel *panel) ++{ ++ struct cwd686 *ctx = panel_to_cwd686(panel); ++ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); ++ int ret; ++ ++ if (!ctx->prepared) ++ return 0; ++ ++ ret = mipi_dsi_dcs_set_display_off(dsi); ++ if (ret) { ++ dev_err(ctx->dev, "failed to turn display off (%d)\n", ret); ++ return ret; ++ } ++ ++ ret = mipi_dsi_dcs_enter_sleep_mode(dsi); ++ if (ret) { ++ dev_err(ctx->dev, "failed to enter sleep mode (%d)\n", ret); ++ return ret; ++ } ++ msleep(120); ++ ++ gpiod_set_value_cansleep(ctx->reset_gpio, 0); ++ msleep(5); ++ ++ ctx->prepared = false; ++ ++ return 0; ++} ++ ++static int cwd686_prepare(struct drm_panel *panel) ++{ ++ struct cwd686 *ctx = panel_to_cwd686(panel); ++ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); ++ int ret; ++ ++ if (ctx->prepared) ++ return 0; ++ ++ gpiod_set_value_cansleep(ctx->reset_gpio, 0); ++ msleep(10); ++ gpiod_set_value_cansleep(ctx->reset_gpio, 1); ++ msleep(120); ++ ++ /* Enabe tearing mode: send TE (tearing effect) at VBLANK */ ++ ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); ++ if (ret) { ++ dev_err(ctx->dev, "failed to enable vblank TE (%d)\n", ret); ++ return ret; ++ } ++ /* Exit sleep mode and power on */ ++ ++ cwd686_init_sequence(ctx); ++ ++ ret = mipi_dsi_dcs_exit_sleep_mode(dsi); ++ if (ret) { ++ dev_err(ctx->dev, "failed to exit sleep mode (%d)\n", ret); ++ return ret; ++ } ++ msleep(120); ++ ++ ret = mipi_dsi_dcs_set_display_on(dsi); ++ if (ret) { ++ dev_err(ctx->dev, "failed to turn display on (%d)\n", ret); ++ return ret; ++ } ++ msleep(20); ++ ++ ctx->prepared = true; ++ ++ return 0; ++} ++ ++static int cwd686_enable(struct drm_panel *panel) ++{ ++ struct cwd686 *ctx = panel_to_cwd686(panel); ++ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); ++ int ret; ++ ++ if (ctx->enabled) ++ return 0; ++ ++ backlight_enable(ctx->backlight); ++ ++ ctx->enabled = true; ++ ++ return 0; ++} ++ ++static int cwd686_get_modes(struct drm_panel *panel, struct drm_connector *connector) ++{ ++ struct cwd686 *ctx = panel_to_cwd686(panel); ++ struct drm_display_mode *mode; ++ ++ mode = drm_mode_duplicate(connector->dev, &default_mode); ++ if (!mode) { ++ dev_err(panel->dev, "bad mode or failed to add mode\n"); ++ return -EINVAL; ++ } ++ drm_mode_set_name(mode); ++ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; ++ ++ connector->display_info.width_mm = mode->width_mm; ++ connector->display_info.height_mm = mode->height_mm; ++ ++ /* set up connector's "panel orientation" property */ ++ drm_connector_set_panel_orientation(connector, ctx->orientation); ++ ++ drm_mode_probed_add(connector, mode); ++ ++ return 1; /* Number of modes */ ++} ++ ++static const struct drm_panel_funcs cwd686_drm_funcs = { ++ .disable = cwd686_disable, ++ .unprepare = cwd686_unprepare, ++ .prepare = cwd686_prepare, ++ .enable = cwd686_enable, ++ .get_modes = cwd686_get_modes, ++}; ++ ++static int cwd686_probe(struct mipi_dsi_device *dsi) ++{ ++ struct device *dev = &dsi->dev; ++ struct cwd686 *ctx; ++ int ret; ++ ++ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ mipi_dsi_set_drvdata(dsi, ctx); ++ ctx->dev = dev; ++ ++ dsi->lanes = 4; ++ dsi->format = MIPI_DSI_FMT_RGB888; ++ dsi->mode_flags = MIPI_DSI_MODE_VIDEO |MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; ++ ++ ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR(ctx->reset_gpio)) { ++ ret = PTR_ERR(ctx->reset_gpio); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to request GPIO (%d)\n", ret); ++ return ret; ++ } ++ ++ ctx->backlight = devm_of_find_backlight(dev); ++ if (IS_ERR(ctx->backlight)) { ++ return PTR_ERR(ctx->backlight); ++ } ++ ++ ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); ++ if (ret) { ++ dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, ret); ++ return ret; ++ } ++ ++ drm_panel_init(&ctx->panel, dev, &cwd686_drm_funcs, DRM_MODE_CONNECTOR_DSI); ++ ++ drm_panel_add(&ctx->panel); ++ ++ ret = mipi_dsi_attach(dsi); ++ if (ret < 0) { ++ dev_err(dev, "mipi_dsi_attach() failed: %d\n", ret); ++ drm_panel_remove(&ctx->panel); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int cwd686_remove(struct mipi_dsi_device *dsi) ++{ ++ struct cwd686 *ctx = mipi_dsi_get_drvdata(dsi); ++ ++ mipi_dsi_detach(dsi); ++ drm_panel_remove(&ctx->panel); ++ ++ return 0; ++} ++ ++static const struct of_device_id cwd686_of_match[] = { ++ { .compatible = "cw,cwd686" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, cwd686_of_match); ++ ++static struct mipi_dsi_driver cwd686_driver = { ++ .probe = cwd686_probe, ++ .remove = cwd686_remove, ++ .driver = { ++ .name = "panel-cwd686", ++ .of_match_table = cwd686_of_match, ++ }, ++}; ++module_mipi_dsi_driver(cwd686_driver); ++ ++MODULE_DESCRIPTION("DRM Driver for cwd686 MIPI DSI panel"); ++MODULE_LICENSE("GPL v2"); diff --git a/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0005-backlight.patch b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0005-backlight.patch new file mode 100644 index 000000000..27976ced0 --- /dev/null +++ b/patch/kernel/archive/rockchip64-5.15/add-board-clockworkpi-a06-0005-backlight.patch @@ -0,0 +1,309 @@ +diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig +index e32694c13da5..a54a4b44c53f 100644 +--- a/drivers/video/backlight/Kconfig ++++ b/drivers/video/backlight/Kconfig +@@ -464,6 +464,12 @@ config BACKLIGHT_LED + If you have a LCD backlight adjustable by LED class driver, say Y + to enable this driver. + ++config BACKLIGHT_OCP8178 ++ tristate "OCP8178 Backlight Driver" ++ depends on GPIOLIB ++ help ++ If you have an OCP8178, say Y to enable the backlight driver. ++ + endif # BACKLIGHT_CLASS_DEVICE + + endmenu +diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile +index cae2c83422ae..09733ff0d68e 100644 +--- a/drivers/video/backlight/Makefile ++++ b/drivers/video/backlight/Makefile +@@ -58,3 +58,4 @@ obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o + obj-$(CONFIG_BACKLIGHT_ARCXCNN) += arcxcnn_bl.o + obj-$(CONFIG_BACKLIGHT_RAVE_SP) += rave-sp-backlight.o + obj-$(CONFIG_BACKLIGHT_LED) += led_bl.o ++obj-$(CONFIG_BACKLIGHT_OCP8178) += ocp8178_bl.o +diff --git a/drivers/video/backlight/ocp8178_bl.c b/drivers/video/backlight/ocp8178_bl.c +new file mode 100644 +index 000000000000..db8db1771644 +--- /dev/null ++++ b/drivers/video/backlight/ocp8178_bl.c +@@ -0,0 +1,277 @@ ++/* ++ * ocp8178_bl.c - ocp8178 backlight driver ++ * ++ * 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 ++#include ++#include ++#include /* Only for legacy support */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ocp8178_backlight { ++ struct device *dev; ++ struct device *fbdev; ++ ++ struct gpio_desc *gpiod; ++ int def_value; ++ int current_value; ++}; ++ ++#define DETECT_DELAY 200 ++#define DETECT_TIME 500 ++#define DETECT_WINDOW_TIME 1000 ++#define START_TIME 10 ++#define END_TIME 10 ++#define SHUTDOWN_TIME 3000 ++#define LOW_BIT_HIGH_TIME 10 ++#define LOW_BIT_LOW_TIME 50 ++#define HIGH_BIT_HIGH_TIME 50 ++#define HIGH_BIT_LOW_TIME 10 ++#define MAX_BRIGHTNESS_VALUE 9 ++ ++static void entry_1wire_mode(struct ocp8178_backlight *gbl) ++{ ++ unsigned long flags = 0; ++ local_irq_save(flags); ++ gpiod_set_value(gbl->gpiod, 0); ++ mdelay(SHUTDOWN_TIME/1000); ++ gpiod_set_value(gbl->gpiod, 1); ++ udelay(DETECT_DELAY); ++ gpiod_set_value(gbl->gpiod, 0); ++ udelay(DETECT_TIME); ++ gpiod_set_value(gbl->gpiod, 1); ++ udelay(DETECT_WINDOW_TIME); ++ local_irq_restore(flags); ++} ++ ++static inline void write_bit(struct ocp8178_backlight *gbl, int bit) ++{ ++ if (bit) { ++ gpiod_set_value(gbl->gpiod, 0); ++ udelay(HIGH_BIT_LOW_TIME); ++ gpiod_set_value(gbl->gpiod, 1); ++ udelay(HIGH_BIT_HIGH_TIME); ++ } else { ++ gpiod_set_value(gbl->gpiod, 0); ++ udelay(LOW_BIT_LOW_TIME); ++ gpiod_set_value(gbl->gpiod, 1); ++ udelay(LOW_BIT_HIGH_TIME); ++ } ++} ++ ++static void write_byte(struct ocp8178_backlight *gbl, int byte) ++{ ++ unsigned long flags = 0; ++ unsigned char data = 0x72; ++ int i; ++ ++ local_irq_save(flags); ++ ++ gpiod_set_value(gbl->gpiod, 1); ++ udelay(START_TIME); ++ for(i = 0; i < 8; i++) { ++ if(data & 0x80) { ++ write_bit(gbl, 1); ++ } else { ++ write_bit(gbl, 0); ++ } ++ data <<= 1; ++ } ++ gpiod_set_value(gbl->gpiod, 0); ++ udelay(END_TIME); ++ ++ data = byte & 0x1f; ++ ++ gpiod_set_value(gbl->gpiod, 1); ++ udelay(START_TIME); ++ for(i = 0; i < 8; i++) { ++ if(data & 0x80) { ++ write_bit(gbl, 1); ++ } else { ++ write_bit(gbl, 0); ++ } ++ data <<= 1; ++ } ++ gpiod_set_value(gbl->gpiod, 0); ++ udelay(END_TIME); ++ gpiod_set_value(gbl->gpiod, 1); ++ ++ local_irq_restore(flags); ++} ++ ++unsigned char ocp8178_bl_table[MAX_BRIGHTNESS_VALUE+1] = {0, 1, 4, 8, 12, 16, 20, 24, 28, 31}; ++ ++static int ocp8178_update_status(struct backlight_device *bl) ++{ ++ struct ocp8178_backlight *gbl = bl_get_data(bl); ++ int brightness = bl->props.brightness, i; ++ ++ if (bl->props.power != FB_BLANK_UNBLANK || ++ bl->props.fb_blank != FB_BLANK_UNBLANK || ++ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) ++ brightness = 0; ++ ++ if(brightness > MAX_BRIGHTNESS_VALUE) ++ brightness = MAX_BRIGHTNESS_VALUE; ++ ++ for(i = 0; i < 2; i++) { ++ entry_1wire_mode(gbl); ++ write_byte(gbl, ocp8178_bl_table[brightness]); ++ } ++ gbl->current_value = brightness; ++ ++ return 0; ++} ++ ++static int ocp8178_get_brightness(struct backlight_device *bl) ++{ ++ struct ocp8178_backlight *gbl = bl_get_data(bl); ++ return gbl->current_value; ++} ++ ++static int ocp8178_check_fb(struct backlight_device *bl, ++ struct fb_info *info) ++{ ++ struct ocp8178_backlight *gbl = bl_get_data(bl); ++ return gbl->fbdev == NULL || gbl->fbdev == info->dev; ++} ++ ++static const struct backlight_ops ocp8178_backlight_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .update_status = ocp8178_update_status, ++ .get_brightness = ocp8178_get_brightness, ++ .check_fb = ocp8178_check_fb, ++}; ++ ++static int ocp8178_probe_dt(struct platform_device *pdev, ++ struct ocp8178_backlight *gbl) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ enum gpiod_flags flags; ++ int ret = 0; ++ u32 value32; ++ ++ of_property_read_u32(np, "default-brightness", &value32); ++ if(value32 > MAX_BRIGHTNESS_VALUE) ++ gbl->def_value = MAX_BRIGHTNESS_VALUE; ++ else ++ gbl->def_value = value32; ++ flags = gbl->def_value ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; ++ ++ gbl->gpiod = devm_gpiod_get(dev, "backlight-control", flags); ++ if (IS_ERR(gbl->gpiod)) { ++ ret = PTR_ERR(gbl->gpiod); ++ ++ if (ret != -EPROBE_DEFER) { ++ dev_err(dev, ++ "Error: The gpios parameter is missing or invalid.\n"); ++ } ++ } ++ ++ return ret; ++} ++ ++static struct backlight_device *backlight; ++ ++static int ocp8178_probe(struct platform_device *pdev) ++{ ++ struct backlight_properties props; ++ struct backlight_device *bl; ++ struct ocp8178_backlight *gbl; ++ struct device_node *np = pdev->dev.of_node; ++ int ret; ++ ++ if ( !np) { ++ dev_err(&pdev->dev, ++ "failed to find platform data or device tree node.\n"); ++ return -ENODEV; ++ } ++ ++ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); ++ if (gbl == NULL) ++ return -ENOMEM; ++ ++ gbl->dev = &pdev->dev; ++ ++ ret = ocp8178_probe_dt(pdev, gbl); ++ if (ret) ++ return ret; ++ ++ gbl->current_value = gbl->def_value; ++ ++ memset(&props, 0, sizeof(props)); ++ props.type = BACKLIGHT_RAW; ++ props.max_brightness = MAX_BRIGHTNESS_VALUE; ++ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), ++ &pdev->dev, gbl, &ocp8178_backlight_ops, ++ &props); ++ if (IS_ERR(bl)) { ++ dev_err(&pdev->dev, "failed to register backlight\n"); ++ return PTR_ERR(bl); ++ } ++ ++// entry_1wire_mode(gbl); ++ ++ bl->props.brightness = gbl->def_value; ++ backlight_update_status(bl); ++ ++ platform_set_drvdata(pdev, bl); ++ ++ backlight = bl; ++ return 0; ++} ++ ++static int ocp8178_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ return 0; ++} ++ ++static int ocp8178_resume(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static struct of_device_id ocp8178_of_match[] = { ++ { .compatible = "ocp8178-backlight" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, ocp8178_of_match); ++ ++static struct platform_driver ocp8178_driver = { ++ .driver = { ++ .name = "ocp8178-backlight", ++ .of_match_table = of_match_ptr(ocp8178_of_match), ++ }, ++ .probe = ocp8178_probe, ++ .suspend = ocp8178_suspend, ++ .resume = ocp8178_resume, ++}; ++ ++module_platform_driver(ocp8178_driver); ++ ++MODULE_DESCRIPTION("OCP8178 Driver"); ++MODULE_LICENSE("GPL"); diff --git a/patch/kernel/archive/rockchip64-5.15/add-boards-to-dts-makefile.patch b/patch/kernel/archive/rockchip64-5.15/add-boards-to-dts-makefile.patch index a1cef21cc..99a84493a 100644 --- a/patch/kernel/archive/rockchip64-5.15/add-boards-to-dts-makefile.patch +++ b/patch/kernel/archive/rockchip64-5.15/add-boards-to-dts-makefile.patch @@ -2,7 +2,7 @@ diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchi index 26661c7b7..1462ed38b 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -1,4 +1,20 @@ +@@ -1,4 +1,21 @@ # SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-pc.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock-pi-e.dtb @@ -13,6 +13,7 @@ index 26661c7b7..1462ed38b 100644 +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-z28pro.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-clockworkpi-a06.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-kobol-helios64.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4v2.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-r4s.dtb diff --git a/patch/u-boot/u-boot-rockchip64/add-board-clockworkpi-a06-0001-uboot.patch b/patch/u-boot/u-boot-rockchip64/add-board-clockworkpi-a06-0001-uboot.patch new file mode 100644 index 000000000..a420a3b08 --- /dev/null +++ b/patch/u-boot/u-boot-rockchip64/add-board-clockworkpi-a06-0001-uboot.patch @@ -0,0 +1,272 @@ +diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile +index 9fb38682e6..a6d8361602 100644 +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -120,6 +120,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3368) += \ + rk3368-px5-evb.dtb \ + + dtb-$(CONFIG_ROCKCHIP_RK3399) += \ ++ rk3399-clockworkpi-a06.dtb \ + rk3399-evb.dtb \ + rk3399-ficus.dtb \ + rk3399-firefly.dtb \ +diff --git a/arch/arm/dts/rk3399-clockworkpi-a06-u-boot.dtsi b/arch/arm/dts/rk3399-clockworkpi-a06-u-boot.dtsi +new file mode 100644 +index 0000000000..82d4a5db44 +--- /dev/null ++++ b/arch/arm/dts/rk3399-clockworkpi-a06-u-boot.dtsi +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++#include "rk3399-u-boot.dtsi" ++#include "rk3399-sdram-lpddr4-100.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc; ++ }; ++}; ++ ++&i2c0 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&rk808 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&sdmmc { ++ u-boot,dm-pre-reloc; ++}; +diff --git a/arch/arm/dts/rk3399-clockworkpi-a06.dts b/arch/arm/dts/rk3399-clockworkpi-a06.dts +new file mode 100644 +index 0000000000..b32b74abb5 +--- /dev/null ++++ b/arch/arm/dts/rk3399-clockworkpi-a06.dts +@@ -0,0 +1,162 @@ ++/* ++ * (C) Copyright 2016 Rockchip Electronics Co., Ltd ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++/dts-v1/; ++#include ++#include ++#include "rk3399.dtsi" ++#include "rk3399-opp.dtsi" ++ ++/ { ++ model = "Clockworkpi A06"; ++ compatible = "clockwork,devterm-a06", "rockchip,rk3399"; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ vdd_center: vdd-center { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm3 0 25000 1>; ++ regulator-name = "vdd_center"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-init-microvolt = <950000>; ++ regulator-always-on; ++ regulator-boot-on; ++ status = "okay"; ++ }; ++ ++ vccsys: vccsys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vccsys"; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc5v0_host: vcc5v0-host-en { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_host"; ++ gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ vcc5v0_typec0: vcc5v0-typec0-en { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_typec0"; ++ gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ vcc5v0_typec1: vcc5v0-typec1-en { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_typec1"; ++ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; ++ }; ++ ++}; ++ ++&saradc { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ mmc-hs400-1_8v; ++ mmc-hs400-enhanced-strobe; ++ non-removable; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ clock-frequency = <400000>; ++ i2c-scl-falling-time-ns = <50>; ++ i2c-scl-rising-time-ns = <100>; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ clock-output-names = "xin32k", "wifibt_32kin"; ++ interrupt-parent = <&gpio0>; ++ interrupts = <4 IRQ_TYPE_LEVEL_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ reg = <0x1b>; ++ rockchip,system-power-controller; ++ #clock-cells = <1>; ++ status = "okay"; ++ ++ vcc12-supply = <&vcc3v3_sys>; ++ ++ regulators { ++ vcc33_lcd: SWITCH_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc33_lcd"; ++ }; ++ }; ++ }; ++}; ++ ++&pinctrl { ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = ++ <1 21 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ pmic_dvs2: pmic-dvs2 { ++ rockchip,pins = ++ <1 18 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++}; +diff --git a/configs/clockworkpi-a06-rk3399_defconfig b/configs/clockworkpi-a06-rk3399_defconfig +new file mode 100644 +index 0000000000..398ed3592f +--- /dev/null ++++ b/configs/clockworkpi-a06-rk3399_defconfig +@@ -0,0 +1,54 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00200000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_ROCKCHIP_RK3399=y ++CONFIG_TARGET_EVB_RK3399=y ++CONFIG_DEBUG_UART_BASE=0xFF1A0000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3399-clockworkpi-a06" ++CONFIG_DEBUG_UART=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-clockworkpi-a06.dtb" ++CONFIG_MISC_INIT_R=y ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 ++CONFIG_TPL=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_RAM_RK3399_LPDDR4=y ++CONFIG_RAM_ROCKCHIP_DEBUG=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_DM_VIDEO=y ++CONFIG_DISPLAY=y ++CONFIG_VIDEO_ROCKCHIP=y ++CONFIG_DISPLAY_ROCKCHIP_HDMI=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y +-- +2.25.1 +