xref: /linux/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c (revision 8d2b0853add1d7534dc0794e3c8e0b9e8c4ec640)
18b1a8f8bSDmitry Baryshkov // SPDX-License-Identifier: MIT
28b1a8f8bSDmitry Baryshkov /*
38b1a8f8bSDmitry Baryshkov  * Copyright (c) 2024 Linaro Ltd
48b1a8f8bSDmitry Baryshkov  */
58b1a8f8bSDmitry Baryshkov 
68b1a8f8bSDmitry Baryshkov #include <drm/drm_bridge.h>
78b1a8f8bSDmitry Baryshkov #include <drm/drm_connector.h>
88b1a8f8bSDmitry Baryshkov #include <drm/drm_managed.h>
98b1a8f8bSDmitry Baryshkov #include <drm/display/drm_hdmi_cec_helper.h>
108b1a8f8bSDmitry Baryshkov 
11*8f194494SThomas Zimmermann #include <linux/export.h>
128b1a8f8bSDmitry Baryshkov #include <linux/mutex.h>
138b1a8f8bSDmitry Baryshkov 
148b1a8f8bSDmitry Baryshkov #include <media/cec.h>
158b1a8f8bSDmitry Baryshkov #include <media/cec-notifier.h>
168b1a8f8bSDmitry Baryshkov 
178b1a8f8bSDmitry Baryshkov static void drm_connector_hdmi_cec_notifier_phys_addr_invalidate(struct drm_connector *connector)
188b1a8f8bSDmitry Baryshkov {
198b1a8f8bSDmitry Baryshkov 	cec_notifier_phys_addr_invalidate(connector->cec.data);
208b1a8f8bSDmitry Baryshkov }
218b1a8f8bSDmitry Baryshkov 
228b1a8f8bSDmitry Baryshkov static void drm_connector_hdmi_cec_notifier_phys_addr_set(struct drm_connector *connector,
238b1a8f8bSDmitry Baryshkov 							  u16 addr)
248b1a8f8bSDmitry Baryshkov {
258b1a8f8bSDmitry Baryshkov 	cec_notifier_set_phys_addr(connector->cec.data, addr);
268b1a8f8bSDmitry Baryshkov }
278b1a8f8bSDmitry Baryshkov 
288b1a8f8bSDmitry Baryshkov static void drm_connector_hdmi_cec_notifier_unregister(struct drm_device *dev, void *res)
298b1a8f8bSDmitry Baryshkov {
308b1a8f8bSDmitry Baryshkov 	struct drm_connector *connector = res;
318b1a8f8bSDmitry Baryshkov 
328b1a8f8bSDmitry Baryshkov 	cec_notifier_conn_unregister(connector->cec.data);
338b1a8f8bSDmitry Baryshkov 	connector->cec.data = NULL;
348b1a8f8bSDmitry Baryshkov }
358b1a8f8bSDmitry Baryshkov 
368b1a8f8bSDmitry Baryshkov static const struct drm_connector_cec_funcs drm_connector_cec_notifier_funcs = {
378b1a8f8bSDmitry Baryshkov 	.phys_addr_invalidate = drm_connector_hdmi_cec_notifier_phys_addr_invalidate,
388b1a8f8bSDmitry Baryshkov 	.phys_addr_set = drm_connector_hdmi_cec_notifier_phys_addr_set,
398b1a8f8bSDmitry Baryshkov };
408b1a8f8bSDmitry Baryshkov 
418b1a8f8bSDmitry Baryshkov int drmm_connector_hdmi_cec_notifier_register(struct drm_connector *connector,
428b1a8f8bSDmitry Baryshkov 					      const char *port_name,
438b1a8f8bSDmitry Baryshkov 					      struct device *dev)
448b1a8f8bSDmitry Baryshkov {
458b1a8f8bSDmitry Baryshkov 	struct cec_connector_info conn_info;
468b1a8f8bSDmitry Baryshkov 	struct cec_notifier *notifier;
478b1a8f8bSDmitry Baryshkov 
488b1a8f8bSDmitry Baryshkov 	cec_fill_conn_info_from_drm(&conn_info, connector);
498b1a8f8bSDmitry Baryshkov 
508b1a8f8bSDmitry Baryshkov 	notifier = cec_notifier_conn_register(dev, port_name, &conn_info);
518b1a8f8bSDmitry Baryshkov 	if (!notifier)
528b1a8f8bSDmitry Baryshkov 		return -ENOMEM;
538b1a8f8bSDmitry Baryshkov 
548b1a8f8bSDmitry Baryshkov 	mutex_lock(&connector->cec.mutex);
558b1a8f8bSDmitry Baryshkov 
568b1a8f8bSDmitry Baryshkov 	connector->cec.data = notifier;
578b1a8f8bSDmitry Baryshkov 	connector->cec.funcs = &drm_connector_cec_notifier_funcs;
588b1a8f8bSDmitry Baryshkov 
598b1a8f8bSDmitry Baryshkov 	mutex_unlock(&connector->cec.mutex);
608b1a8f8bSDmitry Baryshkov 
618b1a8f8bSDmitry Baryshkov 	return drmm_add_action_or_reset(connector->dev,
628b1a8f8bSDmitry Baryshkov 					drm_connector_hdmi_cec_notifier_unregister,
638b1a8f8bSDmitry Baryshkov 					connector);
648b1a8f8bSDmitry Baryshkov }
658b1a8f8bSDmitry Baryshkov EXPORT_SYMBOL(drmm_connector_hdmi_cec_notifier_register);
66