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