diff --git a/distributions/LibreELEC/splash/boot-logo.bmp.gz b/distributions/LibreELEC/splash/boot-logo.bmp.gz
new file mode 100644
index 0000000000..18885867c5
Binary files /dev/null and b/distributions/LibreELEC/splash/boot-logo.bmp.gz differ
diff --git a/packages/lang/gcc-linaro-aarch64-none-elf/package.mk b/packages/lang/gcc-linaro-aarch64-elf/package.mk
similarity index 74%
rename from packages/lang/gcc-linaro-aarch64-none-elf/package.mk
rename to packages/lang/gcc-linaro-aarch64-elf/package.mk
index 800e11c0ce..e63f448f34 100644
--- a/packages/lang/gcc-linaro-aarch64-none-elf/package.mk
+++ b/packages/lang/gcc-linaro-aarch64-elf/package.mk
@@ -16,14 +16,14 @@
# along with LibreELEC. If not, see .
################################################################################
-PKG_NAME="gcc-linaro-aarch64-none-elf"
-PKG_VERSION="4.9-2014.11-x86_64"
+PKG_NAME="gcc-linaro-aarch64-elf"
+PKG_VERSION="4.9-2016.02"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE=""
-PKG_URL="https://releases.linaro.org/14.11/components/toolchain/binaries/aarch64-none-elf/gcc-linaro-${PKG_VERSION}_aarch64-elf.tar.xz"
-PKG_SOURCE_DIR="gcc-linaro-${PKG_VERSION}_aarch64-elf"
+PKG_URL="https://releases.linaro.org/components/toolchain/binaries/${PKG_VERSION}/aarch64-elf/gcc-linaro-${PKG_VERSION}-x86_64_aarch64-elf.tar.xz"
+PKG_SOURCE_DIR="gcc-linaro-${PKG_VERSION}-x86_64_aarch64-elf"
PKG_DEPENDS_HOST="toolchain"
PKG_PRIORITY="optional"
PKG_SECTION="lang"
@@ -38,6 +38,6 @@ make_host() {
}
makeinstall_host() {
- mkdir -p $ROOT/$TOOLCHAIN/lib/gcc-linaro-aarch64-none-elf/
- cp -a * $ROOT/$TOOLCHAIN/lib/gcc-linaro-aarch64-none-elf
+ mkdir -p $ROOT/$TOOLCHAIN/lib/gcc-linaro-aarch64-elf/
+ cp -a * $ROOT/$TOOLCHAIN/lib/gcc-linaro-aarch64-elf
}
diff --git a/packages/lang/gcc-linaro-arm-eabi/package.mk b/packages/lang/gcc-linaro-arm-eabi/package.mk
new file mode 100644
index 0000000000..8c444bdbbb
--- /dev/null
+++ b/packages/lang/gcc-linaro-arm-eabi/package.mk
@@ -0,0 +1,43 @@
+################################################################################
+# This file is part of LibreELEC - https://libreelec.tv
+# Copyright (C) 2016 Team LibreELEC
+#
+# LibreELEC is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LibreELEC. If not, see .
+################################################################################
+
+PKG_NAME="gcc-linaro-arm-eabi"
+PKG_VERSION="4.9-2016.02"
+PKG_REV="1"
+PKG_ARCH="any"
+PKG_LICENSE="GPL"
+PKG_SITE=""
+PKG_URL="https://releases.linaro.org/components/toolchain/binaries/${PKG_VERSION}/arm-eabi/gcc-linaro-${PKG_VERSION}-x86_64_arm-eabi.tar.xz"
+PKG_SOURCE_DIR="gcc-linaro-${PKG_VERSION}-x86_64_arm-eabi"
+PKG_DEPENDS_HOST="toolchain"
+PKG_PRIORITY="optional"
+PKG_SECTION="lang"
+PKG_SHORTDESC=""
+PKG_LONGDESC=""
+
+PKG_IS_ADDON="no"
+PKG_AUTORECONF="no"
+
+make_host() {
+ :
+}
+
+makeinstall_host() {
+ mkdir -p $ROOT/$TOOLCHAIN/lib/gcc-linaro-arm-eabi/
+ cp -a * $ROOT/$TOOLCHAIN/lib/gcc-linaro-arm-eabi
+}
diff --git a/packages/tools/u-boot/package.mk b/packages/tools/u-boot/package.mk
index efe4074589..02353d5366 100644
--- a/packages/tools/u-boot/package.mk
+++ b/packages/tools/u-boot/package.mk
@@ -24,10 +24,10 @@ if [ "$UBOOT_VERSION" = "imx6-cuboxi" ]; then
# https://github.com/SolidRun/u-boot-imx6.git
PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz"
elif [ "$UBOOT_VERSION" = "hardkernel" ]; then
- PKG_VERSION="83bf8f0"
+ PKG_VERSION="61f29bb"
PKG_SITE="https://github.com/hardkernel/u-boot"
PKG_URL="https://github.com/hardkernel/u-boot/archive/$PKG_VERSION.tar.gz"
- PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET gcc-linaro-aarch64-none-elf:host"
+ PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET gcc-linaro-aarch64-elf:host gcc-linaro-arm-eabi:host"
else
exit 0
fi
@@ -67,10 +67,10 @@ make_target() {
for UBOOT_TARGET in $UBOOT_CONFIG; do
if [ "$PROJECT" = "Odroid_C2" ]; then
- export PATH=$ROOT/$TOOLCHAIN/lib/gcc-linaro-aarch64-none-elf/bin/:$PATH
- make CROSS_COMPILE=aarch64-none-elf- ARCH=arm mrproper
- make CROSS_COMPILE=aarch64-none-elf- ARCH=arm $UBOOT_TARGET
- make CROSS_COMPILE=aarch64-none-elf- ARCH=arm HOSTCC="$HOST_CC" HOSTSTRIP="true"
+ export PATH=$ROOT/$TOOLCHAIN/lib/gcc-linaro-aarch64-elf/bin/:$ROOT/$TOOLCHAIN/lib/gcc-linaro-arm-eabi/bin/:$PATH
+ CROSS_COMPILE=aarch64-elf- ARCH=arm CFLAGS="" LDFLAGS="" make mrproper
+ CROSS_COMPILE=aarch64-elf- ARCH=arm CFLAGS="" LDFLAGS="" make $UBOOT_TARGET
+ CROSS_COMPILE=aarch64-elf- ARCH=arm CFLAGS="" LDFLAGS="" make HOSTCC="$HOST_CC" HOSTSTRIP="true"
else
make CROSS_COMPILE="$TARGET_PREFIX" ARCH=arm mrproper
make CROSS_COMPILE="$TARGET_PREFIX" ARCH=arm $UBOOT_TARGET
@@ -129,8 +129,12 @@ makeinstall_target() {
case $PROJECT in
Odroid_C2)
cp -PRv $PKG_DIR/scripts/update-c2.sh $INSTALL/usr/share/bootloader/update.sh
- cp -PRv $ROOT/$PKG_BUILD/sd_fuse/bl1.bin.hardkernel $INSTALL/usr/share/bootloader/bl1
- cp -PRv $ROOT/$PKG_BUILD/sd_fuse/u-boot.bin $INSTALL/usr/share/bootloader/u-boot
+ cp -PRv $ROOT/$PKG_BUILD/u-boot.bin $INSTALL/usr/share/bootloader/u-boot
+ if [ -f $PROJECT_DIR/$PROJECT/splash/boot-logo.bmp.gz ]; then
+ cp -PRv $PROJECT_DIR/$PROJECT/splash/boot-logo.bmp.gz $INSTALL/usr/share/bootloader
+ elif [ -f $DISTRO_DIR/$DISTRO/splash/boot-logo.bmp.gz ]; then
+ cp -PRv $DISTRO_DIR/$DISTRO/splash/boot-logo.bmp.gz $INSTALL/usr/share/bootloader
+ fi
;;
imx6)
cp -PRv $PKG_DIR/scripts/update.sh $INSTALL/usr/share/bootloader
diff --git a/packages/tools/u-boot/patches/61f29bb/u-boot-0001-use-arm-eabi-for-bl301-scp_task.patch b/packages/tools/u-boot/patches/61f29bb/u-boot-0001-use-arm-eabi-for-bl301-scp_task.patch
new file mode 100644
index 0000000000..de61acedbe
--- /dev/null
+++ b/packages/tools/u-boot/patches/61f29bb/u-boot-0001-use-arm-eabi-for-bl301-scp_task.patch
@@ -0,0 +1,23 @@
+From 28c3064d6d3a89962e26f5c9ae3ee105d7377090 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman
+Date: Mon, 8 Aug 2016 01:59:07 +0200
+Subject: [PATCH] Use arm-eabi for bl301/scp_task
+
+For use with Linaro toolchain 4.9-2016.02
+---
+ arch/arm/cpu/armv8/gxb/firmware/scp_task/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/Makefile b/arch/arm/cpu/armv8/gxb/firmware/scp_task/Makefile
+index 865d142..d905365 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/Makefile
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/Makefile
+@@ -6,7 +6,7 @@ include $(buildtree)/include/autoconf.mk
+ include $(buildtree)/.config
+
+ # Select ARMv7-m bare-metal toolchain
+-CROSS_COMPILE=arm-none-eabi-
++CROSS_COMPILE=arm-eabi-
+ ASM=$(CROSS_COMPILE)as
+ CC=$(CROSS_COMPILE)gcc
+ CPP=$(CROSS_COMPILE)cpp
diff --git a/packages/tools/u-boot/release b/packages/tools/u-boot/release
index 876cac8c68..d15f665e4a 100755
--- a/packages/tools/u-boot/release
+++ b/packages/tools/u-boot/release
@@ -41,8 +41,12 @@ mkdir -p $RELEASE_DIR/3rdparty/bootloader
case $PROJECT in
Odroid_C2)
- cp -PR $BUILD/$BOOTLOADER-*/sd_fuse/bl1.bin.hardkernel $RELEASE_DIR/3rdparty/bootloader/bl1
- cp -PR $BUILD/$BOOTLOADER-*/sd_fuse/u-boot.bin $RELEASE_DIR/3rdparty/bootloader/u-boot
+ cp -PR $BUILD/$BOOTLOADER-*/u-boot.bin $RELEASE_DIR/3rdparty/bootloader/u-boot
cp -PR $PROJECT_DIR/$PROJECT/bootloader/boot.ini $RELEASE_DIR/3rdparty/bootloader
+ if [ -f $PROJECT_DIR/$PROJECT/splash/boot-logo.bmp.gz ]; then
+ cp -PR $PROJECT_DIR/$PROJECT/splash/boot-logo.bmp.gz $RELEASE_DIR/3rdparty/bootloader
+ elif [ -f $DISTRO_DIR/$DISTRO/splash/boot-logo.bmp.gz ]; then
+ cp -PR $DISTRO_DIR/$DISTRO/splash/boot-logo.bmp.gz $RELEASE_DIR/3rdparty/bootloader
+ fi
;;
esac
diff --git a/packages/tools/u-boot/scripts/update-c2.sh b/packages/tools/u-boot/scripts/update-c2.sh
index 8902e5d1db..7dde62898c 100644
--- a/packages/tools/u-boot/scripts/update-c2.sh
+++ b/packages/tools/u-boot/scripts/update-c2.sh
@@ -44,11 +44,15 @@ fi
fi
done
+if [ -f $SYSTEM_ROOT/usr/share/bootloader/boot-logo.bmp.gz ]; then
+ echo "*** updating boot logo ..."
+ cp -p $SYSTEM_ROOT/usr/share/bootloader/boot-logo.bmp.gz $BOOT_ROOT
+fi
+
echo "*** updating u-boot for Odroid on: $BOOT_DISK ..."
-dd if=$SYSTEM_ROOT/usr/share/bootloader/bl1 of=$BOOT_DISK conv=fsync bs=1 count=442
-dd if=$SYSTEM_ROOT/usr/share/bootloader/bl1 of=$BOOT_DISK conv=fsync bs=512 seek=1 skip=1
-dd if=$SYSTEM_ROOT/usr/share/bootloader/u-boot of=$BOOT_DISK conv=fsync bs=512 seek=97
+dd if=$SYSTEM_ROOT/usr/share/bootloader/u-boot of=$BOOT_DISK conv=fsync bs=1 count=112
+dd if=$SYSTEM_ROOT/usr/share/bootloader/u-boot of=$BOOT_DISK conv=fsync bs=512 skip=1 seek=1
# monkey patch boot.ini for updated kernel
sed -i '/setenv bootcmd "${kernel}; ${dtb}; ${bootseq}"/i \setenv timer "fdt addr 0x1000000; fdt rm /timer"' /flash/boot.ini
diff --git a/projects/Odroid_C2/bootloader/boot.ini b/projects/Odroid_C2/bootloader/boot.ini
index 75a435f012..e1df57a56a 100644
--- a/projects/Odroid_C2/bootloader/boot.ini
+++ b/projects/Odroid_C2/bootloader/boot.ini
@@ -163,7 +163,7 @@ setenv bootcmd "${kernel}; ${dtb}; ${timer}; ${bootseq}"
#------------------------------------------------------------------------------------------------------
# Prepare to boot
-if test "${hdmi_cec}" = "1"; then setenv cec "hdmitx=cecf"; fi
+if test "${hdmi_cec}" = "1"; then setenv cec "hdmitx=cec17"; fi
if test "${hdmi_hotplug}" = "0"; then setenv hpd "disablehpd=true"; fi
if test "${audio_dac}" = "1"; then setenv dac "enabledac"; fi
if test "${vpu}" = "0"; then fdt rm /mesonstream; fdt rm /vdec; fdt rm /ppmgr; fi
diff --git a/projects/Odroid_C2/initramfs/platform_init b/projects/Odroid_C2/initramfs/platform_init
index 6704129255..b529283cc1 100644
--- a/projects/Odroid_C2/initramfs/platform_init
+++ b/projects/Odroid_C2/initramfs/platform_init
@@ -19,10 +19,6 @@ common_display_setup() {
echo $M > /sys/class/graphics/fb0/window_axis
echo 0 > /sys/class/graphics/fb1/free_scale
echo 1 > /sys/class/video/disable_video
-
- if [ "$bpp" = "32" ]; then
- echo d01068b4 0x7fc0 > /sys/kernel/debug/aml_reg/paddr
- fi
}
case $mode in
diff --git a/projects/Odroid_C2/options b/projects/Odroid_C2/options
index 510a72c379..e39d5507e6 100644
--- a/projects/Odroid_C2/options
+++ b/projects/Odroid_C2/options
@@ -5,7 +5,7 @@
# The TARGET_CPU variable controls which processor should be targeted for
# generated code.
case $TARGET_ARCH in
- arm64)
+ aarch64)
# TARGET_CPU:
# arm2 arm250 arm3 arm6 arm60 arm600 arm610 arm620 arm7 arm7m arm7d
# arm7dm arm7di arm7dmi arm70 arm700 arm700i arm710 arm710c
diff --git a/projects/Odroid_C2/patches/kodi/kodi-0002-disable-suspend.patch b/projects/Odroid_C2/patches/kodi/kodi-0002-disable-suspend.patch
new file mode 100644
index 0000000000..42009e9ce6
--- /dev/null
+++ b/projects/Odroid_C2/patches/kodi/kodi-0002-disable-suspend.patch
@@ -0,0 +1,13 @@
+diff --git a/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp b/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp
+index 4e5bcc6..ad5847d 100644
+--- a/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp
++++ b/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp
+@@ -53,7 +53,7 @@ CLogindUPowerSyscall::CLogindUPowerSyscall()
+ m_canPowerdown = LogindCheckCapability("CanPowerOff");
+ m_canReboot = LogindCheckCapability("CanReboot");
+ m_canHibernate = LogindCheckCapability("CanHibernate");
+- m_canSuspend = LogindCheckCapability("CanSuspend");
++ m_canSuspend = false;
+
+ InhibitDelayLock();
+
diff --git a/projects/Odroid_C2/patches/linux/linux-006-save-cec-config.patch b/projects/Odroid_C2/patches/linux/linux-006-save-cec-config.patch
new file mode 100644
index 0000000000..a66b70ff40
--- /dev/null
+++ b/projects/Odroid_C2/patches/linux/linux-006-save-cec-config.patch
@@ -0,0 +1,85 @@
+diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c
+index 21ca8bb..9f4686f 100644
+--- a/drivers/amlogic/cec/hdmi_ao_cec.c
++++ b/drivers/amlogic/cec/hdmi_ao_cec.c
+@@ -225,14 +225,13 @@ unsigned int aocec_rd_reg(unsigned long addr)
+ {
+ unsigned int data32;
+ unsigned long flags;
+- waiting_aocec_free();
+ spin_lock_irqsave(&cec_dev->cec_reg_lock, flags);
++ waiting_aocec_free();
+ data32 = 0;
+ data32 |= 0 << 16; /* [16] cec_reg_wr */
+ data32 |= 0 << 8; /* [15:8] cec_reg_wrdata */
+- data32 |= addr << 0; /* [7:0] cec_reg_addr */
++ data32 |= (addr & 0xff) << 0; /* [7:0] cec_reg_addr */
+ writel(data32, cec_dev->cec_reg + AO_CEC_RW_REG);
+-
+ waiting_aocec_free();
+ data32 = ((readl(cec_dev->cec_reg + AO_CEC_RW_REG)) >> 24) & 0xff;
+ spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags);
+@@ -241,15 +240,16 @@ unsigned int aocec_rd_reg(unsigned long addr)
+
+ void aocec_wr_reg(unsigned long addr, unsigned long data)
+ {
+- unsigned long data32;
++ unsigned int data32;
+ unsigned long flags;
+- waiting_aocec_free();
+ spin_lock_irqsave(&cec_dev->cec_reg_lock, flags);
++ waiting_aocec_free();
+ data32 = 0;
+ data32 |= 1 << 16; /* [16] cec_reg_wr */
+- data32 |= data << 8; /* [15:8] cec_reg_wrdata */
+- data32 |= addr << 0; /* [7:0] cec_reg_addr */
++ data32 |= (data & 0xff) << 8; /* [15:8] cec_reg_wrdata */
++ data32 |= (addr & 0xff) << 0; /* [7:0] cec_reg_addr */
+ writel(data32, cec_dev->cec_reg + AO_CEC_RW_REG);
++ waiting_aocec_free();
+ spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags);
+ } /* aocec_wr_only_reg */
+
+@@ -737,6 +737,8 @@ static void cec_pre_init(void)
+ {
+ ao_cec_init();
+
++ cec_config(cec_dev->tx_dev->cec_func_config, 1);
++
+ cec_arbit_bit_time_set(3, 0x118, 0);
+ cec_arbit_bit_time_set(5, 0x000, 0);
+ cec_arbit_bit_time_set(7, 0x2aa, 0);
+@@ -1452,8 +1454,6 @@ static int hdmitx_cec_open(struct inode *inode, struct file *file)
+ cec_dev->cec_info.open_count++;
+ if (cec_dev->cec_info.open_count) {
+ cec_dev->cec_info.hal_ctl = 1;
+- /* enable all cec features */
+- cec_config(0x2f, 1);
+ }
+ return 0;
+ }
+@@ -1463,8 +1463,6 @@ static int hdmitx_cec_release(struct inode *inode, struct file *file)
+ cec_dev->cec_info.open_count--;
+ if (!cec_dev->cec_info.open_count) {
+ cec_dev->cec_info.hal_ctl = 0;
+- /* disable all cec features */
+- cec_config(0x0, 1);
+ }
+ return 0;
+ }
+diff --git a/drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_main.c
+index 57105b6..0a7f914 100644
+--- a/drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_main.c
++++ b/drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_main.c
+@@ -2467,9 +2467,9 @@ static int __init hdmitx_boot_para_setup(char *s)
+ init_flag |= INIT_FLAG_NOT_LOAD;
+ } else if (strncmp(token, "cec", 3) == 0) {
+ ret = kstrtoul(token+3, 16, &list);
+- if ((list >= 0) && (list <= 0x2f))
++ if ((list >= 0) && (list <= 0xff))
+ hdmitx_device.cec_func_config = list;
+- hdmi_print(INF, CEC "HDMI hdmi_cec_func_config:0x%x\n",
++ hdmi_print(IMP, CEC "HDMI hdmi_cec_func_config:0x%x\n",
+ hdmitx_device.cec_func_config);
+ } else if (strcmp(token, "forcergb") == 0) {
+ hdmitx_output_rgb();
diff --git a/projects/Odroid_C2/patches/u-boot/u-boot-0001-set-default-boot-options.patch b/projects/Odroid_C2/patches/u-boot/u-boot-0001-set-default-boot-options.patch
index e24d71098b..9c436f60b9 100644
--- a/projects/Odroid_C2/patches/u-boot/u-boot-0001-set-default-boot-options.patch
+++ b/projects/Odroid_C2/patches/u-boot/u-boot-0001-set-default-boot-options.patch
@@ -11,7 +11,7 @@ diff -Naur a/include/configs/odroidc2.h b/include/configs/odroidc2.h
- "console=ttyS0,115200 " \
- "hdmimode=1080p60hz hdmitx=cecf " \
- "logo=osd1,loaded,0x3f800000,1080p60hz " \
-- "androidboot.hardware=odroidc2 " \
+- "androidboot.hardware=odroidc2 androidboot.serialno=${fbt_id#} " \
- "androidboot.selinux=disabled \0" \
- "bootcmd=cfgload; showlogo ${hdmimode}; movi read dtb 0 ${dtbaddr}; movi read boot 0 ${loadaddr}; booti ${loadaddr} - ${dtbaddr}\0"
+ "bootcmd=cfgload\0"
diff --git a/projects/Odroid_C2/patches/u-boot/u-boot-0002-fix-power-off-wakeup.patch b/projects/Odroid_C2/patches/u-boot/u-boot-0002-fix-power-off-wakeup.patch
new file mode 100644
index 0000000000..67ad437a48
--- /dev/null
+++ b/projects/Odroid_C2/patches/u-boot/u-boot-0002-fix-power-off-wakeup.patch
@@ -0,0 +1,1468 @@
+From 6e05bb98a2f4b4c45ad0e77eeb014f366ecac3b5 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman
+Date: Sat, 13 Aug 2016 17:23:22 +0200
+Subject: [PATCH 1/6] Fix secure_task loop
+
+---
+ arch/arm/cpu/armv8/gxb/firmware/scp_task/misc.S | 4 ++--
+ arch/arm/cpu/armv8/gxb/firmware/scp_task/user_task.c | 7 +------
+ 2 files changed, 3 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/misc.S b/arch/arm/cpu/armv8/gxb/firmware/scp_task/misc.S
+index 4ce73f2..9b97da3 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/misc.S
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/misc.S
+@@ -19,6 +19,6 @@ bss_loop:
+
+ .align 2
+ _bss_start:
+-.long _bss_start
++.long _bssstart
+ _bss_end:
+-.long _bss_end
+\ No newline at end of file
++.long _bssend
+\ No newline at end of file
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/user_task.c b/arch/arm/cpu/armv8/gxb/firmware/scp_task/user_task.c
+index 53a35c4..b2f6394 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/user_task.c
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/user_task.c
+@@ -64,13 +64,8 @@ void secure_task(void)
+ presume = (struct resume_param *)(response+1);
+ presume->method = resume_data.method;
+ }
+-
+- /* FIXME : __switch_back_highmb() ? */
+- while(1)
+- ;
+ }
+-
+- __switch_back_highmb();
++ __switch_back_securemb();
+ }
+ }
+
+
+From e18fc08f3e9675dd6e418fd938bcf05e9d8d287d Mon Sep 17 00:00:00 2001
+From: Jonas Karlman
+Date: Sat, 13 Aug 2016 17:23:22 +0200
+Subject: [PATCH 2/6] Use power_off/on_at_24M to turn off/on blue led
+
+---
+ board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+index 65633b4..374481a 100644
+--- a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
++++ b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+@@ -96,15 +96,16 @@ static void power_on_at_clk81(void)
+ power_on_3v3();
+ }
+
++/*odroidc2 GPIOAO_13 powr on :0, power_off :1*/
+ static void power_off_at_24M(void)
+ {
+ //LED gpioao_13
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<29, 0);
++ aml_update_bits(AO_GPIO_O_EN_N, 1<<29, 1<<29);
+ }
+
+ static void power_on_at_24M(void)
+ {
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<29, 1<<29);
++ aml_update_bits(AO_GPIO_O_EN_N, 1<<29, 0);
+ }
+
+ static void power_off_at_32k(void)
+@@ -201,7 +202,7 @@ void set_GPIOAO_BIT13(void)
+
+ void set_custom_gpio_status(void)
+ {
+- set_GPIOAO_BIT13();
++ //set_GPIOAO_BIT13();
+ set_GPIOX_BIT11();
+ set_GPIOX_BIT19();
+ set_GPIOY_BIT14();
+
+From 03115f43534f9d29f952c557d3846028c4ecdf7c Mon Sep 17 00:00:00 2001
+From: Jonas Karlman
+Date: Sat, 13 Aug 2016 17:23:22 +0200
+Subject: [PATCH 3/6] Fix power off/on vcck
+
+GPIOAO.BIT2 is used for VCCK_CON according to odroid-c2_rev0.2_20160226.pdf
+
+Also disables power off/on 3v3
+---
+ board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+index 374481a..c4d15b8 100644
+--- a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
++++ b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+@@ -62,25 +62,25 @@ void pwm_set_voltage(unsigned int id, unsigned int voltage)
+
+ static void power_off_3v3(void)
+ {
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 1<<18);
++ //aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
++ //aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 1<<18);
+ }
+ static void power_on_3v3(void)
+ {
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 0);
++ //aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
++ //aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 0);
+ }
+
+-/*p200/201 GPIOAO_4 powr on :1, power_off :0*/
++/*odroidc2 GPIOAO_2 powr on :1, power_off :0*/
+ static void power_off_vcck(void)
+ {
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<4, 0);
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<20, 0);
++ aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
++ aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 0);
+ }
+ static void power_on_vcck(void)
+ {
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<4, 0);
+- aml_update_bits(AO_GPIO_O_EN_N, 1<<20, 1<<20);
++ aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
++ aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 1<<18);
+ }
+
+ static void power_off_at_clk81(void)
+
+From 96d7386d8270a8684c3a651fdc20dbc1c2b58226 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman
+Date: Sat, 13 Aug 2016 17:23:22 +0200
+Subject: [PATCH 4/6] Disable power-key wakeup
+
+GPIOAO.BIT3 is used for TF_3V3N_1V8_EN according to odroid-c2_rev0.2_20160226.pdf
+---
+ board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+index c4d15b8..f6f2a7d 100644
+--- a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
++++ b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+@@ -249,10 +249,12 @@ unsigned int detect_key(unsigned int suspend_from)
+ cec_node_init();
+ }
+ #endif
++#if 0
+ if ((readl(AO_GPIO_I) & (1<<3)) == 0) {
+ exit_reason = POWER_KEY_WAKEUP;
+ break;
+ }
++#endif
+ if (time_out != 0) {
+ if ((get_time() - init_time) >= time_out * 1000 * 1000) {
+ exit_reason = AUTO_WAKEUP;
+
+From 57c021cfc6504569aa66d26dc3cd17b97155eddb Mon Sep 17 00:00:00 2001
+From: Jonas Karlman
+Date: Sat, 13 Aug 2016 17:23:22 +0200
+Subject: [PATCH 5/6] Backport remote-power-key wakeup code
+
+---
+ .../cpu/armv8/gxb/firmware/scp_task/scp_remote.c | 93 ++++++++++++++++++++--
+ 1 file changed, 88 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/scp_remote.c b/arch/arm/cpu/armv8/gxb/firmware/scp_task/scp_remote.c
+index e73d172..e3cabb7 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/scp_remote.c
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/scp_remote.c
+@@ -18,22 +18,105 @@ enum{
+ DECODEMODE_MAX
+ };
+
++typedef struct reg_remote {
++ int reg;
++ unsigned int val;
++} reg_remote;
++#define CONFIG_END 0xffffffff
+ #define IR_POWER_KEY_MASK 0xffffffff
++#if 0
++//32K
++static const reg_remote RDECODEMODE_NEC[] = {
++ {AO_MF_IR_DEC_LDR_ACTIVE, 350 << 16 | 260 << 0},
++ {AO_MF_IR_DEC_LDR_IDLE, 200 << 16 | 120 << 0},
++ {AO_MF_IR_DEC_LDR_REPEAT, 100 << 16 | 70 << 0},
++ {AO_MF_IR_DEC_BIT_0, 50 << 16 | 20 << 0},
++ {AO_MF_IR_DEC_REG0, 3 << 28 | (0xFA0 << 12)},
++ {AO_MF_IR_DEC_STATUS, (100 << 20) | (45 << 10)},
++ {AO_MF_IR_DEC_REG1, 0x600fdf00},
++ {AO_MF_IR_DEC_REG2, 0x0},
++ {AO_MF_IR_DEC_DURATN2, 0},
++ {AO_MF_IR_DEC_DURATN3, 0},
++ {CONFIG_END, 0}
++};
++#else
++//24M
++static const reg_remote RDECODEMODE_NEC[] = {
++ {AO_MF_IR_DEC_LDR_ACTIVE, 477 << 16 | 400 << 0},
++ {AO_MF_IR_DEC_LDR_IDLE, 248 << 16 | 202 << 0},
++ {AO_MF_IR_DEC_LDR_REPEAT, 130 << 16 | 110 << 0},
++ {AO_MF_IR_DEC_BIT_0, 60 << 16 | 48 << 0},
++ {AO_MF_IR_DEC_REG0, 3 << 28 | (0xFA0 << 12) | 0x13},
++ {AO_MF_IR_DEC_STATUS, (111 << 20) | (100 << 10)},
++ {AO_MF_IR_DEC_REG1, 0x9f50},
++ {AO_MF_IR_DEC_REG2, 0x0},
++ {AO_MF_IR_DEC_DURATN2, 0},
++ {AO_MF_IR_DEC_DURATN3, 0},
++ {CONFIG_END, 0}
++};
++#endif
++
++static const reg_remote *remoteregsTab[] = {
++ RDECODEMODE_NEC,
++};
++
++void setremotereg(const reg_remote * r)
++{
++ writel(r->val, r->reg);
++}
++
++int set_remote_mode(int mode)
++{
++ const reg_remote *reg;
++ reg = remoteregsTab[mode];
++ while (CONFIG_END != reg->reg)
++ setremotereg(reg++);
++ return 0;
++}
++
++/*****************************************************************
++**
++** func : ir_remote_init
++** in this function will do pin configuration and and initialize for
++** IR Remote hardware decoder mode at 32kHZ on ARC.
++**
++********************************************************************/
++static int ir_remote_init_32k_mode(void)
++{
++ //volatile unsigned int status,data_value;
++ int val = readl(AO_RTI_PIN_MUX_REG);
++ writel((val | (1 << 0)), AO_RTI_PIN_MUX_REG);
++ set_remote_mode(DECODEMODE_NEC);
++ //status = readl(AO_MF_IR_DEC_STATUS);
++ uart_put_hex(readl(AO_MF_IR_DEC_STATUS), 32);
++ //data_value = readl(AO_MF_IR_DEC_FRAME);
++ uart_put_hex(readl(AO_MF_IR_DEC_FRAME), 32);
++
++ //step 2 : request nec_remote irq & enable it
++ return 0;
++}
++
++void init_custom_trigger(void)
++{
++ ir_remote_init_32k_mode();
++}
++
+ static unsigned int kk[] = {
+- 0xe51afb04,
++ 0x23dc4db2,
+ };
+ static int init_remote(void)
+ {
+- uart_put_hex(readl(AO_IR_DEC_STATUS), 32);
+- uart_put_hex(readl(AO_IR_DEC_FRAME), 32);
++ //uart_put_hex(readl(AO_IR_DEC_STATUS), 32);
++ //uart_put_hex(readl(AO_IR_DEC_FRAME), 32);
++ init_custom_trigger();
+ return 0;
+ }
+
+ static int remote_detect_key(void)
+ {
+ unsigned power_key;
+- if (((readl(AO_IR_DEC_STATUS))>>3) & 0x1) {
+- power_key = readl(AO_IR_DEC_FRAME);
++ if (((readl(AO_MF_IR_DEC_STATUS))>>3) & 0x1) {
++ power_key = readl(AO_MF_IR_DEC_FRAME);
+ if ((power_key&IR_POWER_KEY_MASK) == kk[DECODEMODE_NEC])
+ return 1;
+
+
+From 005dc1f22f3d3097dbabc6d25cc6e3b54741671b Mon Sep 17 00:00:00 2001
+From: Jonas Karlman
+Date: Wed, 24 Aug 2016 20:04:36 +0200
+Subject: [PATCH 6/6] Fix CEC wakeup
+
+---
+ .../cpu/armv8/gxb/firmware/scp_task/cec_tx_reg.h | 33 +-
+ .../cpu/armv8/gxb/firmware/scp_task/hdmi_cec_arc.c | 840 ++++++++-------------
+ arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c | 8 +-
+ .../cpu/armv8/gxb/firmware/scp_task/task_apis.h | 4 +-
+ .../odroidc2/firmware/scp_task/pwr_ctrl.c | 16 +-
+ 5 files changed, 349 insertions(+), 552 deletions(-)
+
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/cec_tx_reg.h b/arch/arm/cpu/armv8/gxb/firmware/scp_task/cec_tx_reg.h
+index 8f4496d..e88be16 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/cec_tx_reg.h
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/cec_tx_reg.h
+@@ -197,6 +197,7 @@ typedef unsigned int uint32_t;
+ #define ONE_TOUCH_PLAY_MASK 1
+ #define ONE_TOUCH_STANDBY_MASK 2
+ #define AUTO_POWER_ON_MASK 3
++#define STREAMPATH_POWER_ON_MASK 4
+
+ //#define P_HHI_GCLK_MPEG2 CBUS_REG_ADDR(HHI_GCLK_MPEG2)
+ //#define P_HHI_HDMI_CLK_CNTL CBUS_REG_ADDR(HHI_HDMI_CLK_CNTL)
+@@ -224,6 +225,13 @@ enum _cec_log_dev_addr_e {
+ CEC_UNREGISTERED_ADDR
+ };
+
++typedef enum {
++ POWER_ON = 0x00,
++ POWER_STANDBY,
++ TRANS_STANDBY_TO_ON,
++ TRANS_ON_TO_STANDBY,
++} cec_power_status_e;
++
+ typedef enum {
+ CEC_UNRECONIZED_OPCODE = 0x0,
+ CEC_NOT_CORRECT_MODE_TO_RESPOND,
+@@ -240,37 +248,18 @@ typedef enum {
+
+ /* cec message structure */
+ typedef struct {
+- unsigned char msg[16];
++ unsigned char msg[MAX_MSG];
+ unsigned char msg_len;
+-} cec_msg_buf_t;
+-
+-typedef struct {
+- cec_msg_buf_t buf[4]; // message memory
+- unsigned char power_status;
+- unsigned char log_addr;
+ unsigned char cec_power;
+- unsigned char test;
+- unsigned char rx_write_pos;
+- unsigned char rx_read_pos;
+- unsigned char rx_buf_size;
++ unsigned char log_addr;
++ unsigned int phy_addr;
+ } cec_msg_t;
+
+ cec_msg_t cec_msg;
+ unsigned long hdmi_cec_func_config;
+ void cec_node_init(void);
+-void cec_power_on(void);
+-void cec_off(void);
+ unsigned int cec_handler(void);
+ void remote_cec_hw_reset(void);
+-unsigned char remote_cec_ll_rx(void);
+-int remote_cec_ll_tx(unsigned char *msg, unsigned char len);
+-void cec_wr_reg(unsigned long addr, unsigned long data);
+-unsigned long cec_rd_reg(unsigned long addr);
+-void cec_arbit_bit_time_set(unsigned bit_set, unsigned time_set);
+-//void cec_give_device_power_status(void);
+-void cec_inactive_source(void);
+-void cec_set_standby(void);
+-
+ extern void udelay(int i);
+
+ // The following registers are for fine tuning CEC bit timing parameters.
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/hdmi_cec_arc.c b/arch/arm/cpu/armv8/gxb/firmware/scp_task/hdmi_cec_arc.c
+index 33f3d83..79f8dbc 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/hdmi_cec_arc.c
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/hdmi_cec_arc.c
+@@ -11,41 +11,23 @@
+ #define CEC_DBG_PRINT
+ #ifdef CEC_DBG_PRINT
+ #define cec_dbg_print(s,v) {uart_puts(s);uart_put_hex(v,8);}
+- #define cec_dbg_prints(s) {uart_puts(s);}
++ #define cec_dbg_printx(s,v,x) {uart_puts(s);uart_put_hex(v,x);}
++ #define cec_dbg_prints(s) {uart_puts(s);wait_uart_empty();}
+ #else
+ #define cec_dbg_print(s,v)
++ #define cec_dbg_printx(s,v,x)
+ #define cec_dbg_prints(s)
+ #endif
+
+-void cec_reset_addr(void);
+-struct cec_tx_msg_t {
+- unsigned char buf[16];
+- unsigned char retry;
+- unsigned char len;
+-};
+-
+-#define CEX_TX_MSG_BUF_NUM 8
+-#define CEC_TX_MSG_BUF_MASK (CEX_TX_MSG_BUF_NUM - 1)
+-
+-struct cec_tx_msg {
+- struct cec_tx_msg_t msg[CEX_TX_MSG_BUF_NUM];
+- unsigned int send_idx;
+- unsigned int queue_idx;
+-};
+-
+-struct cec_tx_msg cec_tx_msgs = {};
+-
+-
+-int cec_strlen(char *p)
++static int cec_strlen(char *p)
+ {
+ int i=0;
+-
+ while (*p++)
+ i++;
+ return i;
+ }
+
+-void *cec_memcpy(void *memto, const void *memfrom, unsigned int size)
++static void *cec_memcpy(void *memto, const void *memfrom, unsigned int size)
+ {
+ char *tempfrom = (char *)memfrom;
+ char *tempto = (char *)memto;
+@@ -57,61 +39,46 @@ void *cec_memcpy(void *memto, const void *memfrom, unsigned int size)
+ return memto;
+ }
+
+-#define waiting_aocec_free() \
+- do {\
+- unsigned long cnt = 0;\
+- while (readl(P_AO_CEC_RW_REG) & (1<<23))\
+- {\
+- if (5000 == cnt++)\
+- {\
+- break;\
+- }\
+- }\
+- } while(0)
+-
+-unsigned long cec_rd_reg(unsigned long addr)
++static void waiting_aocec_free(void) {
++ unsigned long cnt = 0;
++ while (readl(P_AO_CEC_RW_REG) & (1<<23))
++ {
++ if (8192 <= cnt++)
++ {
++ cec_dbg_printx("\nWARNING: waiting_aocec_free cnt:0x", cnt, 16);
++ cec_dbg_prints("\n");
++ break;
++ }
++ }
++}
++
++static unsigned long cec_rd_reg(unsigned long addr)
+ {
+ unsigned long data32;
+ waiting_aocec_free();
+ data32 = 0;
+- data32 |= 0 << 16; // [16] cec_reg_wr
+- data32 |= 0 << 8; // [15:8] cec_reg_wrdata
+- data32 |= addr << 0; // [7:0] cec_reg_addr
++ data32 |= 0 << 16; // [16] cec_reg_wr
++ data32 |= 0 << 8; // [15:8] cec_reg_wrdata
++ data32 |= (addr & 0xff) << 0; // [7:0] cec_reg_addr
+ writel(data32, P_AO_CEC_RW_REG);
+ waiting_aocec_free();
+ data32 = ((readl(P_AO_CEC_RW_REG)) >> 24) & 0xff;
+- return (data32);
+-} /* cec_rd_reg */
++ return data32;
++}
+
+-void cec_wr_reg (unsigned long addr, unsigned long data)
++static void cec_wr_reg(unsigned long addr, unsigned long data)
+ {
+ unsigned long data32;
+ waiting_aocec_free();
+ data32 = 0;
+- data32 |= 1 << 16; // [16] cec_reg_wr
+- data32 |= data << 8; // [15:8] cec_reg_wrdata
+- data32 |= addr << 0; // [7:0] cec_reg_addr
++ data32 |= 1 << 16; // [16] cec_reg_wr
++ data32 |= (data & 0xff) << 8; // [15:8] cec_reg_wrdata
++ data32 |= (addr & 0xff) << 0; // [7:0] cec_reg_addr
+ writel(data32, P_AO_CEC_RW_REG);
+-} /* aocec_wr_only_reg */
+-
+-void cec_off(void)
+-{
+- /*
+- * [2:1] cntl_clk: 0=Disable clk (Power-off mode);
+- * 1=Enable gated clock (Normal mode);
+- * 2=Enable free-run clk (Debug mode).
+- */
+- writel(0x0, P_AO_CEC_GEN_CNTL);
+-}
+-
+-void cec_rx_read_pos_plus(void)
+-{
+- (cec_msg.rx_read_pos == cec_msg.rx_buf_size - 1) ?
+- (cec_msg.rx_read_pos = 0) :
+- (cec_msg.rx_read_pos++);
++ waiting_aocec_free();
+ }
+
+-void cec_arbit_bit_time_set(unsigned bit_set, unsigned time_set)
++static void cec_arbit_bit_time_set(unsigned bit_set, unsigned time_set)
+ {
+ //11bit:bit[10:0]
+ switch (bit_set) {
+@@ -134,7 +101,7 @@ void cec_arbit_bit_time_set(unsigned bit_set, unsigned time_set)
+ }
+ }
+
+-void cec_hw_buf_clear(void)
++static void cec_hw_buf_clear(void)
+ {
+ cec_wr_reg(CEC_RX_MSG_CMD, RX_DISABLE);
+ cec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT);
+@@ -150,7 +117,8 @@ void cec_hw_buf_clear(void)
+
+ void remote_cec_hw_reset(void)
+ {
+- cec_dbg_prints("hw reset\n");
++ cec_dbg_prints("\nremote_cec_hw_reset\n");
++
+ /*
+ * clock switch to 32k
+ */
+@@ -174,561 +142,399 @@ void remote_cec_hw_reset(void)
+ cec_arbit_bit_time_set(7, 0x2aa);
+ }
+
+-unsigned char remote_cec_ll_rx(void)
+-{
+- int i;
+- int print = 1;
+- unsigned char rx_msg_length = cec_rd_reg(CEC_RX_MSG_LENGTH) + 1;
+-
+- cec_dbg_prints("cec R:");
+- for (i = 0; i < rx_msg_length; i++) {
+- cec_msg.buf[cec_msg.rx_write_pos].msg[i] = cec_rd_reg(CEC_RX_MSG_0_HEADER + i);
+- if (print) {
+- cec_dbg_print(" ", cec_msg.buf[cec_msg.rx_write_pos].msg[i]);
+- }
+- if (i == 1 && cec_msg.buf[cec_msg.rx_write_pos].msg[i] == CEC_OC_VENDOR_COMMAND_WITH_ID) {
+- /* do not print command with ID */
+- print = 0;
+- }
+- }
+- cec_msg.buf[cec_msg.rx_write_pos].msg_len = rx_msg_length;
+- cec_dbg_prints("\n");
+-
+- return 0;
+-}
+-void cec_buf_clear(void)
+-{
+- int i;
+-
+- for (i = 0; i < 16; i++)
+- cec_msg.buf[cec_msg.rx_read_pos].msg[i] = 0;
+-}
+-
+-void cec_tx_buf_init(void)
+-{
+- int i, j;
+- for (j = 0; j < CEX_TX_MSG_BUF_NUM; j++) {
+- for (i = 0; i < 16; i++) {
+- cec_tx_msgs.msg[j].buf[i] = 0;
+- }
+- cec_tx_msgs.msg[j].retry = 0;
+- cec_tx_msgs.msg[j].len = 0;
+- }
+-}
+-
+-int cec_queue_tx_msg(unsigned char *msg, unsigned char len)
+-{
+- int s_idx, q_idx;
+-
+- s_idx = cec_tx_msgs.send_idx;
+- q_idx = cec_tx_msgs.queue_idx;
+- if (((q_idx + 1) & CEC_TX_MSG_BUF_MASK) == s_idx) {
+- cec_dbg_prints("tx buffer full, abort msg\n");
+- cec_reset_addr();
+- return -1;
+- }
+- if (len && msg) {
+- cec_memcpy(cec_tx_msgs.msg[q_idx].buf, msg, len);
+- cec_tx_msgs.msg[q_idx].len = len;
+- cec_tx_msgs.queue_idx = (q_idx + 1) & CEC_TX_MSG_BUF_MASK;
+- }
+- return 0;
+-}
+-
+-int cec_triggle_tx(unsigned char *msg, unsigned char len)
+-{
+- int i;
+-
+- if ((TX_IDLE == cec_rd_reg(CEC_TX_MSG_STATUS)) ||
+- (TX_DONE == cec_rd_reg(CEC_TX_MSG_STATUS))) {
+- cec_dbg_prints("cec T:");
+- for (i = 0; i < len; i++) {
+- cec_wr_reg(CEC_TX_MSG_0_HEADER + i, msg[i]);
+- cec_dbg_print(" ", msg[i]);
+- }
+- cec_dbg_prints("\n");
+- cec_wr_reg(CEC_TX_MSG_LENGTH, len-1);
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_REQ_CURRENT); //TX_REQ_NEXT
+- return 0;
+- }
+- return -1;
+-}
+-
+-int remote_cec_ll_tx(unsigned char *msg, unsigned char len)
+-{
+- cec_queue_tx_msg(msg, len);
+- cec_triggle_tx(msg, len);
+-
+- return 0;
+-}
+-
+-int ping_cec_ll_tx(unsigned char *msg, unsigned char len)
++static int cec_triggle_tx(unsigned char *msg, unsigned char len)
+ {
+- int i;
+- int ret = 0;
+- unsigned int n = 900;
+- unsigned int reg;
+-
+- ret = cec_rd_reg(CEC_RX_MSG_STATUS);
+- cec_dbg_print("rx stat:", ret);
+- ret = cec_rd_reg(CEC_TX_MSG_STATUS);
+- cec_dbg_print(", tx stat:", ret);
+- cec_dbg_prints("\n");
+-
+- while (cec_rd_reg(CEC_TX_MSG_STATUS) == TX_BUSY) {
+- /*
+- * waiting tx to idle if it is busy, other device may in tx state
+- */
+- }
+- if (cec_rd_reg(CEC_TX_MSG_STATUS) == TX_ERROR)
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
++ unsigned int i, cnt = 0;
+
++ cec_dbg_prints(" T:");
+ for (i = 0; i < len; i++) {
+ cec_wr_reg(CEC_TX_MSG_0_HEADER + i, msg[i]);
++ cec_dbg_print(" ", msg[i]);
+ }
+- cec_wr_reg(CEC_TX_MSG_LENGTH, len-1);
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_REQ_CURRENT); //TX_REQ_NEXT
+- ret = cec_rd_reg(CEC_RX_MSG_STATUS);
+- cec_dbg_print("rx stat:", ret);
+- ret = cec_rd_reg(CEC_TX_MSG_STATUS);
+- cec_dbg_print(", tx stat:", ret);
+ cec_dbg_prints("\n");
++ cec_wr_reg(CEC_TX_MSG_LENGTH, len - 1);
+
+- while (1) {
+- reg = cec_rd_reg(CEC_TX_MSG_STATUS);
+- if ( reg == TX_DONE ) {
+- ret = TX_DONE;
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+- cec_dbg_prints("ping_cec_ll_tx:TX_DONE\n")
+- break;
+- }
++ do {
++ cec_wr_reg(CEC_TX_MSG_CMD, TX_REQ_CURRENT);
++ cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
++ cnt++;
++ } while (cec_rd_reg(CEC_TX_NUM_MSG));
+
+- if (reg == TX_ERROR) {
+- ret = TX_ERROR;
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+- cec_dbg_prints("ping_cec_ll_tx:TX_ERROR\n")
+- break;
+- }
+- if (!(n--)) {
+- cec_dbg_prints("ping_cec_ll_tx:TX_BUSY\n")
+- ret = TX_BUSY;
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+- break;
+- }
+- if (reg != TX_BUSY) {
+- break;
+- }
+- _udelay(500);
++ if (cnt > 1) {
++ cec_dbg_printx("WARNING: cec_triggle_tx cnt:0x", cnt, 16);
++ cec_dbg_prints("\n");
+ }
+
+- return ret;
++ _udelay(150);
++ return 0;
+ }
+
+-void cec_imageview_on(void)
+-{
+- unsigned char msg[2];
+-
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4)| CEC_TV_ADDR;
+- msg[1] = CEC_OC_IMAGE_VIEW_ON;
+-
+- ping_cec_ll_tx(msg, 2);
++#define DEVICE_TV 0
++#define DEVICE_RECORDER 1
++#define DEVICE_RESERVED 2
++#define DEVICE_TUNER 3
++#define DEVICE_PLAYBACK 4
++#define DEVICE_AUDIO_SYSTEM 5
++#define DEVICE_PURE_CEC_SWITCH 6
++#define DEVICE_VIDEO_PROCESSOR 7
++
++static unsigned char log_addr_to_devtype(unsigned char addr)
++{
++ static unsigned char addr_map[] = {
++ DEVICE_TV,
++ DEVICE_RECORDER,
++ DEVICE_RECORDER,
++ DEVICE_TUNER,
++ DEVICE_PLAYBACK,
++ DEVICE_AUDIO_SYSTEM,
++ DEVICE_TUNER,
++ DEVICE_TUNER,
++ DEVICE_PLAYBACK,
++ DEVICE_RECORDER,
++ DEVICE_TUNER,
++ DEVICE_PLAYBACK,
++ DEVICE_RESERVED,
++ DEVICE_RESERVED,
++ DEVICE_TV,
++ DEVICE_PLAYBACK
++ };
++ return addr_map[addr & 0xf];
+ }
+
+-void cec_report_physical_address(void)
++static void cec_report_physical_address(void)
+ {
+ unsigned char msg[5];
+- unsigned char phy_addr_ab = (readl(P_AO_DEBUG_REG1) >> 8) & 0xff;
+- unsigned char phy_addr_cd = readl(P_AO_DEBUG_REG1) & 0xff;
++ cec_dbg_prints("cec_report_physical_address\n");
+
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4)| CEC_BROADCAST_ADDR;
++ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_BROADCAST_ADDR;
+ msg[1] = CEC_OC_REPORT_PHYSICAL_ADDRESS;
+- msg[2] = phy_addr_ab;
+- msg[3] = phy_addr_cd;
+- msg[4] = CEC_PLAYBACK_DEVICE_TYPE;
++ msg[2] = (cec_msg.phy_addr >> 8) & 0xff;
++ msg[3] = (cec_msg.phy_addr >> 0) & 0xff;
++ msg[4] = log_addr_to_devtype(cec_msg.log_addr);
+
+- remote_cec_ll_tx(msg, 5);
++ cec_triggle_tx(msg, 5);
+ }
+
+-void cec_report_device_power_status(void)
++static void cec_report_power_status(unsigned char initiator)
+ {
+ unsigned char msg[3];
++ cec_dbg_printx("cec_report_power_status initiator:0x", initiator, 4);
++ cec_dbg_prints("\n");
+
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4)| CEC_TV_ADDR;
++ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | (initiator & 0xf);
+ msg[1] = CEC_OC_REPORT_POWER_STATUS;
+- msg[2] = cec_msg.power_status;
++ msg[2] = POWER_STANDBY;
+
+- remote_cec_ll_tx(msg, 3);
++ cec_triggle_tx(msg, 3);
+ }
+
+-void cec_set_stream_path(void)
++static void cec_feature_abort(unsigned char reason, unsigned char initiator)
+ {
+- unsigned char phy_addr_ab = (readl(P_AO_DEBUG_REG1) >> 8) & 0xff;
+- unsigned char phy_addr_cd = readl(P_AO_DEBUG_REG1) & 0xff;
+-
+- if ((hdmi_cec_func_config >> CEC_FUNC_MASK) & 0x1) {
+- if ((hdmi_cec_func_config >> AUTO_POWER_ON_MASK) & 0x1) {
+- if ((phy_addr_ab == cec_msg.buf[cec_msg.rx_read_pos].msg[2]) &&
+- (phy_addr_cd == cec_msg.buf[cec_msg.rx_read_pos].msg[3])) {
+- cec_msg.cec_power = 0x1;
+- }
+- }
+- }
++ unsigned char msg[4];
++ cec_dbg_print("cec_feature_abort reason:0x", reason);
++ cec_dbg_printx(", initiator:0x", initiator, 4);
++ cec_dbg_prints("\n");
++
++ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | (initiator & 0xf);
++ msg[1] = CEC_OC_FEATURE_ABORT;
++ msg[2] = cec_msg.msg[1];
++ msg[3] = reason;
++
++ cec_triggle_tx(msg, 4);
+ }
+
+-void cec_device_vendor_id(void)
++static void cec_menu_status(unsigned char menu_status, unsigned char initiator)
+ {
+- unsigned char msg[5];
++ unsigned char msg[3];
++ cec_dbg_print("cec_menu_status menu_status:0x", menu_status);
++ cec_dbg_printx(", initiator:0x", initiator, 4);
++ cec_dbg_prints("\n");
+
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4)| CEC_BROADCAST_ADDR;
+- msg[1] = CEC_OC_DEVICE_VENDOR_ID;
+- msg[2] = 0x00;
+- msg[3] = 0x00;
+- msg[4] = 0x00;
++ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | (initiator & 0xf);
++ msg[1] = CEC_OC_MENU_STATUS;
++ msg[2] = menu_status;
+
+- remote_cec_ll_tx(msg, 5);
++ cec_triggle_tx(msg, 3);
+ }
+
+-void cec_feature_abort(void)
++static void cec_set_stream_path(unsigned char initiator)
+ {
+- if (cec_msg.buf[cec_msg.rx_read_pos].msg[1] != 0xf) {
+- unsigned char msg[4];
+-
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_TV_ADDR;
+- msg[1] = CEC_OC_FEATURE_ABORT;
+- msg[2] = cec_msg.buf[cec_msg.rx_read_pos].msg[1];
+- msg[3] = CEC_UNRECONIZED_OPCODE;
++ unsigned int phy_addr = (cec_msg.msg[2] << 8) | cec_msg.msg[3];
++ cec_dbg_printx("cec_set_stream_path initiator:0x", initiator, 4);
++ cec_dbg_printx(", phy_addr:0x", phy_addr, 16);
++ cec_dbg_prints("\n");
+
+- remote_cec_ll_tx(msg, 4);
++ if ((hdmi_cec_func_config >> STREAMPATH_POWER_ON_MASK) & 0x1) {
++ if (cec_msg.phy_addr == phy_addr && initiator == CEC_TV_ADDR) {
++ cec_msg.cec_power = 0x1;
++ }
+ }
+ }
+
+-void cec_menu_status_smp(int menu_status)
++static void cec_routing_change(unsigned char initiator)
+ {
+- unsigned char msg[3];
+-
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4)| CEC_TV_ADDR;
+- msg[1] = CEC_OC_MENU_STATUS;
+- msg[2] = menu_status;
++ unsigned int phy_addr = (cec_msg.msg[4] << 8) | cec_msg.msg[5];
++ cec_dbg_printx("cec_routing_change initiator:0x", initiator, 4);
++ cec_dbg_printx(", phy_addr:0x", phy_addr, 16);
++ cec_dbg_prints("\n");
+
+- remote_cec_ll_tx(msg, 3);
++ if ((hdmi_cec_func_config >> STREAMPATH_POWER_ON_MASK) & 0x1) {
++ if (cec_msg.phy_addr == phy_addr && initiator == CEC_TV_ADDR) {
++ cec_msg.cec_power = 0x1;
++ }
++ }
+ }
+
+-void cec_inactive_source(void)
++static void cec_user_control_pressed(void)
+ {
+- unsigned char msg[4];
+- unsigned char phy_addr_ab = (readl(P_AO_DEBUG_REG1) >> 8) & 0xff;
+- unsigned char phy_addr_cd = readl(P_AO_DEBUG_REG1) & 0xff;
+-
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_TV_ADDR;
+- msg[1] = CEC_OC_INACTIVE_SOURCE;
+- msg[2] = phy_addr_ab;
+- msg[3] = phy_addr_cd;
++ cec_dbg_print("cec_user_control_pressed operation:0x", cec_msg.msg[2]);
++ cec_dbg_prints("\n");
+
+- remote_cec_ll_tx(msg, 4);
++ if ((hdmi_cec_func_config >> ONE_TOUCH_STANDBY_MASK) & 0x1) {
++ if ((0x40 == cec_msg.msg[2]) || // Power
++ (0x6b == cec_msg.msg[2]) || // Power Toggle Function
++ (0x6d == cec_msg.msg[2]) || // Power On Function
++ (0x0a == cec_msg.msg[2]) || // Setup Menu
++ (0x0b == cec_msg.msg[2]) || // Contents Menu
++ (0x10 == cec_msg.msg[2]) || // Media Top Menu
++ (0x11 == cec_msg.msg[2]) || // Media Context-sensitive Menu
++ (0x09 == cec_msg.msg[2])) { // Root Menu
++ cec_msg.cec_power = 0x1;
++ }
++ }
+ }
+
+-void cec_set_standby(void)
++static void cec_device_vendor_id(void)
+ {
+- unsigned char msg[2];
++ unsigned char msg[5];
++ cec_dbg_prints("cec_device_vendor_id\n");
++
+ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_BROADCAST_ADDR;
+- msg[1] = CEC_OC_STANDBY;
++ msg[1] = CEC_OC_DEVICE_VENDOR_ID;
++ msg[2] = 0x00;
++ msg[3] = 0x00;
++ msg[4] = 0x00;
+
+- remote_cec_ll_tx(msg, 2);
++ cec_triggle_tx(msg, 5);
+ }
+
+-void cec_give_deck_status(void)
++static void cec_deck_status(unsigned char initiator)
+ {
+ unsigned char msg[3];
++ cec_dbg_printx("cec_deck_status initiator:0x", initiator, 4);
++ cec_dbg_prints("\n");
+
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_TV_ADDR;
++ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | (initiator & 0xf);
+ msg[1] = CEC_OC_DECK_STATUS;
+- msg[2] = 0x1a;
++ msg[2] = 0x1a; // DECK_STOP
+
+- remote_cec_ll_tx(msg, 3);
++ cec_triggle_tx(msg, 3);
+ }
+
+-void cec_set_osd_name(void)
++static void cec_set_osd_name(unsigned char initiator)
+ {
+ unsigned char msg[16];
+ unsigned char osd_len = cec_strlen(CONFIG_CEC_OSD_NAME);
++ cec_dbg_printx("cec_set_osd_name initiator:0x", initiator, 4);
++ cec_dbg_prints("\n");
+
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_TV_ADDR;
++ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | (initiator & 0xf);
+ msg[1] = CEC_OC_SET_OSD_NAME;
+ cec_memcpy(&msg[2], CONFIG_CEC_OSD_NAME, osd_len);
+
+- remote_cec_ll_tx(msg, osd_len + 2);
++ cec_triggle_tx(msg, osd_len + 2);
+ }
+
+-void cec_get_version(void)
++static void cec_get_version(unsigned char initiator)
+ {
+- unsigned char dest_log_addr = cec_msg.log_addr & 0xf;
+ unsigned char msg[3];
++ cec_dbg_printx("cec_get_version initiator:0x", initiator, 4);
++ cec_dbg_prints("\n");
+
+- if (0xf != dest_log_addr) {
+- msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_TV_ADDR;
+- msg[1] = CEC_OC_CEC_VERSION;
+- msg[2] = CEC_VERSION_14A;
+- remote_cec_ll_tx(msg, 3);
+- }
++ msg[0] = ((cec_msg.log_addr & 0xf) << 4) | (initiator & 0xf);
++ msg[1] = CEC_OC_CEC_VERSION;
++ msg[2] = CEC_VERSION_14A;
++
++ cec_triggle_tx(msg, 3);
+ }
+
+-unsigned int cec_handle_message(void)
++static unsigned int cec_handle_message(void)
+ {
+- unsigned char opcode;
+-
+- if (((hdmi_cec_func_config>>CEC_FUNC_MASK) & 0x1) &&
+- (cec_msg.buf[cec_msg.rx_read_pos].msg_len > 1)) {
+- opcode = cec_msg.buf[cec_msg.rx_read_pos].msg[1];
+- switch (opcode) {
+- case CEC_OC_GET_CEC_VERSION:
+- cec_get_version();
+- break;
+- case CEC_OC_GIVE_DECK_STATUS:
+- cec_give_deck_status();
+- break;
+- case CEC_OC_GIVE_PHYSICAL_ADDRESS:
+- cec_report_physical_address();
+- break;
+- case CEC_OC_GIVE_DEVICE_VENDOR_ID:
+- cec_device_vendor_id();
+- break;
+- case CEC_OC_GIVE_OSD_NAME:
+- cec_set_osd_name();
+- break;
+- case CEC_OC_SET_STREAM_PATH:
+- cec_set_stream_path();
+- break;
+- case CEC_OC_GIVE_DEVICE_POWER_STATUS:
+- cec_report_device_power_status();
+- break;
+- case CEC_OC_USER_CONTROL_PRESSED:
+- if (((hdmi_cec_func_config >> CEC_FUNC_MASK) & 0x1) &&
+- ((hdmi_cec_func_config >> AUTO_POWER_ON_MASK) & 0x1) &&
+- (cec_msg.buf[cec_msg.rx_read_pos].msg_len == 3) &&
+- ((0x40 == cec_msg.buf[cec_msg.rx_read_pos].msg[2]) ||
+- (0x6d == cec_msg.buf[cec_msg.rx_read_pos].msg[2]) ||
+- (0x09 == cec_msg.buf[cec_msg.rx_read_pos].msg[2]) )) {
+- cec_msg.cec_power = 0x1;
+- }
+- break;
+- case CEC_OC_MENU_REQUEST:
+- cec_menu_status_smp(DEVICE_MENU_INACTIVE);
+- break;
+- default:
+- break;
++ unsigned char initiator = (cec_msg.msg[0] >> 4) & 0xf;
++ unsigned char destination = cec_msg.msg[0] & 0xf;
++ unsigned char opcode = (cec_msg.msg_len > 1) ? cec_msg.msg[1] : CEC_OC_POLLING_MESSAGE;
++ unsigned char directly_addressed = (destination != CEC_BROADCAST_ADDR && destination == cec_msg.log_addr);
++
++ cec_dbg_printx("cec_handle_message initiator:0x", initiator, 4);
++ cec_dbg_printx(", destination:0x", destination, 4);
++ cec_dbg_print(", opcode:0x", opcode);
++ cec_dbg_prints("\n");
++
++ switch (opcode) {
++ case CEC_OC_POLLING_MESSAGE:
++ break;
++ case CEC_OC_GET_CEC_VERSION:
++ if (directly_addressed)
++ cec_get_version(initiator);
++ break;
++ case CEC_OC_GIVE_DECK_STATUS:
++ cec_deck_status(initiator);
++ break;
++ case CEC_OC_GIVE_PHYSICAL_ADDRESS:
++ cec_report_physical_address();
++ break;
++ case CEC_OC_GIVE_DEVICE_VENDOR_ID:
++ cec_device_vendor_id();
++ break;
++ case CEC_OC_VENDOR_COMMAND:
++ case CEC_OC_VENDOR_COMMAND_WITH_ID:
++ break;
++ case CEC_OC_GIVE_OSD_NAME:
++ if (directly_addressed)
++ cec_set_osd_name(initiator);
++ break;
++ case CEC_OC_SET_STREAM_PATH:
++ cec_set_stream_path(initiator);
++ break;
++ case CEC_OC_ROUTING_CHANGE:
++ cec_routing_change(initiator);
++ break;
++ case CEC_OC_GIVE_DEVICE_POWER_STATUS:
++ if (directly_addressed)
++ cec_report_power_status(initiator);
++ break;
++ case CEC_OC_USER_CONTROL_PRESSED:
++ if (directly_addressed)
++ cec_user_control_pressed();
++ break;
++ case CEC_OC_USER_CONTROL_RELEASED:
++ break;
++ case CEC_OC_MENU_REQUEST:
++ if (directly_addressed)
++ cec_menu_status(DEVICE_MENU_INACTIVE, initiator);
++ break;
++ case CEC_OC_ABORT_MESSAGE:
++ if (directly_addressed)
++ cec_feature_abort(CEC_UNRECONIZED_OPCODE, initiator);
++ break;
++ default:
++ if (directly_addressed) {
++ cec_dbg_print("WARNING: unhandled directly addressed opcode:0x", opcode);
++ cec_dbg_prints("\n");
++ cec_feature_abort(CEC_UNABLE_TO_DETERMINE, initiator);
+ }
++ break;
+ }
+- cec_rx_read_pos_plus();
+ return 0;
+ }
+
+-void cec_reset_addr(void)
++static unsigned int cec_tx_irq_handler(void)
+ {
+- remote_cec_hw_reset();
+- cec_wr_reg(CEC_LOGICAL_ADDR0, 0);
+- cec_hw_buf_clear();
+- cec_wr_reg(CEC_LOGICAL_ADDR0, cec_msg.log_addr);
+- _udelay(100);
+- cec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | cec_msg.log_addr);
++ unsigned int cnt = 0;
++ unsigned int tx_msg_status = cec_rd_reg(CEC_TX_MSG_STATUS);
++ unsigned int tx_num_msg = cec_rd_reg(CEC_TX_NUM_MSG);
++ cec_dbg_printx("cec_tx_irq_handler tx_msg_status:0x", tx_msg_status, 4);
++ cec_dbg_printx(", tx_num_msg:0x", tx_num_msg, 4);
++ cec_dbg_prints("\n");
++
++ do {
++ cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
++ cnt++;
++ } while (cec_rd_reg(CEC_TX_NUM_MSG));
++ writel((1 << 1), P_AO_CEC_INTR_CLR);
++
++ if (cnt > 1) {
++ cec_dbg_printx("WARNING: cec_tx_irq_handler cnt:0x", cnt, 16);
++ cec_dbg_prints("\n");
++ }
++
++ return 0;
+ }
+
+-unsigned int cec_handler(void)
++static unsigned int cec_rx_irq_handler(void)
+ {
+- unsigned char s_idx;
+- static int busy_count = 0;
+- if (0xf == cec_rd_reg(CEC_RX_NUM_MSG)) {
+- cec_wr_reg(CEC_RX_CLEAR_BUF, 0x1);
+- cec_wr_reg(CEC_RX_CLEAR_BUF, 0x0);
+- cec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT);
+- cec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP);
+- cec_dbg_prints("error:hw_buf overflow\n");
+- }
++ unsigned int cnt = 0;
++ unsigned int rx_msg_status = cec_rd_reg(CEC_RX_MSG_STATUS);
++ unsigned int rx_num_msg = cec_rd_reg(CEC_RX_NUM_MSG);
++ cec_dbg_printx("cec_rx_irq_handler rx_msg_status:0x", rx_msg_status, 4);
++ cec_dbg_printx(", rx_num_msg:0x", rx_num_msg, 4);
++ cec_dbg_prints("\n");
+
+- switch (cec_rd_reg(CEC_RX_MSG_STATUS)) {
+- case RX_DONE:
+- if (1 == cec_rd_reg(CEC_RX_NUM_MSG)) {
+- remote_cec_ll_rx();
+- (cec_msg.rx_write_pos == cec_msg.rx_buf_size - 1) ? (cec_msg.rx_write_pos = 0) : (cec_msg.rx_write_pos++);
++ if (rx_num_msg) {
++ unsigned int i, rx_msg_length = cec_rd_reg(CEC_RX_MSG_LENGTH) + 1;
++ cec_dbg_prints(" R:");
++ for (i = 0; i < rx_msg_length && i < MAX_MSG; i++) {
++ cec_msg.msg[i] = cec_rd_reg(CEC_RX_MSG_0_HEADER + i);
++ cec_dbg_print(" ", cec_msg.msg[i]);
+ }
+- cec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT);
+- cec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP);
+- cec_dbg_prints("RX_OK\n");
+- break;
+- case RX_ERROR:
+- cec_dbg_prints("RX_ERROR\n");
+- if (TX_ERROR == cec_rd_reg(CEC_TX_MSG_STATUS)) {
+- cec_dbg_prints("TX_ERROR\n");
+- cec_reset_addr();
+- } else {
+- cec_dbg_prints("TX_other\n");
+- cec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT);
+- cec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP);
++ for (; i < MAX_MSG; i++) {
++ cec_msg.msg[i] = 0x0;
+ }
+- break;
+- default:
+- break;
++ cec_msg.msg_len = rx_msg_length;
++ cec_dbg_prints("\n");
+ }
+
+- switch (cec_rd_reg(CEC_TX_MSG_STATUS)) {
+- case TX_DONE:
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+- cec_tx_msgs.send_idx = (cec_tx_msgs.send_idx + 1) & CEC_TX_MSG_BUF_MASK;
+- s_idx = cec_tx_msgs.send_idx;
+- if (cec_tx_msgs.send_idx != cec_tx_msgs.queue_idx) {
+- cec_dbg_prints("TX_OK\n");
+- cec_triggle_tx(cec_tx_msgs.msg[s_idx].buf,
+- cec_tx_msgs.msg[s_idx].len);
+- } else {
+- cec_dbg_prints("TX_END\n");
+- }
+- busy_count = 0;
+- break;
++ do {
++ cec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT);
++ cec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP);
++ cnt++;
++ } while (cec_rd_reg(CEC_RX_NUM_MSG));
++ writel((1 << 2), P_AO_CEC_INTR_CLR);
+
+- case TX_ERROR:
+- cec_dbg_prints("@TX_ERROR\n");
+- if (RX_ERROR == cec_rd_reg(CEC_RX_MSG_STATUS)) {
+- cec_dbg_prints("@RX_ERROR\n");
+- cec_reset_addr();
+- } else {
+- cec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+- s_idx = cec_tx_msgs.send_idx;
+- if (cec_tx_msgs.msg[s_idx].retry < 5) {
+- cec_tx_msgs.msg[s_idx].retry++;
+- cec_triggle_tx(cec_tx_msgs.msg[s_idx].buf,
+- cec_tx_msgs.msg[s_idx].len);
+- } else {
+- cec_dbg_prints("TX retry too much, abort msg\n");
+- cec_tx_msgs.send_idx = (cec_tx_msgs.send_idx + 1) & CEC_TX_MSG_BUF_MASK;
+- }
+- }
+- busy_count = 0;
+- break;
++ if (cnt > 2) {
++ cec_dbg_printx("WARNING: cec_rx_irq_handler cnt:0x", cnt, 16);
++ cec_dbg_prints("\n");
++ }
+
+- case TX_IDLE:
+- s_idx = cec_tx_msgs.send_idx;
+- if (cec_tx_msgs.send_idx != cec_tx_msgs.queue_idx) { // triggle tx if idle
+- cec_triggle_tx(cec_tx_msgs.msg[s_idx].buf,
+- cec_tx_msgs.msg[s_idx].len);
+- }
+- busy_count = 0;
+- break;
++ if (rx_num_msg)
++ cec_handle_message();
+
+- case TX_BUSY:
+- busy_count++;
+- if (busy_count >= 2000) {
+- uart_puts("busy too long, reset hw\n");
+- cec_reset_addr();
+- busy_count = 0;
+- }
+- break;
++ return 0;
++}
+
+- default:
+- break;
++unsigned int cec_handler(void)
++{
++ unsigned int intr_stat = readl(P_AO_CEC_INTR_STAT);
++ if (intr_stat & (1<<1)) {
++ cec_tx_irq_handler();
+ }
+- if (cec_msg.rx_read_pos != cec_msg.rx_write_pos) {
+- cec_handle_message();
++ if (intr_stat & (1<<2)) {
++ cec_rx_irq_handler();
+ }
+-
+ return 0;
+ }
+
+ void cec_node_init(void)
+ {
+- static int i = 0;
+- static unsigned int retry = 0;
+- static int regist_devs = 0;
+- static enum _cec_log_dev_addr_e *probe = NULL;
+-
+- int tx_stat;
+- unsigned char msg[1];
+- unsigned int kern_log_addr = (readl(P_AO_DEBUG_REG1) >> 16) & 0xf;
+- enum _cec_log_dev_addr_e player_dev[3][3] =
+- {{CEC_PLAYBACK_DEVICE_1_ADDR, CEC_PLAYBACK_DEVICE_2_ADDR, CEC_PLAYBACK_DEVICE_3_ADDR},
+- {CEC_PLAYBACK_DEVICE_2_ADDR, CEC_PLAYBACK_DEVICE_3_ADDR, CEC_PLAYBACK_DEVICE_1_ADDR},
+- {CEC_PLAYBACK_DEVICE_3_ADDR, CEC_PLAYBACK_DEVICE_1_ADDR, CEC_PLAYBACK_DEVICE_2_ADDR}};
+-
+- if (retry >= 12) { // retry all device addr
+- cec_msg.log_addr = 0x0f;
+- uart_puts("failed on retried all possible address\n");
+- return ;
+- }
+- if (probe == NULL) {
+- cec_msg.rx_read_pos = 0;
+- cec_msg.rx_write_pos = 0;
+- cec_msg.rx_buf_size = 4;
+-
+- cec_msg.power_status = 1;
+- cec_msg.cec_power = 0;
+- cec_msg.test = 0x0;
+- cec_tx_msgs.send_idx = 0;
+- cec_tx_msgs.queue_idx = 0;
+- cec_tx_buf_init();
+- cec_buf_clear();
+- cec_wr_reg(CEC_LOGICAL_ADDR0, 0);
+- cec_hw_buf_clear();
+- cec_wr_reg(CEC_LOGICAL_ADDR0, 0xf);
+- _udelay(100);
+- cec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+- /*
+- * use kernel cec logic address to detect which logic address is the
+- * started one to allocate.
+- */
+- cec_dbg_print("kern log_addr:0x", kern_log_addr);
+- uart_puts("\n");
+- for (i = 0; i < 3; i++) {
+- if (kern_log_addr == player_dev[i][0]) {
+- probe = player_dev[i];
+- break;
+- }
+- }
+- if (probe == NULL) {
+- probe = player_dev[0];
+- }
+- i = 0;
+- }
++ unsigned int phy_addr = readl(P_AO_DEBUG_REG1) & 0xffff;
++ unsigned char log_addr = readl(P_AO_DEBUG_REG3) & 0xf;
+
+- msg[0] = (probe[i]<<4) | probe[i];
+- tx_stat = ping_cec_ll_tx(msg, 1);
+- if (tx_stat == TX_BUSY) { // can't get cec bus
+- retry++;
+- remote_cec_hw_reset();
+- if (!(retry & 0x03)) {
+- cec_dbg_print("retry too much, log_addr:0x", probe[i]);
+- uart_puts("\n");
+- } else {
+- i -= 1;
+- }
+- } else if (tx_stat == TX_ERROR) {
+- cec_wr_reg(CEC_LOGICAL_ADDR0, 0);
+- cec_hw_buf_clear();
+- cec_wr_reg(CEC_LOGICAL_ADDR0, probe[i]);
+- _udelay(100);
+- cec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | probe[i]);
+- cec_msg.log_addr = probe[i];
+- cec_dbg_print("Set cec log_addr:0x", cec_msg.log_addr);
+- cec_dbg_print(", ADDR0:", cec_rd_reg(CEC_LOGICAL_ADDR0));
+- uart_puts("\n");
+- probe = NULL;
+- regist_devs = 0;
+- i = 0;
+- retry = 0;
+- return ;
+- } else if (tx_stat == TX_DONE) {
+- cec_dbg_print("sombody takes cec log_addr:0x", probe[i]);
+- uart_puts("\n");
+- regist_devs |= (1 << i);
+- retry += (4 - (retry & 0x03));
+- if (regist_devs == 0x07) {
+- // No avilable logical address
+- cec_msg.log_addr = 0x0f;
+- cec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+- uart_puts("CEC allocate logic address failed\n");
+- }
+- }
+- i++;
+- if (i == 3) {
+- i = 0;
++ cec_dbg_print("cec_node_init cec_config:0x", hdmi_cec_func_config);
++ cec_dbg_printx(", log_addr:0x", log_addr, 4);
++ cec_dbg_printx(", phy_addr:0x", phy_addr, 16);
++ cec_dbg_prints("\n");
++
++ cec_msg.msg_len = 0;
++ cec_msg.cec_power = 0;
++ cec_msg.log_addr = log_addr;
++ cec_msg.phy_addr = phy_addr;
++
++ if (!cec_msg.log_addr || !cec_msg.phy_addr) {
++ cec_dbg_prints("WARNING: log/phy_addr is not set, disabling cec wakeup\n");
++ hdmi_cec_func_config = hdmi_cec_func_config & ~(0x1 << CEC_FUNC_MASK);
++ return;
+ }
++
++ cec_wr_reg(CEC_LOGICAL_ADDR0, 0);
++ cec_hw_buf_clear();
++ cec_wr_reg(CEC_LOGICAL_ADDR0, log_addr);
++ _udelay(100);
++ cec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | log_addr);
++ _udelay(100);
++
++ cec_report_physical_address();
++ cec_device_vendor_id();
++ cec_set_osd_name(CEC_TV_ADDR);
+ }
+
+ #endif
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c b/arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c
+index 5db0e69..b16910c 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c
+@@ -70,15 +70,15 @@ void enter_suspend(unsigned int suspend_from)
+ p_pwr_op = &pwr_op_d;
+ pwr_op_init(p_pwr_op);
+
+-/*
+ // FIXME : (1) BLUE LED GPIOAO_13 (2) Current issue 12*mA -> 7*mA
+ #ifdef CONFIG_CEC_WAKEUP
+- hdmi_cec_func_config = readl(P_AO_DEBUG_REG0);
++ hdmi_cec_func_config = readl(P_AO_DEBUG_REG0) & 0xff;
++ wait_uart_empty();
+ uart_puts("CEC cfg:0x");
+- uart_put_hex(hdmi_cec_func_config, 16);
++ uart_put_hex(hdmi_cec_func_config, 8);
+ uart_puts("\n");
++ wait_uart_empty();
+ #endif
+-*/
+ p_pwr_op->power_off_at_clk81();
+ p_pwr_op->power_off_at_24M();
+
+diff --git a/arch/arm/cpu/armv8/gxb/firmware/scp_task/task_apis.h b/arch/arm/cpu/armv8/gxb/firmware/scp_task/task_apis.h
+index fe6bd75..6ec5486 100644
+--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/task_apis.h
++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/task_apis.h
+@@ -14,8 +14,8 @@ int uart_puts(const char *s);
+
+ /* #define dbg_print(s,v) */
+ /* #define dbg_prints(s) */
+-#define writel(v, addr) (*((unsigned *)addr) = v)
+-#define readl(addr) (*((unsigned *)addr))
++#define writel(v, addr) (*((volatile unsigned *)addr) = v)
++#define readl(addr) (*((volatile unsigned *)addr))
+
+ #define dbg_print(s, v) {uart_puts(s); uart_put_hex(v, 32); uart_puts("\n"); }
+ /* #define dbg_prints(s) {uart_puts(s);wait_uart_empty();} */
+diff --git a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+index f6f2a7d..aa902be 100644
+--- a/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
++++ b/board/hardkernel/odroidc2/firmware/scp_task/pwr_ctrl.c
+@@ -8,6 +8,8 @@
+
+ #ifdef CONFIG_CEC_WAKEUP
+ #include
++#else
++typedef unsigned int uint32_t;
+ #endif
+
+ extern int pwm_voltage_table[31][2];
+@@ -227,7 +229,7 @@ unsigned int detect_key(unsigned int suspend_from)
+ unsigned int init_time = get_time();
+ init_remote();
+ #ifdef CONFIG_CEC_WAKEUP
+- if (hdmi_cec_func_config & 0x1) {
++ if ((hdmi_cec_func_config >> CEC_FUNC_MASK) & 0x1) {
+ remote_cec_hw_reset();
+ cec_node_init();
+ }
+@@ -236,19 +238,19 @@ unsigned int detect_key(unsigned int suspend_from)
+ set_custom_gpio_status();
+
+ do {
+- #ifdef CONFIG_CEC_WAKEUP
+- if (cec_msg.log_addr) {
+- if (hdmi_cec_func_config & 0x1) {
++#ifdef CONFIG_CEC_WAKEUP
++ if ((hdmi_cec_func_config >> CEC_FUNC_MASK) & 0x1) {
++ if (cec_msg.log_addr) {
+ cec_handler();
+ if (cec_msg.cec_power == 0x1) { //cec power key
+ exit_reason = CEC_WAKEUP;
+ break;
+ }
++ } else {
++ cec_node_init();
+ }
+- } else if (hdmi_cec_func_config & 0x1) {
+- cec_node_init();
+ }
+- #endif
++#endif
+ #if 0
+ if ((readl(AO_GPIO_I) & (1<<3)) == 0) {
+ exit_reason = POWER_KEY_WAKEUP;
diff --git a/scripts/mkimage b/scripts/mkimage
index 11c089cf20..b631fa295c 100755
--- a/scripts/mkimage
+++ b/scripts/mkimage
@@ -230,9 +230,8 @@ elif [ "$BOOTLOADER" = "u-boot" ]; then
# allow custom dd script for vendor specific fusing
. $RELEASE_DIR/3rdparty/bootloader/u-boot-fuse
elif [ -f "$RELEASE_DIR/3rdparty/bootloader/u-boot" ]; then
- dd if="$RELEASE_DIR/3rdparty/bootloader/bl1" of="$DISK" conv=fsync,notrunc bs=1 count=442 >"$SAVE_ERROR" 2>&1 || show_error
- dd if="$RELEASE_DIR/3rdparty/bootloader/bl1" of="$DISK" conv=fsync,notrunc bs=512 skip=1 seek=1 >"$SAVE_ERROR" 2>&1 || show_error
- dd if="$RELEASE_DIR/3rdparty/bootloader/u-boot" of="$DISK" conv=fsync,notrunc bs=512 seek=97 >"$SAVE_ERROR" 2>&1 || show_error
+ dd if="$RELEASE_DIR/3rdparty/bootloader/u-boot" of="$DISK" conv=fsync,notrunc bs=1 count=112 >"$SAVE_ERROR" 2>&1 || show_error
+ dd if="$RELEASE_DIR/3rdparty/bootloader/u-boot" of="$DISK" conv=fsync,notrunc bs=512 skip=1 seek=1 >"$SAVE_ERROR" 2>&1 || show_error
fi
echo "image: copying files to part1..."
@@ -247,6 +246,10 @@ elif [ "$BOOTLOADER" = "u-boot" ]; then
mcopy $RELEASE_DIR/3rdparty/bootloader/u-boot.img ::
fi
+ if [ -f $RELEASE_DIR/3rdparty/bootloader/boot-logo.bmp.gz ]; then
+ mcopy $RELEASE_DIR/3rdparty/bootloader/boot-logo.bmp.gz ::
+ fi
+
for dtb in $RELEASE_DIR/3rdparty/bootloader/*.dtb ; do
if [ -f $dtb ] ; then
mcopy "$dtb" ::/$(basename "$dtb")