summaryrefslogtreecommitdiff
authorYong Qin <yong.qin@amlogic.com>2019-09-28 02:54:01 (GMT)
committer zihuan.ling <zihuan.ling@amlogic.com>2019-10-15 07:04:30 (GMT)
commiteb73259276d4a34de89388b2f97e4b55d0985729 (patch)
treeb80d38fa3197dcf07e82fb9503658d0d0a45e090
parent380e19a9997e9f4136ff7ead777c3700e6ea7406 (diff)
downloadcommon-eb73259276d4a34de89388b2f97e4b55d0985729.zip
common-eb73259276d4a34de89388b2f97e4b55d0985729.tar.gz
common-eb73259276d4a34de89388b2f97e4b55d0985729.tar.bz2
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 <yong.qin@amlogic.com>
Diffstat
-rw-r--r--drivers/amlogic/cec/hdmi_ao_cec.c172
-rw-r--r--drivers/amlogic/cec/hdmi_ao_cec.h3
-rw-r--r--include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h2
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 <linux/notifier.h>
#include <linux/random.h>
#include <linux/pinctrl/consumer.h>
-
+#include <linux/pm_wakeup.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/pm.h>
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h>
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
@@ -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