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

Commit 9bef5e65 authored by Ajay Singh Parmar's avatar Ajay Singh Parmar
Browse files

msm: mdss: hdmi: Cable connection status notification



Provide a callback machanism to all the modules registered
for HDMI cable notifications. The registered modules will be
notified everytime the cable is connected or disconnected.
The callback will be scheduled on global kernel workqueue.

Change-Id: I74630748448d8479b6e0cda6ccd148cbeae48a51
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent 4ae4d503
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
@@ -223,6 +224,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;
@@ -328,6 +400,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)
@@ -2865,6 +2940,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;
@@ -2894,6 +2970,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__);
@@ -2911,8 +2991,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);
+4 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2014, 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
@@ -55,6 +55,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;
@@ -78,6 +80,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;
	u32 present_hdcp;
+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_*/