diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_cec_core.c | 40 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_cec_core.h | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_cec.c | 22 |
3 files changed, 63 insertions, 2 deletions
diff --git a/drivers/video/fbdev/msm/mdss_cec_core.c b/drivers/video/fbdev/msm/mdss_cec_core.c index 1d9950494d65..ab7a8056016a 100644 --- a/drivers/video/fbdev/msm/mdss_cec_core.c +++ b/drivers/video/fbdev/msm/mdss_cec_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -594,6 +594,41 @@ end: return ret; } +static ssize_t cec_wta_clear_logical_addr(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int clear_flag; + unsigned long flags; + ssize_t ret; + struct cec_ctl *ctl = cec_get_ctl(dev); + struct cec_ops *ops; + + if (!ctl) { + pr_err("Invalid ctl\n"); + ret = -EINVAL; + goto end; + } + + ops = ctl->init_data.ops; + + ret = kstrtoint(buf, 10, &clear_flag); + if (ret) { + pr_err("kstrtoint failed\n"); + goto end; + } + + ret = count; + + spin_lock_irqsave(&ctl->lock, flags); + if (ctl->enabled) { + if (ops && ops->clear_logical_addr) + ops->clear_logical_addr(ops->data, !!clear_flag); + } + spin_unlock_irqrestore(&ctl->lock, flags); +end: + return ret; +} + static ssize_t cec_rda_msg(struct device *dev, struct device_attribute *attr, char *buf) { @@ -703,6 +738,8 @@ static DEVICE_ATTR(enable_compliance, S_IRUGO | S_IWUSR, cec_rda_enable_compliance, cec_wta_enable_compliance); static DEVICE_ATTR(logical_addr, S_IRUSR | S_IWUSR, cec_rda_logical_addr, cec_wta_logical_addr); +static DEVICE_ATTR(clear_logical_addr, 0200, + NULL, cec_wta_clear_logical_addr); static DEVICE_ATTR(rd_msg, S_IRUGO, cec_rda_msg, NULL); static DEVICE_ATTR(wr_msg, S_IWUSR | S_IRUSR, NULL, cec_wta_msg); @@ -710,6 +747,7 @@ static struct attribute *cec_fs_attrs[] = { &dev_attr_enable.attr, &dev_attr_enable_compliance.attr, &dev_attr_logical_addr.attr, + &dev_attr_clear_logical_addr.attr, &dev_attr_rd_msg.attr, &dev_attr_wr_msg.attr, NULL, diff --git a/drivers/video/fbdev/msm/mdss_cec_core.h b/drivers/video/fbdev/msm/mdss_cec_core.h index 12b7677c5dee..481884a732d8 100644 --- a/drivers/video/fbdev/msm/mdss_cec_core.h +++ b/drivers/video/fbdev/msm/mdss_cec_core.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -67,6 +67,7 @@ struct cec_ops { int (*send_msg)(void *data, struct cec_msg *msg); void (*wt_logical_addr)(void *data, u8 addr); + void (*clear_logical_addr)(void *data, bool flag); void (*wakeup_en)(void *data, bool en); bool (*is_wakeup_en)(void *data); void (*device_suspend)(void *data, bool suspend); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_cec.c b/drivers/video/fbdev/msm/mdss_hdmi_cec.c index 4efacfa86032..cafa4e207332 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_cec.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_cec.c @@ -37,6 +37,7 @@ struct hdmi_cec_ctrl { bool cec_enabled; bool cec_wakeup_en; bool cec_device_suspend; + bool cec_clear_logical_addr; u32 cec_msg_wr_status; struct cec_msg recv_msg; @@ -212,6 +213,13 @@ static int hdmi_cec_msg_read(struct hdmi_cec_ctrl *cec_ctrl) for (; i < MAX_OPERAND_SIZE; i++) msg->operand[i] = 0; + /* + * Clearing the logical address is used when the system doesn't + * need to process CEC command any more. + */ + if (cec_ctrl->cec_clear_logical_addr) + return -EINVAL; + DEV_DBG("%s: opcode 0x%x, wakup_en %d, device_suspend %d\n", __func__, msg->opcode, cec_ctrl->cec_wakeup_en, cec_ctrl->cec_device_suspend); @@ -379,6 +387,19 @@ static void hdmi_cec_write_logical_addr(void *input, u8 addr) DSS_REG_W(cec_ctrl->init_data.io, HDMI_CEC_ADDR, addr & 0xF); } +static void hdmi_cec_clear_logical_addr(void *input, bool clear_flag) +{ + struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input; + + if (!cec_ctrl || !cec_ctrl->init_data.io) { + DEV_ERR("%s: Invalid input\n", __func__); + return; + } + + if (cec_ctrl->cec_enabled) + cec_ctrl->cec_clear_logical_addr = clear_flag; +} + static int hdmi_cec_enable(void *input, bool enable) { int ret = 0; @@ -489,6 +510,7 @@ void *hdmi_cec_init(struct hdmi_cec_init_data *init_data) /* populate hardware specific operations to client */ ops->send_msg = hdmi_cec_msg_send; ops->wt_logical_addr = hdmi_cec_write_logical_addr; + ops->clear_logical_addr = hdmi_cec_clear_logical_addr; ops->enable = hdmi_cec_enable; ops->data = cec_ctrl; ops->wakeup_en = hdmi_cec_wakeup_en; |
