From 253acf4855327450dee7d13bf408272dcd9ad614 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Sat, 28 Sep 2019 10:54:01 +0800 Subject: [PATCH] cec: Add Feature for freeze mode power on [1/2] PD#TV-10483 Problem: Add feature for freeze mode power on by cec. Solution: Add feature for freeze mode power on by cec. Verify: tl1 Change-Id: I3e0271cb000d64c4b30cfc75c59e8ca374993d7f Signed-off-by: Yong Qin --- drivers/amlogic/cec/hdmi_ao_cec.c | 172 +++++++++++++++++---- drivers/amlogic/cec/hdmi_ao_cec.h | 3 +- .../amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h | 2 + 3 files changed, 144 insertions(+), 33 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index d8b91fa..681c65f 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -48,7 +48,9 @@ #include #include #include - +#include +#include +#include #include #include #include @@ -579,6 +581,8 @@ void cecb_irq_handle(void) complete(&cec_dev->rx_ok); new_msg = 1; dwork = &cec_dev->cec_work; + if (is_pm_freeze_mode()) + cec_freeze_mode_process(); mod_delayed_work(cec_dev->cec_thread, dwork, 0); } @@ -1863,6 +1867,10 @@ static int cec_late_check_rx_buffer(void) void cec_key_report(int suspend) { + if (is_pm_freeze_mode()) { + pm_wakeup_event(cec_dev->dbg_dev, 2000); + CEC_INFO("freeze mode:pm_wakeup_event\n"); + } input_event(cec_dev->cec_info.remote_cec_dev, EV_KEY, KEY_POWER, 1); input_sync(cec_dev->cec_info.remote_cec_dev); input_event(cec_dev->cec_info.remote_cec_dev, EV_KEY, KEY_POWER, 0); @@ -2158,6 +2166,63 @@ static bool cec_service_suspended(void) return false; } +static void cec_save_pre_setting(void) +{ + unsigned int config_data; + + /*if (is_pm_freeze_mode())*/ + /* cec_config(CEC_FUNC_CFG_ALL, 1);*/ + /* AO_DEBUG_REG1 + * 0-15 : phy addr + * 16-20: logical address + * 21-23: device type + */ + config_data = cec_dev->cec_info.log_addr; + cec_set_reg_bits(AO_DEBUG_REG1, config_data, 16, 4); + config_data = cec_dev->dev_type; + cec_set_reg_bits(AO_DEBUG_REG1, config_data, 20, 4); + CEC_ERR("%s: logaddr:0x%x, devtype:0x%x\n", __func__, + cec_dev->cec_info.log_addr, + config_data = cec_dev->dev_type); +} + +static void cec_restore_pre_setting(void) +{ + unsigned int logaddr; + unsigned int devtype; + unsigned int config_data; + char *token; + + config_data = cec_config(0, 0); + /*get device type*/ + logaddr = (config_data >> 16) & 0xf; + devtype = (config_data >> 20) & 0xf; + /*get logical address*/ + if (cec_dev->cec_num > ENABLE_ONE_CEC) + cec_logicaddr_add(CEC_B, logaddr); + else + cec_logicaddr_add(ee_cec, logaddr); + cec_dev->cec_info.addr_enable |= (1 << logaddr); + + /* add by hal, to init some data structure */ + cec_dev->dev_type = devtype; + cec_dev->cec_info.log_addr = logaddr; + cec_dev->cec_info.vendor_id = cec_dev->v_data.vendor_id; + CEC_ERR("%s: logaddr:0x%x, devtype:0x%x\n", __func__, + cec_dev->cec_info.log_addr, + config_data = cec_dev->dev_type); + + /*suspend freeze mode, driver handle cec msg*/ + cec_dev->hal_flag &= ~(1 << HDMI_OPTION_SERVICE_FLAG); + if (cec_msg_dbg_en) { + cec_status(); + token = kmalloc(2048, GFP_KERNEL); + dump_cecrx_reg(token); + CEC_ERR("%s\n", token); + kfree(token); + } +} + static void cec_task(struct work_struct *work) { struct delayed_work *dwork = &cec_dev->cec_work; @@ -2184,6 +2249,16 @@ static void cec_task(struct work_struct *work) queue_delayed_work(cec_dev->cec_thread, dwork, CEC_FRAME_DELAY); } +void cec_freeze_mode_process(void) +{ + unsigned int cec_cfg; + + CEC_ERR("%s\n", __func__); + cec_cfg = cec_config(0, 0); + if (cec_cfg & CEC_FUNC_CFG_CEC_ON) + cec_rx_process(); +} + static void ceca_tasklet_pro(unsigned long arg) { unsigned int intr_stat = 0; @@ -2714,6 +2789,9 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, return count; cec_ip_share_io(true, val); pr_info("share_io %d (0:a to b, 1:b to a)\n", val); + } else if (token && strncmp(token, "setfreeze", 9) == 0) { + cec_save_pre_setting(); + CEC_ERR("Set enter freeze mode\n"); } else { if (token) CEC_ERR("no cmd:%s, supported list:\n", token); @@ -2748,7 +2826,6 @@ static ssize_t dbg_show(struct class *cla, return 0; } - static struct class_attribute aocec_class_attr[] = { __ATTR_WO(cmd), __ATTR_WO(cmda), @@ -3203,7 +3280,13 @@ static long hdmitx_cec_ioctl(struct file *f, return -EINVAL; } break; - + case CEC_IOC_SET_FREEZE_MODE: + /* system enter power down freeze mode + * need save current device type and logical addr + */ + cec_save_pre_setting(); + CEC_ERR("need enter freeze mode\n"); + break; default: CEC_ERR("error ioctrl\n"); break; @@ -3256,13 +3339,13 @@ static const struct file_operations hdmitx_cec_fops = { static void aocec_early_suspend(struct early_suspend *h) { cec_dev->cec_suspend = CEC_PW_STANDBY; - CEC_INFO("%s, suspend:%d\n", __func__, cec_dev->cec_suspend); + CEC_ERR("%s, suspend sts:%d\n", __func__, cec_dev->cec_suspend); } static void aocec_late_resume(struct early_suspend *h) { cec_dev->cec_suspend = CEC_PW_POWER_ON; - CEC_INFO("%s, suspend:%d\n", __func__, cec_dev->cec_suspend); + CEC_ERR("%s, suspend sts:%d\n", __func__, cec_dev->cec_suspend); } #endif @@ -3702,25 +3785,29 @@ static int aml_cec_probe(struct platform_device *pdev) /* request two int source */ CEC_ERR("request_irq two irq src\n"); r = request_irq(cec_dev->irq_ceca, &ceca_isr, - IRQF_SHARED, irq_name_a, (void *)cec_dev); + IRQF_SHARED | IRQF_NO_SUSPEND, irq_name_a, + (void *)cec_dev); if (r < 0) CEC_INFO("aocec irq request fail\n"); r = request_irq(cec_dev->irq_cecb, &cecb_isr, - IRQF_SHARED, irq_name_b, (void *)cec_dev); + IRQF_SHARED | IRQF_NO_SUSPEND, irq_name_b, + (void *)cec_dev); if (r < 0) CEC_INFO("cecb irq request fail\n"); } else { if (!r && (ee_cec == CEC_A)) { r = request_irq(cec_dev->irq_ceca, &ceca_isr, - IRQF_SHARED, irq_name_a, (void *)cec_dev); + IRQF_SHARED | IRQF_NO_SUSPEND, irq_name_a, + (void *)cec_dev); if (r < 0) CEC_INFO("aocec irq request fail\n"); } if (!r && (ee_cec == CEC_B)) { r = request_irq(cec_dev->irq_cecb, &cecb_isr, - IRQF_SHARED, irq_name_b, (void *)cec_dev); + IRQF_SHARED | IRQF_NO_SUSPEND, irq_name_b, + (void *)cec_dev); if (r < 0) CEC_INFO("cecb irq request fail\n"); } @@ -3751,6 +3838,19 @@ static int aml_cec_probe(struct platform_device *pdev) ret = -EFAULT; goto tag_cec_threat_err; } + /*freeze wakeup init*/ + device_init_wakeup(&pdev->dev, 1); + CEC_INFO("dev init wakeup\n"); + if (cec_dev->cec_num > ENABLE_ONE_CEC) { + dev_pm_set_wake_irq(&pdev->dev, cec_dev->irq_ceca); + dev_pm_set_wake_irq(&pdev->dev, cec_dev->irq_cecb); + } else { + if (ee_cec == CEC_A) + dev_pm_set_wake_irq(&pdev->dev, cec_dev->irq_ceca); + else + dev_pm_set_wake_irq(&pdev->dev, cec_dev->irq_cecb); + } + INIT_DELAYED_WORK(&cec_dev->cec_work, cec_task); queue_delayed_work(cec_dev->cec_thread, &cec_dev->cec_work, 0); tasklet_init(&ceca_tasklet, ceca_tasklet_pro, @@ -3824,7 +3924,7 @@ static int aml_cec_remove(struct platform_device *pdev) static int aml_cec_pm_prepare(struct device *dev) { //cec_dev->cec_suspend = CEC_DEEP_SUSPEND; - CEC_INFO("%s\n", __func__); + CEC_ERR("%s\n", __func__); return 0; } @@ -3837,7 +3937,7 @@ static void aml_cec_pm_complete(struct device *dev) CEC_ERR("clr wakeup reason fail\n"); } - CEC_INFO("%s\n", __func__); + CEC_ERR("%s\n", __func__); } static int aml_cec_suspend_noirq(struct device *dev) @@ -3847,17 +3947,20 @@ static int aml_cec_suspend_noirq(struct device *dev) cec_dev->cec_info.power_status = CEC_PW_TRANS_ON_TO_STANDBY; cec_dev->cec_suspend = CEC_PW_TRANS_ON_TO_STANDBY; - CEC_INFO("cec suspend noirq\n"); - if (cec_dev->cec_num > ENABLE_ONE_CEC) - cec_clear_all_logical_addr(CEC_B); - else - cec_clear_all_logical_addr(ee_cec); - - if (!IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) - ret = pinctrl_pm_select_sleep_state(cec_dev->dbg_dev); - else - CEC_ERR("pinctrl sleep_state error\n"); + if (is_pm_freeze_mode()) { + CEC_ERR("%s:freeze mode\n", __func__); + cec_restore_pre_setting(); + } else { + if (cec_dev->cec_num > ENABLE_ONE_CEC) + cec_clear_all_logical_addr(CEC_B); + else + cec_clear_all_logical_addr(ee_cec); + if (!IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) + ret = pinctrl_pm_select_sleep_state(cec_dev->dbg_dev); + else + CEC_ERR("pinctrl sleep_state error\n"); + } cec_dev->cec_info.power_status = CEC_PW_STANDBY; cec_dev->cec_suspend = CEC_PW_STANDBY; return 0; @@ -3868,20 +3971,25 @@ static int aml_cec_resume_noirq(struct device *dev) int ret = 0; unsigned int temp; - CEC_INFO("cec resume noirq!\n"); + CEC_ERR("cec resume noirq!\n"); cec_dev->cec_info.power_status = CEC_PW_TRANS_STANDBY_TO_ON; cec_dev->cec_suspend = CEC_PW_TRANS_STANDBY_TO_ON; - - scpi_get_wakeup_reason(&cec_dev->wakeup_reason); - CEC_ERR("wakeup_reason:0x%x\n", cec_dev->wakeup_reason); - - scpi_get_cec_val(SCPI_CMD_GET_CEC1, - (unsigned int *)&cec_dev->wakup_data); - scpi_get_cec_val(SCPI_CMD_GET_CEC2, &temp); - CEC_ERR("cev val1: %#x;val2: %#x\n", - *((unsigned int *)&cec_dev->wakup_data), - temp); + if (!is_pm_freeze_mode()) { + scpi_get_wakeup_reason(&cec_dev->wakeup_reason); + CEC_ERR("wakeup_reason:0x%x\n", cec_dev->wakeup_reason); + + scpi_get_cec_val(SCPI_CMD_GET_CEC1, + (unsigned int *)&cec_dev->wakup_data); + CEC_ERR("cev val1:0x%x,0x%x,0x%x\n", + cec_dev->wakup_data.wk_logic_addr, + cec_dev->wakup_data.wk_phy_addr, + cec_dev->wakup_data.wk_port_id); + scpi_get_cec_val(SCPI_CMD_GET_CEC2, &temp); + CEC_ERR("cev val2: 0x%#x\n", temp); + } else { + CEC_ERR("freeze mode\n"); + } cec_pre_init(); if (!IS_ERR(cec_dev->dbg_dev->pins->default_state)) ret = pinctrl_pm_select_default_state(cec_dev->dbg_dev); diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 0a4f6b9..e297fb9 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/10/11: Fix coverity error\n" +#define CEC_DRIVER_VERSION "2019/10/11:add freeze mode wake up func-1\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "cec" @@ -577,5 +577,6 @@ extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); extern void cec_clear_all_logical_addr(unsigned int cec_sel); extern int dump_cecrx_reg(char *b); extern void cec_ip_share_io(u32 share, u32 cec_ip); +void cec_freeze_mode_process(void); #endif /* __AO_CEC_H__ */ diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h index 0c218f6..f09515a 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h @@ -100,6 +100,8 @@ enum _cec_log_dev_addr_e { #define CEC_IOC_SET_AUTO_DEVICE_OFF _IOW(CEC_IOC_MAGIC, 0x0F, uint32_t) #define CEC_IOC_GET_BOOT_ADDR _IOW(CEC_IOC_MAGIC, 0x10, uint32_t) #define CEC_IOC_GET_BOOT_REASON _IOW(CEC_IOC_MAGIC, 0x11, uint32_t) +#define CEC_IOC_SET_FREEZE_MODE _IOW(CEC_IOC_MAGIC, 0x12, uint32_t) + #define CEC_FAIL_NONE 0 #define CEC_FAIL_NACK 1 -- 2.7.4