diff --git a/packages/tools/u-boot/package.mk b/packages/tools/u-boot/package.mk index e27b317096..784e8eb324 100644 --- a/packages/tools/u-boot/package.mk +++ b/packages/tools/u-boot/package.mk @@ -25,7 +25,7 @@ if [ "$UBOOT_VERSION" = "imx6-cuboxi" ]; then PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" [ -n "$UBOOT_CONFIG_V2" ] && PKG_DEPENDS_TARGET="toolchain u-boot-v2" elif [ "$UBOOT_VERSION" = "hardkernel" ]; then - PKG_VERSION="61f29bb" + PKG_VERSION="6e4e886" 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-elf:host gcc-linaro-arm-eabi:host" 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/6e4e886/u-boot-0001-use-arm-eabi-for-bl301-scp_task.patch similarity index 100% rename from packages/tools/u-boot/patches/61f29bb/u-boot-0001-use-arm-eabi-for-bl301-scp_task.patch rename to packages/tools/u-boot/patches/6e4e886/u-boot-0001-use-arm-eabi-for-bl301-scp_task.patch diff --git a/projects/Odroid_C2/bootloader/boot.ini b/projects/Odroid_C2/bootloader/boot.ini index e1df57a56a..1d5516845b 100644 --- a/projects/Odroid_C2/bootloader/boot.ini +++ b/projects/Odroid_C2/bootloader/boot.ini @@ -136,13 +136,42 @@ setenv hdmi_cec "1" #------------------------------------------------------------------------------------------------------ setenv audio_dac "0" +#------------------------------------------------------------------------------------------------------ +# +# CPU Frequency / Cores control +# +# WARNING!!! WARNING!!! WARNING!!! +# Before changing anything here please read the wiki entry: +# http://odroid.com/dokuwiki/doku.php?id=en:c2_set_cpu_freq +# +# MAX CPU's +# setenv maxcpus "1" +# setenv maxcpus "2" +# setenv maxcpus "3" +# setenv maxcpus "4" +# +# MAX Frequency +# setenv max_freq "2016" # 2.016GHz +# setenv max_freq "1944" # 1.944GHz +# setenv max_freq "1944" # 1.944GHz +# setenv max_freq "1920" # 1.920GHz +# setenv max_freq "1896" # 1.896GHz +# setenv max_freq "1752" # 1.752GHz +# setenv max_freq "1680" # 1.680GHz +# setenv max_freq "1656" # 1.656GHz +# setenv max_freq "1536" # 1.536GHz +# +#------------------------------------------------------------------------------------------------------ +setenv maxcpus "4" +setenv max_freq "1536" + #------------------------------------------------------------------------------------------------------ # # Odroid C1 specific # #------------------------------------------------------------------------------------------------------ setenv odroidp1 "no_console_suspend hdmimode=${video_output} m_bpp=${video_bpp} vout=${video_mode}" -setenv odroidp2 "${disableuhs} consoleblank=0" +setenv odroidp2 "${disableuhs} consoleblank=0 max_freq=${max_freq} maxcpus=${maxcpus}" setenv odroid "${odroidp1} ${odroidp2}" #------------------------------------------------------------------------------------------------------ diff --git a/projects/Odroid_C2/patches/linux/linux-008-max_freq_dvfs_table.patch b/projects/Odroid_C2/patches/linux/linux-008-max_freq_dvfs_table.patch new file mode 100644 index 0000000000..c961848a26 --- /dev/null +++ b/projects/Odroid_C2/patches/linux/linux-008-max_freq_dvfs_table.patch @@ -0,0 +1,97 @@ +From dee146cbbb8428b073fba85390577590fc365d86 Mon Sep 17 00:00:00 2001 +From: Joy Cho +Date: Wed, 31 Aug 2016 16:27:48 +0900 +Subject: [PATCH] ODROID-C2: Add setup routine to set max. cpu frequency of + dvfs table + +- set "max_freq" in boot.ini +- in MHz unit +ex) setenv max_freq "1656" + +Change-Id: I352c9540d0c34d3ec0ba0f470dae9d4e0786c001 +--- + drivers/amlogic/mailbox/scpi_protocol.c | 53 +++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/drivers/amlogic/mailbox/scpi_protocol.c b/drivers/amlogic/mailbox/scpi_protocol.c +index ec787d2..f3aa3e0 100644 +--- a/drivers/amlogic/mailbox/scpi_protocol.c ++++ b/drivers/amlogic/mailbox/scpi_protocol.c +@@ -129,6 +129,12 @@ static int high_priority_cmds[] = { + SCPI_CMD_SENSOR_CFG_BOUNDS, + }; + ++#if defined(CONFIG_ARCH_MESON64_ODROIDC2) ++#define DVFS_COUNT_MAX 13 ++#define DVFS_COUNT_1536 6 ++static unsigned long max_freq_dvfs; ++#endif ++ + static struct scpi_opp *scpi_opps[MAX_DVFS_DOMAINS]; + + static int scpi_linux_errmap[SCPI_ERR_MAX] = { +@@ -267,6 +273,9 @@ struct scpi_opp *scpi_dvfs_get_opps(u8 domain) + struct scpi_opp *opps; + size_t opps_sz; + int count, ret; ++#if defined(CONFIG_ARCH_MESON64_ODROIDC2) ++ int i, max_index; ++#endif + + if (domain >= MAX_DVFS_DOMAINS) + return ERR_PTR(-EINVAL); +@@ -285,6 +294,27 @@ struct scpi_opp *scpi_dvfs_get_opps(u8 domain) + return ERR_PTR(-ENOMEM); + + count = DVFS_OPP_COUNT(buf.header); ++ ++#if defined(CONFIG_ARCH_MESON64_ODROIDC2) ++ max_index = 0; ++ if (max_freq_dvfs) { ++ for (i = 0; i < count; i++) { ++ if (buf.opp[i].freq_hz == max_freq_dvfs) ++ break; ++ else ++ max_index++; ++ } ++ count = max_index + 1; ++ } ++ /* if no param "max_freq_dvfs or wrong "max_freq_dvfs" ++ * from boot.ini, consider stable max value */ ++ if ((max_freq_dvfs == 0) || (count > DVFS_COUNT_MAX)) ++ count = DVFS_COUNT_1536; /* default max : 1.536GHz */ ++ ++ pr_info("dvfs [%s] - new count %d, max_freq %ld\n", __func__, ++ count, max_freq_dvfs); ++#endif ++ + opps_sz = count * sizeof(*(opps->opp)); + + opps->count = count; +@@ -416,3 +446,26 @@ int scpi_get_sensor_value(u16 sensor, u32 *val) + return ret; + } + EXPORT_SYMBOL_GPL(scpi_get_sensor_value); ++ ++#if defined(CONFIG_ARCH_MESON64_ODROIDC2) ++static int __init get_max_freq(char *str) ++{ ++ int ret; ++ ++ if (NULL == str) { ++ /* consider default set */ ++ max_freq_dvfs = 1536000000; ++ return -EINVAL; ++ } ++ ++ ret = kstrtoul(str, 0, &max_freq_dvfs); ++ ++ /* in unit Hz */ ++ max_freq_dvfs *= 1000000; ++ ++ pr_info("dvfs [%s] - max_freq : %ld\n", __func__, max_freq_dvfs); ++ ++ return 0; ++} ++__setup("max_freq=", get_max_freq); ++#endif 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 deleted file mode 100644 index 67ad437a48..0000000000 --- a/projects/Odroid_C2/patches/u-boot/u-boot-0002-fix-power-off-wakeup.patch +++ /dev/null @@ -1,1468 +0,0 @@ -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/projects/Odroid_C2/patches/u-boot/u-boot-0002-update_cec_wakeup_code.patch b/projects/Odroid_C2/patches/u-boot/u-boot-0002-update_cec_wakeup_code.patch new file mode 100644 index 0000000000..d8e5c0916c --- /dev/null +++ b/projects/Odroid_C2/patches/u-boot/u-boot-0002-update_cec_wakeup_code.patch @@ -0,0 +1,225 @@ +From c2ebdfc8d2a03f583410db24bb8086044e9c72bb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 7 Sep 2016 20:55:24 +0200 +Subject: [PATCH] Update CEC wakeup code + +This also removes the forced cec config +--- + .../cpu/armv8/gxb/firmware/scp_task/hdmi_cec_arc.c | 102 ++++++++++++--------- + arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c | 2 - + 2 files changed, 58 insertions(+), 46 deletions(-) + +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 969777f..7d397ca 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 +@@ -41,7 +41,7 @@ static void *cec_memcpy(void *memto, const void *memfrom, unsigned int size) + } + + static void waiting_aocec_free(void) { +- unsigned int cnt = 0; ++ unsigned long cnt = 0; + while (readl(P_AO_CEC_RW_REG) & (1<<23)) + { + if (8192 <= cnt++) +@@ -146,8 +146,6 @@ void remote_cec_hw_reset(void) + static int cec_triggle_tx(unsigned char *msg, unsigned char len) + { + unsigned int i, cnt = 0; +- cec_dbg_print("cec_triggle_tx len:0x", len); +- cec_dbg_prints("\n"); + + cec_dbg_prints(" T:"); + for (i = 0; i < len; i++) { +@@ -168,6 +166,7 @@ static int cec_triggle_tx(unsigned char *msg, unsigned char len) + cec_dbg_prints("\n"); + } + ++ _udelay(150); + return 0; + } + +@@ -180,7 +179,7 @@ static int cec_triggle_tx(unsigned char *msg, unsigned char len) + #define DEVICE_PURE_CEC_SWITCH 6 + #define DEVICE_VIDEO_PROCESSOR 7 + +-static unsigned char log_addr_to_devtype(unsigned int addr) ++static unsigned char log_addr_to_devtype(unsigned char addr) + { + static unsigned char addr_map[] = { + DEVICE_TV, +@@ -211,7 +210,7 @@ static void cec_report_physical_address(void) + msg[0] = ((cec_msg.log_addr & 0xf) << 4) | CEC_BROADCAST_ADDR; + msg[1] = CEC_OC_REPORT_PHYSICAL_ADDRESS; + msg[2] = (cec_msg.phy_addr >> 8) & 0xff; +- msg[3] = cec_msg.phy_addr & 0xff; ++ msg[3] = (cec_msg.phy_addr >> 0) & 0xff; + msg[4] = log_addr_to_devtype(cec_msg.log_addr); + + cec_triggle_tx(msg, 5); +@@ -245,18 +244,44 @@ static void cec_feature_abort(unsigned char reason, unsigned char initiator) + cec_triggle_tx(msg, 4); + } + +-static void cec_set_stream_path(void) ++static void cec_menu_status(unsigned char menu_status, unsigned char initiator) ++{ ++ 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) | (initiator & 0xf); ++ msg[1] = CEC_OC_MENU_STATUS; ++ msg[2] = menu_status; ++ ++ cec_triggle_tx(msg, 3); ++} ++ ++static void cec_set_stream_path(unsigned char initiator) + { +- unsigned char phy_addr_ab = (cec_msg.phy_addr >> 8) & 0xff; +- unsigned char phy_addr_cd = cec_msg.phy_addr & 0xff; +- cec_dbg_prints("cec_set_stream_path\n"); +- +- if ((hdmi_cec_func_config >> AUTO_POWER_ON_MASK) & 0x1) { +- if ((hdmi_cec_func_config >> STREAMPATH_POWER_ON_MASK) & 0x1) { +- if ((phy_addr_ab == cec_msg.msg[2]) && +- (phy_addr_cd == cec_msg.msg[3])) { +- cec_msg.cec_power = 0x1; +- } ++ 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"); ++ ++ 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; ++ } ++ } ++} ++ ++static void cec_routing_change(unsigned char initiator) ++{ ++ 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"); ++ ++ 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; + } + } + } +@@ -266,10 +291,14 @@ static void cec_user_control_pressed(void) + cec_dbg_print("cec_user_control_pressed operation:0x", cec_msg.msg[2]); + cec_dbg_prints("\n"); + +- if ((hdmi_cec_func_config >> AUTO_POWER_ON_MASK) & 0x1) { ++ 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; + } +@@ -290,20 +319,6 @@ static void cec_device_vendor_id(void) + cec_triggle_tx(msg, 5); + } + +-static void cec_menu_status(unsigned char menu_status, unsigned char initiator) +-{ +- 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) | (initiator & 0xf); +- msg[1] = CEC_OC_MENU_STATUS; +- msg[2] = menu_status; +- +- cec_triggle_tx(msg, 3); +-} +- + static void cec_deck_status(unsigned char initiator) + { + unsigned char msg[3]; +@@ -349,7 +364,7 @@ static unsigned int cec_handle_message(void) + 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 != 0xf && destination == cec_msg.log_addr); ++ 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); +@@ -380,7 +395,10 @@ static unsigned int cec_handle_message(void) + cec_set_osd_name(initiator); + break; + case CEC_OC_SET_STREAM_PATH: +- cec_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) +@@ -494,16 +512,7 @@ unsigned int cec_handler(void) + void cec_node_init(void) + { + unsigned int phy_addr = readl(P_AO_DEBUG_REG1) & 0xffff; +- unsigned int log_addr = readl(P_AO_DEBUG_REG3) & 0xf; +- if (!log_addr) +- log_addr = 0xf; +- +- cec_dbg_printx("AO_DEBUG_REG0:0x", readl(P_AO_DEBUG_REG0), 32); +- cec_dbg_printx(", AO_DEBUG_REG1:0x", readl(P_AO_DEBUG_REG1), 32); +- cec_dbg_prints("\n"); +- cec_dbg_printx("AO_DEBUG_REG2:0x", readl(P_AO_DEBUG_REG2), 32); +- cec_dbg_printx(", AO_DEBUG_REG3:0x", readl(P_AO_DEBUG_REG3), 32); +- cec_dbg_prints("\n"); ++ unsigned char log_addr = readl(P_AO_DEBUG_REG3) & 0xf; + + cec_dbg_print("cec_node_init cec_config:0x", hdmi_cec_func_config); + cec_dbg_printx(", log_addr:0x", log_addr, 4); +@@ -515,6 +524,12 @@ void cec_node_init(void) + 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); +@@ -523,7 +538,6 @@ void cec_node_init(void) + _udelay(100); + + cec_report_physical_address(); +- _udelay(150); + cec_device_vendor_id(); + cec_set_osd_name(CEC_TV_ADDR); + } +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 8a414da..b16910c 100644 +--- a/arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c ++++ b/arch/arm/cpu/armv8/gxb/firmware/scp_task/suspend.c +@@ -73,8 +73,6 @@ void enter_suspend(unsigned int suspend_from) + // 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) & 0xff; +- if (!hdmi_cec_func_config) +- hdmi_cec_func_config = 0x2f; // Force cec config until kernel is "fixed" + wait_uart_empty(); + uart_puts("CEC cfg:0x"); + uart_put_hex(hdmi_cec_func_config, 8);