summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_cec_core.c40
-rw-r--r--drivers/video/fbdev/msm/mdss_cec_core.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_cec.c22
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;