Loading drivers/video/msm/mdss/mdss_hdmi_tx.c +82 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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__); Loading @@ -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); Loading drivers/video/msm/mdss/mdss_hdmi_tx.h +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading include/linux/msm_hdmi.h 0 → 100644 +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_*/ Loading
drivers/video/msm/mdss/mdss_hdmi_tx.c +82 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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__); Loading @@ -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); Loading
drivers/video/msm/mdss/mdss_hdmi_tx.h +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading
include/linux/msm_hdmi.h 0 → 100644 +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_*/