diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 85e7fd5b42e6..0d45d2239a20 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -131,6 +131,10 @@ struct ao_cec_dev { struct vendor_info_data v_data; struct cec_global_info_t cec_info; struct cec_platform_data_s *plat_data; + unsigned int wakeup_st; + unsigned int msg_idx; + unsigned int msg_num; + struct st_rx_msg msgbuff[CEC_MSG_BUFF_MAX]; }; struct cec_msg_last { @@ -165,6 +169,7 @@ static struct hrtimer start_bit_check; static unsigned char rx_msg[MAX_MSG]; static unsigned char rx_len; static unsigned int new_msg; + /*static bool wake_ok = 1;*/ static bool ee_cec; static bool pin_status; @@ -416,6 +421,26 @@ void cec_dbg_init(void) stdbgflg.hal_cmd_bypass = 0; } +void cec_store_msg_to_buff(unsigned char len, unsigned char *msg) +{ + unsigned int i; + unsigned int msg_idx; + + if (!cec_dev) + return; + + if (cec_dev->wakeup_st && (len < MAX_MSG) && + (cec_dev->msg_idx < CEC_MSG_BUFF_MAX)) { + msg_idx = cec_dev->msg_idx; + cec_dev->msgbuff[msg_idx].len = len; + for (i = 0; i < MAX_MSG; i++) + cec_dev->msgbuff[msg_idx].msg[i] = msg[i]; + cec_dev->msg_idx++; + cec_dev->msg_num++; + CEC_INFO("save len %d, num %d\n", len, cec_dev->msg_idx); + } +} + void cecb_hw_reset(void) { /* cec disable */ @@ -602,8 +627,7 @@ void cecb_irq_handle(void) if ((intr_cec & CEC_IRQ_RX_EOM) || lock) { cecb_pick_msg(rx_msg, &rx_len); CEC_INFO_L(L_2, "irqflg:RX_EOM\n"); - /*complete(&cec_dev->rx_ok);*/ - /*new_msg = 1;*/ + cec_store_msg_to_buff(rx_len, rx_msg); cec_new_msg_push(); dwork = &cec_dev->cec_work; mod_delayed_work(cec_dev->cec_thread, dwork, 0); @@ -1334,6 +1358,8 @@ int ceca_rx_irq_handle(unsigned char *msg, unsigned char *len) msg[i] = aocec_rd_reg(CEC_RX_MSG_0_HEADER + i); ret = rx_stat; + /* for resume, cec hal not ready */ + cec_store_msg_to_buff(*len, msg); /* ignore ping message */ if (cec_msg_dbg_en && *len > 1) { @@ -2325,8 +2351,7 @@ static void ceca_tasklet_pro(unsigned long arg) if ((-1) == ceca_rx_irq_handle(rx_msg, &rx_len)) return; - /*complete(&cec_dev->rx_ok);*/ - /*new_msg = 1;*/ + cec_store_msg_to_buff(rx_len, rx_msg); cec_new_msg_push(); mod_delayed_work(cec_dev->cec_thread, dwork, 0); } @@ -2926,6 +2951,22 @@ static ssize_t hdmitx_cec_read(struct file *f, char __user *buf, size_t size, loff_t *p) { int ret; + unsigned int idx; + unsigned int len = 0; + + if (!cec_dev) + return 0; + + if (cec_dev->msg_num) { + cec_dev->msg_num--; + idx = cec_dev->msg_idx; + len = cec_dev->msgbuff[idx].len; + cec_dev->msg_idx++; + if (copy_to_user(buf, &cec_dev->msgbuff[idx].msg[0], len)) + return -EINVAL; + CEC_INFO("read msg from buff len=%d\n", len); + return len; + } /*CEC_ERR("read msg start\n");*/ ret = wait_for_completion_timeout(&cec_dev->rx_ok, CEC_FRAME_DELAY); @@ -2943,6 +2984,7 @@ static ssize_t hdmitx_cec_read(struct file *f, char __user *buf, /*CEC_ERR("read msg end\n");*/ if (copy_to_user(buf, rx_msg, rx_len)) return -EINVAL; + CEC_INFO("read msg len=%d\n", rx_len); return rx_len; } @@ -3436,9 +3478,14 @@ static void aocec_early_suspend(struct early_suspend *h) static void aocec_late_resume(struct early_suspend *h) { + if (!cec_dev) + return; + + cec_dev->wakeup_st = 0; + cec_dev->msg_idx = 0; + cec_dev->cec_suspend = CEC_PW_POWER_ON; CEC_ERR("%s, suspend sts:%d\n", __func__, cec_dev->cec_suspend); - } #endif @@ -4015,6 +4062,21 @@ static int aml_cec_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int aml_cec_pm_prepare(struct device *dev) { + unsigned int i, j; + + if (IS_ERR_OR_NULL(cec_dev)) { + pr_info("%s cec_dev is null\n", __func__); + return 0; + } + /*initial msg buffer*/ + cec_dev->wakeup_st = 0; + cec_dev->msg_idx = 0; + cec_dev->msg_num = 0; + for (i = 0; i < CEC_MSG_BUFF_MAX; i++) { + cec_dev->msgbuff[i].len = 0; + for (j = 0; j < MAX_MSG; j++) + cec_dev->msgbuff[i].msg[j] = 0; + } //cec_dev->cec_suspend = CEC_DEEP_SUSPEND; CEC_ERR("%s\n", __func__); return 0; @@ -4022,6 +4084,12 @@ static int aml_cec_pm_prepare(struct device *dev) static void aml_cec_pm_complete(struct device *dev) { + if (IS_ERR_OR_NULL(cec_dev)) + return; + + cec_dev->wakeup_st = 0; + cec_dev->msg_idx = 0; + if (get_resume_method() == CEC_WAKEUP) { cec_key_report(0); @@ -4067,7 +4135,11 @@ static int aml_cec_resume_noirq(struct device *dev) cec_dev->cec_info.power_status = CEC_PW_TRANS_STANDBY_TO_ON; cec_dev->cec_suspend = CEC_PW_TRANS_STANDBY_TO_ON; + /*initial msg buffer*/ + cec_dev->msg_idx = 0; + cec_dev->msg_num = 0; if (!is_pm_freeze_mode()) { + cec_clear_all_logical_addr(ee_cec); scpi_get_wakeup_reason(&cec_dev->wakeup_reason); CEC_ERR("wakeup_reason:0x%x\n", cec_dev->wakeup_reason); @@ -4079,6 +4151,8 @@ static int aml_cec_resume_noirq(struct device *dev) cec_dev->wakup_data.wk_port_id); scpi_get_cec_val(SCPI_CMD_GET_CEC2, &temp); CEC_ERR("cev val2: 0x%#x\n", temp); + /* disable all logical address */ + /*cec_dev->cec_info.addr_enable = 0;*/ } else { CEC_ERR("freeze mode\n"); } @@ -4087,9 +4161,10 @@ static int aml_cec_resume_noirq(struct device *dev) ret = pinctrl_pm_select_default_state(cec_dev->dbg_dev); else CEC_ERR("pinctrl default_state error\n"); - + cec_irq_enable(true); cec_dev->cec_info.power_status = CEC_PW_POWER_ON; cec_dev->cec_suspend = CEC_PW_POWER_ON; + cec_dev->wakeup_st = 1; return 0; } diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 635dab27c771..def2126892c8 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -18,7 +18,7 @@ #ifndef __AO_CEC_H__ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "2019/11/15:add poll for andorid chk new msg\n" +#define CEC_DRIVER_VERSION "2019/11/12: store msg during bootup from st\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "cec" @@ -83,6 +83,8 @@ enum cecbver { #define ENABLE_ONE_CEC 1 #define ENABLE_TWO_CEC 2 +#define CEC_MSG_BUFF_MAX 30 + /* #define CEC_FUNC_MASK 0 #define ONE_TOUCH_PLAY_MASK 1 @@ -518,6 +520,11 @@ struct dbgflg { }; +struct st_rx_msg { + unsigned char len; + unsigned char msg[16]; +}; + #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI extern unsigned long hdmirx_rd_top(unsigned long addr); extern void hdmirx_wr_top(unsigned long addr, unsigned long data);