12c9916cdSFrançois Tigeot /*
22c9916cdSFrançois Tigeot * Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
32c9916cdSFrançois Tigeot *
42c9916cdSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
52c9916cdSFrançois Tigeot * copy of this software and associated documentation files (the "Software"),
62c9916cdSFrançois Tigeot * to deal in the Software without restriction, including without limitation
72c9916cdSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sub license,
82c9916cdSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the
92c9916cdSFrançois Tigeot * Software is furnished to do so, subject to the following conditions:
102c9916cdSFrançois Tigeot *
112c9916cdSFrançois Tigeot * The above copyright notice and this permission notice (including the
122c9916cdSFrançois Tigeot * next paragraph) shall be included in all copies or substantial portions
132c9916cdSFrançois Tigeot * of the Software.
142c9916cdSFrançois Tigeot *
152c9916cdSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
162c9916cdSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
172c9916cdSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
182c9916cdSFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
192c9916cdSFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
202c9916cdSFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
212c9916cdSFrançois Tigeot * DEALINGS IN THE SOFTWARE.
222c9916cdSFrançois Tigeot */
232c9916cdSFrançois Tigeot
242c9916cdSFrançois Tigeot #include <linux/err.h>
252c9916cdSFrançois Tigeot #include <linux/module.h>
262c9916cdSFrançois Tigeot
272c9916cdSFrançois Tigeot #include <drm/drmP.h>
282c9916cdSFrançois Tigeot #include <drm/drm_crtc.h>
292c9916cdSFrançois Tigeot #include <drm/drm_panel.h>
302c9916cdSFrançois Tigeot
312c9916cdSFrançois Tigeot static DEFINE_MUTEX(panel_lock);
322c9916cdSFrançois Tigeot static LINUX_LIST_HEAD(panel_list);
332c9916cdSFrançois Tigeot
348621f407SFrançois Tigeot /**
358621f407SFrançois Tigeot * DOC: drm panel
368621f407SFrançois Tigeot *
378621f407SFrançois Tigeot * The DRM panel helpers allow drivers to register panel objects with a
388621f407SFrançois Tigeot * central registry and provide functions to retrieve those panels in display
398621f407SFrançois Tigeot * drivers.
408621f407SFrançois Tigeot */
418621f407SFrançois Tigeot
428621f407SFrançois Tigeot /**
438621f407SFrançois Tigeot * drm_panel_init - initialize a panel
448621f407SFrançois Tigeot * @panel: DRM panel
458621f407SFrançois Tigeot *
468621f407SFrançois Tigeot * Sets up internal fields of the panel so that it can subsequently be added
478621f407SFrançois Tigeot * to the registry.
488621f407SFrançois Tigeot */
drm_panel_init(struct drm_panel * panel)492c9916cdSFrançois Tigeot void drm_panel_init(struct drm_panel *panel)
502c9916cdSFrançois Tigeot {
512c9916cdSFrançois Tigeot INIT_LIST_HEAD(&panel->list);
522c9916cdSFrançois Tigeot }
532c9916cdSFrançois Tigeot EXPORT_SYMBOL(drm_panel_init);
542c9916cdSFrançois Tigeot
558621f407SFrançois Tigeot /**
568621f407SFrançois Tigeot * drm_panel_add - add a panel to the global registry
578621f407SFrançois Tigeot * @panel: panel to add
588621f407SFrançois Tigeot *
598621f407SFrançois Tigeot * Add a panel to the global registry so that it can be looked up by display
608621f407SFrançois Tigeot * drivers.
618621f407SFrançois Tigeot *
628621f407SFrançois Tigeot * Return: 0 on success or a negative error code on failure.
638621f407SFrançois Tigeot */
drm_panel_add(struct drm_panel * panel)642c9916cdSFrançois Tigeot int drm_panel_add(struct drm_panel *panel)
652c9916cdSFrançois Tigeot {
662c9916cdSFrançois Tigeot mutex_lock(&panel_lock);
672c9916cdSFrançois Tigeot list_add_tail(&panel->list, &panel_list);
682c9916cdSFrançois Tigeot mutex_unlock(&panel_lock);
692c9916cdSFrançois Tigeot
702c9916cdSFrançois Tigeot return 0;
712c9916cdSFrançois Tigeot }
722c9916cdSFrançois Tigeot EXPORT_SYMBOL(drm_panel_add);
732c9916cdSFrançois Tigeot
748621f407SFrançois Tigeot /**
758621f407SFrançois Tigeot * drm_panel_remove - remove a panel from the global registry
768621f407SFrançois Tigeot * @panel: DRM panel
778621f407SFrançois Tigeot *
788621f407SFrançois Tigeot * Removes a panel from the global registry.
798621f407SFrançois Tigeot */
drm_panel_remove(struct drm_panel * panel)802c9916cdSFrançois Tigeot void drm_panel_remove(struct drm_panel *panel)
812c9916cdSFrançois Tigeot {
822c9916cdSFrançois Tigeot mutex_lock(&panel_lock);
832c9916cdSFrançois Tigeot list_del_init(&panel->list);
842c9916cdSFrançois Tigeot mutex_unlock(&panel_lock);
852c9916cdSFrançois Tigeot }
862c9916cdSFrançois Tigeot EXPORT_SYMBOL(drm_panel_remove);
872c9916cdSFrançois Tigeot
888621f407SFrançois Tigeot /**
898621f407SFrançois Tigeot * drm_panel_attach - attach a panel to a connector
908621f407SFrançois Tigeot * @panel: DRM panel
918621f407SFrançois Tigeot * @connector: DRM connector
928621f407SFrançois Tigeot *
938621f407SFrançois Tigeot * After obtaining a pointer to a DRM panel a display driver calls this
948621f407SFrançois Tigeot * function to attach a panel to a connector.
958621f407SFrançois Tigeot *
968621f407SFrançois Tigeot * An error is returned if the panel is already attached to another connector.
978621f407SFrançois Tigeot *
988621f407SFrançois Tigeot * Return: 0 on success or a negative error code on failure.
998621f407SFrançois Tigeot */
drm_panel_attach(struct drm_panel * panel,struct drm_connector * connector)1002c9916cdSFrançois Tigeot int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
1012c9916cdSFrançois Tigeot {
1022c9916cdSFrançois Tigeot if (panel->connector)
1032c9916cdSFrançois Tigeot return -EBUSY;
1042c9916cdSFrançois Tigeot
1052c9916cdSFrançois Tigeot panel->connector = connector;
1062c9916cdSFrançois Tigeot panel->drm = connector->dev;
1072c9916cdSFrançois Tigeot
1082c9916cdSFrançois Tigeot return 0;
1092c9916cdSFrançois Tigeot }
1102c9916cdSFrançois Tigeot EXPORT_SYMBOL(drm_panel_attach);
1112c9916cdSFrançois Tigeot
1128621f407SFrançois Tigeot /**
1138621f407SFrançois Tigeot * drm_panel_detach - detach a panel from a connector
1148621f407SFrançois Tigeot * @panel: DRM panel
1158621f407SFrançois Tigeot *
1168621f407SFrançois Tigeot * Detaches a panel from the connector it is attached to. If a panel is not
1178621f407SFrançois Tigeot * attached to any connector this is effectively a no-op.
1188621f407SFrançois Tigeot *
1198621f407SFrançois Tigeot * Return: 0 on success or a negative error code on failure.
1208621f407SFrançois Tigeot */
drm_panel_detach(struct drm_panel * panel)1212c9916cdSFrançois Tigeot int drm_panel_detach(struct drm_panel *panel)
1222c9916cdSFrançois Tigeot {
1232c9916cdSFrançois Tigeot panel->connector = NULL;
1242c9916cdSFrançois Tigeot panel->drm = NULL;
1252c9916cdSFrançois Tigeot
1262c9916cdSFrançois Tigeot return 0;
1272c9916cdSFrançois Tigeot }
1282c9916cdSFrançois Tigeot EXPORT_SYMBOL(drm_panel_detach);
1292c9916cdSFrançois Tigeot
1302c9916cdSFrançois Tigeot #ifdef CONFIG_OF
1318621f407SFrançois Tigeot /**
1328621f407SFrançois Tigeot * of_drm_find_panel - look up a panel using a device tree node
1338621f407SFrançois Tigeot * @np: device tree node of the panel
1348621f407SFrançois Tigeot *
1358621f407SFrançois Tigeot * Searches the set of registered panels for one that matches the given device
1368621f407SFrançois Tigeot * tree node. If a matching panel is found, return a pointer to it.
1378621f407SFrançois Tigeot *
1388621f407SFrançois Tigeot * Return: A pointer to the panel registered for the specified device tree
1398621f407SFrançois Tigeot * node or NULL if no panel matching the device tree node can be found.
1408621f407SFrançois Tigeot */
of_drm_find_panel(const struct device_node * np)141*a85cb24fSFrançois Tigeot struct drm_panel *of_drm_find_panel(const struct device_node *np)
1422c9916cdSFrançois Tigeot {
1432c9916cdSFrançois Tigeot struct drm_panel *panel;
1442c9916cdSFrançois Tigeot
1452c9916cdSFrançois Tigeot mutex_lock(&panel_lock);
1462c9916cdSFrançois Tigeot
1472c9916cdSFrançois Tigeot list_for_each_entry(panel, &panel_list, list) {
1482c9916cdSFrançois Tigeot if (panel->dev->of_node == np) {
1492c9916cdSFrançois Tigeot mutex_unlock(&panel_lock);
1502c9916cdSFrançois Tigeot return panel;
1512c9916cdSFrançois Tigeot }
1522c9916cdSFrançois Tigeot }
1532c9916cdSFrançois Tigeot
1542c9916cdSFrançois Tigeot mutex_unlock(&panel_lock);
1552c9916cdSFrançois Tigeot return NULL;
1562c9916cdSFrançois Tigeot }
1572c9916cdSFrançois Tigeot EXPORT_SYMBOL(of_drm_find_panel);
1582c9916cdSFrançois Tigeot #endif
1592c9916cdSFrançois Tigeot
1602c9916cdSFrançois Tigeot MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
1612c9916cdSFrançois Tigeot MODULE_DESCRIPTION("DRM panel infrastructure");
162