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