summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkata Prahlad Valluru <vvalluru@codeaurora.org>2019-12-13 19:40:53 +0530
committerVenkata Prahlad Valluru <vvalluru@codeaurora.org>2020-03-06 16:22:55 +0530
commit1233c7c4b0c141ae19a2bd98b01cc389d4a149f5 (patch)
treee0f8f3a9a8be865aed1d0114082d2542564872c5
parent9346632ccfe6946cf77b869403dbf65dcd6a24de (diff)
fbdev: msm: hdmi: read CEC msg before clearing interrupt
Read CEC msg in ISR itself and then trigger work queue. Change-Id: Ib40e544849e3b3338a412b9fa5ba737bfc13dad9 Signed-off-by: Venkata Prahlad Valluru <vvalluru@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_cec.c77
1 files changed, 46 insertions, 31 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_cec.c b/drivers/video/fbdev/msm/mdss_hdmi_cec.c
index a4ed01210e04..4efacfa86032 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_cec.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_cec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -39,6 +39,7 @@ struct hdmi_cec_ctrl {
bool cec_device_suspend;
u32 cec_msg_wr_status;
+ struct cec_msg recv_msg;
spinlock_t lock;
struct work_struct cec_read_work;
struct completion cec_msg_wr_done;
@@ -164,65 +165,75 @@ static void hdmi_cec_deinit_input_event(struct hdmi_cec_ctrl *cec_ctrl)
cec_ctrl->input = NULL;
}
-static void hdmi_cec_msg_recv(struct work_struct *work)
+static int hdmi_cec_msg_read(struct hdmi_cec_ctrl *cec_ctrl)
{
- int i;
- u32 data;
- struct hdmi_cec_ctrl *cec_ctrl = NULL;
struct dss_io_data *io = NULL;
- struct cec_msg msg;
- struct cec_cbs *cbs;
+ struct cec_msg *msg;
+ u32 data;
+ int i;
- cec_ctrl = container_of(work, struct hdmi_cec_ctrl, cec_read_work);
if (!cec_ctrl || !cec_ctrl->init_data.io) {
DEV_ERR("%s: invalid input\n", __func__);
- return;
+ return -EINVAL;
}
if (!cec_ctrl->cec_enabled) {
DEV_ERR("%s: cec not enabled\n", __func__);
- return;
+ return -ENODEV;
}
+ msg = &cec_ctrl->recv_msg;
io = cec_ctrl->init_data.io;
- cbs = cec_ctrl->init_data.cbs;
-
data = DSS_REG_R(io, HDMI_CEC_RD_DATA);
- msg.recvr_id = (data & 0x000F);
- msg.sender_id = (data & 0x00F0) >> 4;
- msg.frame_size = (data & 0x1F00) >> 8;
- DEV_DBG("%s: Recvd init=[%u] dest=[%u] size=[%u]\n", __func__,
- msg.sender_id, msg.recvr_id,
- msg.frame_size);
-
- if (msg.frame_size < 1 || msg.frame_size > MAX_CEC_FRAME_SIZE) {
+ msg->recvr_id = (data & 0x000F);
+ msg->sender_id = (data & 0x00F0) >> 4;
+ msg->frame_size = (data & 0x1F00) >> 8;
+ if (msg->frame_size < 1 || msg->frame_size > MAX_CEC_FRAME_SIZE) {
DEV_ERR("%s: invalid message (frame length = %d)\n",
- __func__, msg.frame_size);
- return;
- } else if (msg.frame_size == 1) {
+ __func__, msg->frame_size);
+ return -EINVAL;
+ } else if (msg->frame_size == 1) {
DEV_DBG("%s: polling message (dest[%x] <- init[%x])\n",
- __func__, msg.recvr_id, msg.sender_id);
- return;
+ __func__, msg->recvr_id, msg->sender_id);
+ return -EINVAL;
}
/* data block 0 : opcode */
data = DSS_REG_R_ND(io, HDMI_CEC_RD_DATA);
- msg.opcode = data & 0xFF;
+ msg->opcode = data & 0xFF;
/* data block 1-14 : operand 0-13 */
- for (i = 0; i < msg.frame_size - 2; i++) {
+ for (i = 0; i < msg->frame_size - 2; i++) {
data = DSS_REG_R_ND(io, HDMI_CEC_RD_DATA);
- msg.operand[i] = data & 0xFF;
+ msg->operand[i] = data & 0xFF;
}
for (; i < MAX_OPERAND_SIZE; i++)
- msg.operand[i] = 0;
+ msg->operand[i] = 0;
DEV_DBG("%s: opcode 0x%x, wakup_en %d, device_suspend %d\n", __func__,
- msg.opcode, cec_ctrl->cec_wakeup_en,
+ msg->opcode, cec_ctrl->cec_wakeup_en,
cec_ctrl->cec_device_suspend);
+ return 0;
+}
+
+static void hdmi_cec_msg_recv(struct work_struct *work)
+{
+ struct hdmi_cec_ctrl *cec_ctrl = NULL;
+ struct cec_msg msg;
+ struct cec_cbs *cbs;
+
+ cec_ctrl = container_of(work, struct hdmi_cec_ctrl, cec_read_work);
+ if (!cec_ctrl || !cec_ctrl->init_data.io) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ cbs = cec_ctrl->init_data.cbs;
+ memcpy(&msg, &cec_ctrl->recv_msg, sizeof(msg));
+
if ((msg.opcode == CEC_OP_SET_STREAM_PATH ||
msg.opcode == CEC_OP_KEY_PRESS) &&
cec_ctrl->input && cec_ctrl->cec_wakeup_en &&
@@ -308,8 +319,12 @@ int hdmi_cec_isr(void *input)
if ((cec_intr & BIT(6)) && (cec_intr & BIT(7))) {
DEV_DBG("%s: CEC_IRQ_FRAME_RD_DONE\n", __func__);
+ rc = hdmi_cec_msg_read(cec_ctrl);
+ if (!rc)
+ queue_work(cec_ctrl->init_data.workq,
+ &cec_ctrl->cec_read_work);
+
DSS_REG_W(io, HDMI_CEC_INT, cec_intr | BIT(6));
- queue_work(cec_ctrl->init_data.workq, &cec_ctrl->cec_read_work);
}
return rc;