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