1bb5cdf8dSAndrew F. Davis /* 2bb5cdf8dSAndrew F. Davis * OMAP Display Subsystem Base 3bb5cdf8dSAndrew F. Davis * 4bb5cdf8dSAndrew F. Davis * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ 5bb5cdf8dSAndrew F. Davis * 6bb5cdf8dSAndrew F. Davis * This program is free software; you can redistribute it and/or modify 7bb5cdf8dSAndrew F. Davis * it under the terms of the GNU General Public License version 2 as 8bb5cdf8dSAndrew F. Davis * published by the Free Software Foundation. 9bb5cdf8dSAndrew F. Davis * 10bb5cdf8dSAndrew F. Davis * This program is distributed in the hope that it will be useful, but 11bb5cdf8dSAndrew F. Davis * WITHOUT ANY WARRANTY; without even the implied warranty of 12bb5cdf8dSAndrew F. Davis * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13bb5cdf8dSAndrew F. Davis * General Public License for more details. 14bb5cdf8dSAndrew F. Davis */ 15bb5cdf8dSAndrew F. Davis 16a99ac0d9STomi Valkeinen #include <linux/kernel.h> 17a99ac0d9STomi Valkeinen #include <linux/module.h> 181e08c822SPeter Ujfalusi #include <linux/of.h> 191e08c822SPeter Ujfalusi #include <linux/of_graph.h> 201e08c822SPeter Ujfalusi #include <linux/list.h> 21d3541ca8SLaurent Pinchart 22d3541ca8SLaurent Pinchart #include "dss.h" 231e08c822SPeter Ujfalusi #include "omapdss.h" 24a99ac0d9STomi Valkeinen 2572877cf3SLaurent Pinchart static struct dss_device *dss_device; 267c299716STomi Valkeinen 271e08c822SPeter Ujfalusi static struct list_head omapdss_comp_list; 281e08c822SPeter Ujfalusi 291e08c822SPeter Ujfalusi struct omapdss_comp_node { 301e08c822SPeter Ujfalusi struct list_head list; 311e08c822SPeter Ujfalusi struct device_node *node; 321e08c822SPeter Ujfalusi bool dss_core_component; 331e08c822SPeter Ujfalusi }; 341e08c822SPeter Ujfalusi 3572877cf3SLaurent Pinchart struct dss_device *omapdss_get_dss(void) 367c299716STomi Valkeinen { 3772877cf3SLaurent Pinchart return dss_device; 387c299716STomi Valkeinen } 3972877cf3SLaurent Pinchart EXPORT_SYMBOL(omapdss_get_dss); 407c299716STomi Valkeinen 4172877cf3SLaurent Pinchart void omapdss_set_dss(struct dss_device *dss) 427c299716STomi Valkeinen { 4372877cf3SLaurent Pinchart dss_device = dss; 447c299716STomi Valkeinen } 4572877cf3SLaurent Pinchart EXPORT_SYMBOL(omapdss_set_dss); 467c299716STomi Valkeinen 47*50638ae5SLaurent Pinchart struct dispc_device *dispc_get_dispc(struct dss_device *dss) 48*50638ae5SLaurent Pinchart { 49*50638ae5SLaurent Pinchart return dss->dispc; 50*50638ae5SLaurent Pinchart } 51*50638ae5SLaurent Pinchart EXPORT_SYMBOL(dispc_get_dispc); 52*50638ae5SLaurent Pinchart 53d3541ca8SLaurent Pinchart const struct dispc_ops *dispc_get_ops(struct dss_device *dss) 548a13398cSTomi Valkeinen { 55d3541ca8SLaurent Pinchart return dss->dispc_ops; 568a13398cSTomi Valkeinen } 578a13398cSTomi Valkeinen EXPORT_SYMBOL(dispc_get_ops); 588a13398cSTomi Valkeinen 591e08c822SPeter Ujfalusi static bool omapdss_list_contains(const struct device_node *node) 601e08c822SPeter Ujfalusi { 611e08c822SPeter Ujfalusi struct omapdss_comp_node *comp; 621e08c822SPeter Ujfalusi 631e08c822SPeter Ujfalusi list_for_each_entry(comp, &omapdss_comp_list, list) { 641e08c822SPeter Ujfalusi if (comp->node == node) 651e08c822SPeter Ujfalusi return true; 661e08c822SPeter Ujfalusi } 671e08c822SPeter Ujfalusi 681e08c822SPeter Ujfalusi return false; 691e08c822SPeter Ujfalusi } 701e08c822SPeter Ujfalusi 711e08c822SPeter Ujfalusi static void omapdss_walk_device(struct device *dev, struct device_node *node, 721e08c822SPeter Ujfalusi bool dss_core) 731e08c822SPeter Ujfalusi { 741e08c822SPeter Ujfalusi struct device_node *n; 751e08c822SPeter Ujfalusi struct omapdss_comp_node *comp = devm_kzalloc(dev, sizeof(*comp), 761e08c822SPeter Ujfalusi GFP_KERNEL); 771e08c822SPeter Ujfalusi 781e08c822SPeter Ujfalusi if (comp) { 791e08c822SPeter Ujfalusi comp->node = node; 801e08c822SPeter Ujfalusi comp->dss_core_component = dss_core; 811e08c822SPeter Ujfalusi list_add(&comp->list, &omapdss_comp_list); 821e08c822SPeter Ujfalusi } 831e08c822SPeter Ujfalusi 841e08c822SPeter Ujfalusi /* 851e08c822SPeter Ujfalusi * of_graph_get_remote_port_parent() prints an error if there is no 861e08c822SPeter Ujfalusi * port/ports node. To avoid that, check first that there's the node. 871e08c822SPeter Ujfalusi */ 881e08c822SPeter Ujfalusi n = of_get_child_by_name(node, "ports"); 891e08c822SPeter Ujfalusi if (!n) 901e08c822SPeter Ujfalusi n = of_get_child_by_name(node, "port"); 911e08c822SPeter Ujfalusi if (!n) 921e08c822SPeter Ujfalusi return; 931e08c822SPeter Ujfalusi 941e08c822SPeter Ujfalusi of_node_put(n); 951e08c822SPeter Ujfalusi 961e08c822SPeter Ujfalusi n = NULL; 971e08c822SPeter Ujfalusi while ((n = of_graph_get_next_endpoint(node, n)) != NULL) { 981e08c822SPeter Ujfalusi struct device_node *pn = of_graph_get_remote_port_parent(n); 991e08c822SPeter Ujfalusi 1001e08c822SPeter Ujfalusi if (!pn) 1011e08c822SPeter Ujfalusi continue; 1021e08c822SPeter Ujfalusi 1031e08c822SPeter Ujfalusi if (!of_device_is_available(pn) || omapdss_list_contains(pn)) { 1041e08c822SPeter Ujfalusi of_node_put(pn); 1051e08c822SPeter Ujfalusi continue; 1061e08c822SPeter Ujfalusi } 1071e08c822SPeter Ujfalusi 1081e08c822SPeter Ujfalusi omapdss_walk_device(dev, pn, false); 1091e08c822SPeter Ujfalusi } 1101e08c822SPeter Ujfalusi } 1111e08c822SPeter Ujfalusi 1121e08c822SPeter Ujfalusi void omapdss_gather_components(struct device *dev) 1131e08c822SPeter Ujfalusi { 1141e08c822SPeter Ujfalusi struct device_node *child; 1151e08c822SPeter Ujfalusi 1161e08c822SPeter Ujfalusi INIT_LIST_HEAD(&omapdss_comp_list); 1171e08c822SPeter Ujfalusi 1181e08c822SPeter Ujfalusi omapdss_walk_device(dev, dev->of_node, true); 1191e08c822SPeter Ujfalusi 1201e08c822SPeter Ujfalusi for_each_available_child_of_node(dev->of_node, child) { 1211e08c822SPeter Ujfalusi if (!of_find_property(child, "compatible", NULL)) 1221e08c822SPeter Ujfalusi continue; 1231e08c822SPeter Ujfalusi 1241e08c822SPeter Ujfalusi omapdss_walk_device(dev, child, true); 1251e08c822SPeter Ujfalusi } 1261e08c822SPeter Ujfalusi } 1271e08c822SPeter Ujfalusi EXPORT_SYMBOL(omapdss_gather_components); 1281e08c822SPeter Ujfalusi 1291e08c822SPeter Ujfalusi static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp) 1301e08c822SPeter Ujfalusi { 1311e08c822SPeter Ujfalusi if (comp->dss_core_component) 1321e08c822SPeter Ujfalusi return true; 1331e08c822SPeter Ujfalusi if (omapdss_component_is_display(comp->node)) 1341e08c822SPeter Ujfalusi return true; 1351e08c822SPeter Ujfalusi if (omapdss_component_is_output(comp->node)) 1361e08c822SPeter Ujfalusi return true; 1371e08c822SPeter Ujfalusi 1381e08c822SPeter Ujfalusi return false; 1391e08c822SPeter Ujfalusi } 1401e08c822SPeter Ujfalusi 1411e08c822SPeter Ujfalusi bool omapdss_stack_is_ready(void) 1421e08c822SPeter Ujfalusi { 1431e08c822SPeter Ujfalusi struct omapdss_comp_node *comp; 1441e08c822SPeter Ujfalusi 1451e08c822SPeter Ujfalusi list_for_each_entry(comp, &omapdss_comp_list, list) { 1461e08c822SPeter Ujfalusi if (!omapdss_component_is_loaded(comp)) 1471e08c822SPeter Ujfalusi return false; 1481e08c822SPeter Ujfalusi } 1491e08c822SPeter Ujfalusi 1501e08c822SPeter Ujfalusi return true; 1511e08c822SPeter Ujfalusi } 1521e08c822SPeter Ujfalusi EXPORT_SYMBOL(omapdss_stack_is_ready); 1531e08c822SPeter Ujfalusi 154a99ac0d9STomi Valkeinen MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 155a99ac0d9STomi Valkeinen MODULE_DESCRIPTION("OMAP Display Subsystem Base"); 156a99ac0d9STomi Valkeinen MODULE_LICENSE("GPL v2"); 157