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

Commit f3c754f0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: hdmi: add support for CEC suspend and resume events"

parents 5a8284c9 8ef980d2
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -464,7 +464,9 @@ extern struct mdss_data_type *mdss_res;
struct irq_info {
	u32 irq;
	u32 irq_mask;
	u32 irq_wake_mask;
	u32 irq_ena;
	u32 irq_wake_ena;
	u32 irq_buzy;
};

@@ -488,6 +490,8 @@ struct mdss_util_intf {
	int (*register_irq)(struct mdss_hw *hw);
	void (*enable_irq)(struct mdss_hw *hw);
	void (*disable_irq)(struct mdss_hw *hw);
	void (*enable_wake_irq)(struct mdss_hw *hw);
	void (*disable_wake_irq)(struct mdss_hw *hw);
	void (*disable_irq_nosync)(struct mdss_hw *hw);
	int (*irq_dispatch)(u32 hw_ndx, int irq, void *ptr);
	int (*get_iommu_domain)(u32 type);
+2 −5
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, 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
@@ -445,10 +445,7 @@ static ssize_t cec_wta_enable(struct device *dev,
		ctl->cec_wakeup_en = false;

	if (ops && ops->wakeup_en)
		ret = ops->wakeup_en(ops->data, ctl->cec_wakeup_en);

	if (ret)
		goto end;
		ops->wakeup_en(ops->data, ctl->cec_wakeup_en);

	if (ctl->enabled == cec_en) {
		pr_debug("cec is already %s\n",
+7 −3
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, 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
@@ -54,7 +54,9 @@ struct cec_msg {
 * @enable: function pointer to enable CEC
 * @send_msg: function pointer to send CEC message
 * @wt_logical_addr: function pointer to write logical address
 * @wakeup_en: function pointer to enable wakup feature
 * @wakeup_en: function pointer to enable wakeup feature
 * @is_wakeup_en: function pointer to query wakeup feature state
 * @device_suspend: function pointer to update device suspend state
 * @data: pointer to the data needed to send with operation functions
 *
 * Defines all the operations that abstract module can call
@@ -65,7 +67,9 @@ struct cec_ops {
	int (*send_msg)(void *data,
		struct cec_msg *msg);
	void (*wt_logical_addr)(void *data, u8 addr);
	int (*wakeup_en)(void *data, bool en);
	void (*wakeup_en)(void *data, bool en);
	bool (*is_wakeup_en)(void *data);
	void (*device_suspend)(void *data, bool suspend);
	void *data;
};

+118 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2016, 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
@@ -16,6 +16,7 @@
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/input.h>

#include "mdss_hdmi_cec.h"
#include "mdss_panel.h"
@@ -28,14 +29,21 @@

/* Reference: HDMI 1.4a Specification section 7.1 */

#define CEC_OP_SET_STREAM_PATH  0x86
#define CEC_OP_KEY_PRESS        0x44
#define CEC_OP_STANDBY          0x36

struct hdmi_cec_ctrl {
	bool cec_enabled;
	bool cec_wakeup_en;
	bool cec_device_suspend;

	u32 cec_msg_wr_status;
	spinlock_t lock;
	struct work_struct cec_read_work;
	struct completion cec_msg_wr_done;
	struct hdmi_cec_init_data init_data;
	struct input_dev *input;
};

static int hdmi_cec_msg_send(void *data, struct cec_msg *msg)
@@ -116,6 +124,46 @@ static int hdmi_cec_msg_send(void *data, struct cec_msg *msg)
	return rc;
} /* hdmi_cec_msg_send */

static void hdmi_cec_init_input_event(struct hdmi_cec_ctrl *cec_ctrl)
{
	int rc = 0;

	if (!cec_ctrl) {
		DEV_ERR("%s: Invalid input\n", __func__);
		return;
	}

	/* Initialize CEC input events */
	if (!cec_ctrl->input)
		cec_ctrl->input = input_allocate_device();
	if (!cec_ctrl->input) {
		DEV_ERR("%s: hdmi input device allocation failed\n", __func__);
		return;
	}

	cec_ctrl->input->name = "HDMI CEC User or Deck Control";
	cec_ctrl->input->phys = "hdmi/input0";
	cec_ctrl->input->id.bustype = BUS_VIRTUAL;

	input_set_capability(cec_ctrl->input, EV_KEY, KEY_POWER);

	rc = input_register_device(cec_ctrl->input);
	if (rc) {
		DEV_ERR("%s: cec input device registeration failed\n",
				__func__);
		input_free_device(cec_ctrl->input);
		cec_ctrl->input = NULL;
		return;
	}
}

static void hdmi_cec_deinit_input_event(struct hdmi_cec_ctrl *cec_ctrl)
{
	if (cec_ctrl->input)
		input_unregister_device(cec_ctrl->input);
	cec_ctrl->input = NULL;
}

static void hdmi_cec_msg_recv(struct work_struct *work)
{
	int i;
@@ -171,6 +219,31 @@ static void hdmi_cec_msg_recv(struct work_struct *work)
	for (; i < 14; i++)
		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,
		cec_ctrl->cec_device_suspend);

	if ((msg.opcode == CEC_OP_SET_STREAM_PATH ||
		msg.opcode == CEC_OP_KEY_PRESS) &&
		cec_ctrl->input && cec_ctrl->cec_wakeup_en &&
		cec_ctrl->cec_device_suspend) {
		DEV_DBG("%s: Sending power on at wakeup\n", __func__);
		input_report_key(cec_ctrl->input, KEY_POWER, 1);
		input_sync(cec_ctrl->input);
		input_report_key(cec_ctrl->input, KEY_POWER, 0);
		input_sync(cec_ctrl->input);
	}

	if ((msg.opcode == CEC_OP_STANDBY) &&
		cec_ctrl->input && cec_ctrl->cec_wakeup_en &&
		!cec_ctrl->cec_device_suspend) {
		DEV_DBG("%s: Sending power off on standby\n", __func__);
		input_report_key(cec_ctrl->input, KEY_POWER, 1);
		input_sync(cec_ctrl->input);
		input_report_key(cec_ctrl->input, KEY_POWER, 0);
		input_sync(cec_ctrl->input);
	}

	if (cbs && cbs->msg_recv_notify)
		cbs->msg_recv_notify(cbs->data, &msg);
}
@@ -242,6 +315,42 @@ int hdmi_cec_isr(void *input)
	return rc;
}

void hdmi_cec_device_suspend(void *input, bool suspend)
{
	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;

	if (!cec_ctrl) {
		DEV_WARN("%s: HDMI CEC HW module not initialized.\n", __func__);
		return;
	}

	cec_ctrl->cec_device_suspend = suspend;
}

bool hdmi_cec_is_wakeup_en(void *input)
{
	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;

	if (!cec_ctrl) {
		DEV_WARN("%s: HDMI CEC HW module not initialized.\n", __func__);
		return 0;
	}

	return cec_ctrl->cec_wakeup_en;
}

static void hdmi_cec_wakeup_en(void *input, bool enable)
{
	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;

	if (!cec_ctrl) {
		DEV_ERR("%s: Invalid input\n", __func__);
		return;
	}

	cec_ctrl->cec_wakeup_en = enable;
}

static void hdmi_cec_write_logical_addr(void *input, u8 addr)
{
	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input;
@@ -367,6 +476,11 @@ void *hdmi_cec_init(struct hdmi_cec_init_data *init_data)
	ops->wt_logical_addr = hdmi_cec_write_logical_addr;
	ops->enable = hdmi_cec_enable;
	ops->data = cec_ctrl;
	ops->wakeup_en = hdmi_cec_wakeup_en;
	ops->is_wakeup_en = hdmi_cec_is_wakeup_en;
	ops->device_suspend = hdmi_cec_device_suspend;

	hdmi_cec_init_input_event(cec_ctrl);

	return cec_ctrl;
error:
@@ -383,5 +497,8 @@ void hdmi_cec_deinit(void *data)
{
	struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)data;

	if (cec_ctrl)
		hdmi_cec_deinit_input_event(cec_ctrl);

	kfree(cec_ctrl);
}
+22 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2013, 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2013, 2015-2016, 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
@@ -66,4 +66,25 @@ void *hdmi_cec_init(struct hdmi_cec_init_data *init_data);
 * This API release all resources allocated.
 */
void hdmi_cec_deinit(void *data);

/**
 * hdmi_cec_is_wakeup_en() - checks cec wakeup state
 * @cec_ctrl: pointer to cec hw module's data
 *
 * Return: cec wakeup state
 *
 * This API is used to query whether the cec wakeup functionality is
 * enabled or not.
 */
bool hdmi_cec_is_wakeup_en(void *cec_ctrl);

/**
 * hdmi_cec_device_suspend() - updates cec with device suspend state
 * @cec_ctrl: pointer to cec hw module's data
 * @suspend: device suspend state
 *
 * This API is used to update the CEC HW module of the device's suspend
 * state.
 */
void hdmi_cec_device_suspend(void *cec_ctrl, bool suspend);
#endif /* __MDSS_HDMI_CEC_H__ */
Loading