xref: /openbmc/linux/drivers/gpu/drm/omapdrm/dss/output.c (revision dc6a81c3)
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