1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 4 * Author: Archit Taneja <archit@ti.com> 5 */ 6 7 #include <linux/bitops.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/slab.h> 12 #include <linux/of.h> 13 #include <linux/of_graph.h> 14 15 #include <drm/drm_bridge.h> 16 #include <drm/drm_panel.h> 17 18 #include "dss.h" 19 #include "omapdss.h" 20 21 int omapdss_device_init_output(struct omap_dss_device *out) 22 { 23 struct device_node *remote_node; 24 25 remote_node = of_graph_get_remote_node(out->dev->of_node, 26 ffs(out->of_ports) - 1, 0); 27 if (!remote_node) { 28 dev_dbg(out->dev, "failed to find video sink\n"); 29 return 0; 30 } 31 32 out->next = omapdss_find_device_by_node(remote_node); 33 out->bridge = of_drm_find_bridge(remote_node); 34 out->panel = of_drm_find_panel(remote_node); 35 if (IS_ERR(out->panel)) 36 out->panel = NULL; 37 38 of_node_put(remote_node); 39 40 if (out->next && out->type != out->next->type) { 41 dev_err(out->dev, "output type and display type don't match\n"); 42 omapdss_device_put(out->next); 43 out->next = NULL; 44 return -EINVAL; 45 } 46 47 return out->next || out->bridge || out->panel ? 0 : -EPROBE_DEFER; 48 } 49 EXPORT_SYMBOL(omapdss_device_init_output); 50 51 void omapdss_device_cleanup_output(struct omap_dss_device *out) 52 { 53 if (out->next) 54 omapdss_device_put(out->next); 55 } 56 EXPORT_SYMBOL(omapdss_device_cleanup_output); 57 58 int dss_install_mgr_ops(struct dss_device *dss, 59 const struct dss_mgr_ops *mgr_ops, 60 struct omap_drm_private *priv) 61 { 62 if (dss->mgr_ops) 63 return -EBUSY; 64 65 dss->mgr_ops = mgr_ops; 66 dss->mgr_ops_priv = priv; 67 68 return 0; 69 } 70 EXPORT_SYMBOL(dss_install_mgr_ops); 71 72 void dss_uninstall_mgr_ops(struct dss_device *dss) 73 { 74 dss->mgr_ops = NULL; 75 dss->mgr_ops_priv = NULL; 76 } 77 EXPORT_SYMBOL(dss_uninstall_mgr_ops); 78 79 void dss_mgr_set_timings(struct omap_dss_device *dssdev, 80 const struct videomode *vm) 81 { 82 dssdev->dss->mgr_ops->set_timings(dssdev->dss->mgr_ops_priv, 83 dssdev->dispc_channel, vm); 84 } 85 EXPORT_SYMBOL(dss_mgr_set_timings); 86 87 void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev, 88 const struct dss_lcd_mgr_config *config) 89 { 90 dssdev->dss->mgr_ops->set_lcd_config(dssdev->dss->mgr_ops_priv, 91 dssdev->dispc_channel, config); 92 } 93 EXPORT_SYMBOL(dss_mgr_set_lcd_config); 94 95 int dss_mgr_enable(struct omap_dss_device *dssdev) 96 { 97 return dssdev->dss->mgr_ops->enable(dssdev->dss->mgr_ops_priv, 98 dssdev->dispc_channel); 99 } 100 EXPORT_SYMBOL(dss_mgr_enable); 101 102 void dss_mgr_disable(struct omap_dss_device *dssdev) 103 { 104 dssdev->dss->mgr_ops->disable(dssdev->dss->mgr_ops_priv, 105 dssdev->dispc_channel); 106 } 107 EXPORT_SYMBOL(dss_mgr_disable); 108 109 void dss_mgr_start_update(struct omap_dss_device *dssdev) 110 { 111 dssdev->dss->mgr_ops->start_update(dssdev->dss->mgr_ops_priv, 112 dssdev->dispc_channel); 113 } 114 EXPORT_SYMBOL(dss_mgr_start_update); 115 116 int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev, 117 void (*handler)(void *), void *data) 118 { 119 struct dss_device *dss = dssdev->dss; 120 121 return dss->mgr_ops->register_framedone_handler(dss->mgr_ops_priv, 122 dssdev->dispc_channel, 123 handler, data); 124 } 125 EXPORT_SYMBOL(dss_mgr_register_framedone_handler); 126 127 void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev, 128 void (*handler)(void *), void *data) 129 { 130 struct dss_device *dss = dssdev->dss; 131 132 dss->mgr_ops->unregister_framedone_handler(dss->mgr_ops_priv, 133 dssdev->dispc_channel, 134 handler, data); 135 } 136 EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler); 137