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

Commit e8838e5e 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: Cable connection status notification"

parents 462d8f03 9bef5e65
Loading
Loading
Loading
Loading
+82 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/types.h>
#include <linux/msm_hdmi.h>
#include <mach/msm_hdmi_audio_codec.h>

#define REG_DUMP 0
@@ -231,6 +232,77 @@ static const struct hdmi_tx_audio_acr_arry hdmi_tx_audio_acr_lut[] = {
		{20480, 247500} } },
};

int register_hdmi_cable_notification(struct hdmi_cable_notify *handler)
{
	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
	struct list_head *pos;

	if (!hdmi_tx_hw.ptr) {
		DEV_WARN("%s: HDMI Tx core not ready\n", __func__);
		return -EPROBE_DEFER;
	}

	if (!handler) {
		DEV_ERR("%s: Empty handler\n", __func__);
		return -ENODEV;
	}

	hdmi_ctrl = (struct hdmi_tx_ctrl *) hdmi_tx_hw.ptr;

	mutex_lock(&hdmi_ctrl->cable_notify_mutex);
	handler->status = hdmi_ctrl->hpd_state;
	list_for_each(pos, &hdmi_ctrl->cable_notify_handlers);
	list_add_tail(&handler->link, pos);
	mutex_unlock(&hdmi_ctrl->cable_notify_mutex);

	return handler->status;
} /* register_hdmi_cable_notification */

int unregister_hdmi_cable_notification(struct hdmi_cable_notify *handler)
{
	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;

	if (!hdmi_tx_hw.ptr) {
		DEV_WARN("%s: HDMI Tx core not ready\n", __func__);
		return -ENODEV;
	}

	if (!handler) {
		DEV_ERR("%s: Empty handler\n", __func__);
		return -ENODEV;
	}

	hdmi_ctrl = (struct hdmi_tx_ctrl *) hdmi_tx_hw.ptr;

	mutex_lock(&hdmi_ctrl->cable_notify_mutex);
	list_del(&handler->link);
	mutex_unlock(&hdmi_ctrl->cable_notify_mutex);

	return 0;
} /* unregister_hdmi_cable_notification */

static void hdmi_tx_cable_notify_work(struct work_struct *work)
{
	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
	struct hdmi_cable_notify *pos;

	hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, cable_notify_work);

	if (!hdmi_ctrl) {
		DEV_ERR("%s: invalid hdmi data\n", __func__);
		return;
	}

	mutex_lock(&hdmi_ctrl->cable_notify_mutex);
	list_for_each_entry(pos, &hdmi_ctrl->cable_notify_handlers, link) {
		if (pos->status != hdmi_ctrl->hpd_state) {
			pos->status = hdmi_ctrl->hpd_state;
			pos->hpd_notify(pos);
		}
	}
	mutex_unlock(&hdmi_ctrl->cable_notify_mutex);
} /* hdmi_tx_cable_notify_work */

static bool hdmi_tx_is_cea_format(int mode)
{
	bool cea_fmt;
@@ -336,6 +408,9 @@ static inline void hdmi_tx_send_cable_notification(

	if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
		switch_set_state(&hdmi_ctrl->sdev, val);

	/* Notify all registered modules of cable connection status */
	schedule_work(&hdmi_ctrl->cable_notify_work);
} /* hdmi_tx_send_cable_notification */

static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -2926,6 +3001,7 @@ static void hdmi_tx_dev_deinit(struct hdmi_tx_ctrl *hdmi_ctrl)
	if (hdmi_ctrl->workq)
		destroy_workqueue(hdmi_ctrl->workq);
	mutex_destroy(&hdmi_ctrl->lut_lock);
	mutex_destroy(&hdmi_ctrl->cable_notify_mutex);
	mutex_destroy(&hdmi_ctrl->mutex);

	hdmi_tx_hw.ptr = NULL;
@@ -2955,6 +3031,10 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)
	hdmi_setup_video_mode_lut();
	mutex_init(&hdmi_ctrl->mutex);
	mutex_init(&hdmi_ctrl->lut_lock);
	mutex_init(&hdmi_ctrl->cable_notify_mutex);

	INIT_LIST_HEAD(&hdmi_ctrl->cable_notify_handlers);

	hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
	if (!hdmi_ctrl->workq) {
		DEV_ERR("%s: hdmi_tx_workq creation failed.\n", __func__);
@@ -2972,8 +3052,9 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)
	hdmi_ctrl->hpd_initialized = false;
	hdmi_ctrl->hpd_off_pending = false;
	init_completion(&hdmi_ctrl->hpd_done);
	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);

	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
	INIT_WORK(&hdmi_ctrl->cable_notify_work, hdmi_tx_cable_notify_work);
	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);

	spin_lock_init(&hdmi_ctrl->hpd_state_lock);
+3 −0
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ struct hdmi_tx_ctrl {

	struct mutex mutex;
	struct mutex lut_lock;
	struct mutex cable_notify_mutex;
	struct list_head cable_notify_handlers;
	struct kobject *kobj;
	struct switch_dev sdev;
	struct switch_dev audio_sdev;
@@ -79,6 +81,7 @@ struct hdmi_tx_ctrl {
	struct work_struct hpd_int_work;

	struct work_struct power_off_work;
	struct work_struct cable_notify_work;

	bool hdcp_feature_on;
	bool hpd_disabled;
+57 −0
Original line number Diff line number Diff line
/* include/linux/msm_hdmi.h
 *
 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
#ifndef _MSM_HDMI_H_
#define _MSM_HDMI_H_

/*
 * HDMI cable notify handler sturcture.
 * link A link for the linked list
 * status Current status of HDMI cable connection
 * hpd_notify Callback function to provide cable status
 */
struct hdmi_cable_notify {
	struct list_head link;
	int status;
	void (*hpd_notify) (struct hdmi_cable_notify *h);
};

#ifdef CONFIG_FB_MSM_MDSS_HDMI_PANEL
/*
 * Register for HDMI cable connect or disconnect notification.
 * @param handler callback handler for notification
 * @return negative value as error otherwise current status of cable
 */
int register_hdmi_cable_notification(
		struct hdmi_cable_notify *handler);

/*
 * Un-register for HDMI cable connect or disconnect notification.
 * @param handler callback handler for notification
 * @return negative value as error
 */
int unregister_hdmi_cable_notification(
		struct hdmi_cable_notify *handler);
#else
int register_hdmi_cable_notification(
		struct hdmi_cable_notify *handler) {
	return 0;
}

int unregister_hdmi_cable_notification(
		struct hdmi_cable_notify *handler) {
	return 0;
}
#endif /* CONFIG_FB_MSM_MDSS_HDMI_PANEL */

#endif /*_MSM_HDMI_H_*/