Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80774a56 authored by Venkata Prahlad Valluru's avatar Venkata Prahlad Valluru
Browse files

mdss: msm: hdmi: add CEC clear_logical_addr sysnode



When the logical address is cleared, CEC hal sets the logical
address to 15 but kernel cannot determine whether the logical
address is cleared or set to 15. To clearly detect that the
logical address is cleared, a new sysnode
"clear_logical_addr" is added.

If clear_logical_addr is set to 1, then kernel ignores
received CEC messages until it's reset to 0.

Change-Id: I517a3054c0816e774836767f3e0e47f92b395666
Signed-off-by: default avatarVenkata Prahlad Valluru <vvalluru@codeaurora.org>
parent 1233c7c4
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
/* 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,
+2 −1
Original line number Diff line number Diff line
/* 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);
+22 −0
Original line number Diff line number Diff line
@@ -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;