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