aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-05-15 03:41:34 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-05-28 02:25:15 -0400
commitf2dd36ac9974cc2353bcbb8e6b643fb96030564c (patch)
treefda3f517df2ec8c72dca114ba5688a54b358b3ef /drivers/video
parent2b22df835ba42ad6c5f09a52baf68cfb60650f56 (diff)
OMAPDSS: move 'compatible' converter to omapdss driver
Move the panel/encoder driver compatible-string converter from arch/arm/mach-omap2/display.c to omapdss driver. That is a more logical place for it, as it's really an omapdss internal hack. The code is rewritten to follow the video node graph, starting from omapdss. This removes the need to have the device compatible-string database. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/omap2/Makefile2
-rw-r--r--drivers/video/fbdev/omap2/dss/Kconfig4
-rw-r--r--drivers/video/fbdev/omap2/dss/Makefile1
-rw-r--r--drivers/video/fbdev/omap2/dss/omapdss-boot-init.c229
4 files changed, 235 insertions, 1 deletions
diff --git a/drivers/video/fbdev/omap2/Makefile b/drivers/video/fbdev/omap2/Makefile
index bf8127df8c71..f8745ec369cc 100644
--- a/drivers/video/fbdev/omap2/Makefile
+++ b/drivers/video/fbdev/omap2/Makefile
@@ -1,5 +1,5 @@
1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o 1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2 2
3obj-$(CONFIG_OMAP2_DSS) += dss/ 3obj-y += dss/
4obj-y += displays-new/ 4obj-y += displays-new/
5obj-$(CONFIG_FB_OMAP2) += omapfb/ 5obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/fbdev/omap2/dss/Kconfig b/drivers/video/fbdev/omap2/dss/Kconfig
index 8921a7a76a15..285bcd103dce 100644
--- a/drivers/video/fbdev/omap2/dss/Kconfig
+++ b/drivers/video/fbdev/omap2/dss/Kconfig
@@ -1,6 +1,10 @@
1config OMAP2_DSS_INIT
2 bool
3
1menuconfig OMAP2_DSS 4menuconfig OMAP2_DSS
2 tristate "OMAP2+ Display Subsystem support" 5 tristate "OMAP2+ Display Subsystem support"
3 select VIDEOMODE_HELPERS 6 select VIDEOMODE_HELPERS
7 select OMAP2_DSS_INIT
4 help 8 help
5 OMAP2+ Display Subsystem support. 9 OMAP2+ Display Subsystem support.
6 10
diff --git a/drivers/video/fbdev/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile
index 390ab746bdc0..245f933060ee 100644
--- a/drivers/video/fbdev/omap2/dss/Makefile
+++ b/drivers/video/fbdev/omap2/dss/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 2obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2# Core DSS files 3# Core DSS files
3omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 4omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
diff --git a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c
new file mode 100644
index 000000000000..99af9e88b2d8
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c
@@ -0,0 +1,229 @@
1/*
2 * Copyright (C) 2014 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * As omapdss panel drivers are omapdss specific, but we want to define the
20 * DT-data in generic manner, we convert the compatible strings of the panel and
21 * encoder nodes from "panel-foo" to "omapdss,panel-foo". This way we can have
22 * both correct DT data and omapdss specific drivers.
23 *
24 * When we get generic panel drivers to the kernel, this file will be removed.
25 */
26
27#include <linux/kernel.h>
28#include <linux/of.h>
29#include <linux/of_graph.h>
30#include <linux/slab.h>
31#include <linux/list.h>
32
33static struct list_head dss_conv_list __initdata;
34
35static const char prefix[] __initconst = "omapdss,";
36
37struct dss_conv_node {
38 struct list_head list;
39 struct device_node *node;
40 bool root;
41};
42
43static int __init omapdss_count_strings(const struct property *prop)
44{
45 const char *p = prop->value;
46 int l = 0, total = 0;
47 int i;
48
49 for (i = 0; total < prop->length; total += l, p += l, i++)
50 l = strlen(p) + 1;
51
52 return i;
53}
54
55static void __init omapdss_update_prop(struct device_node *node, char *compat,
56 int len)
57{
58 struct property *prop;
59
60 prop = kzalloc(sizeof(*prop), GFP_KERNEL);
61 if (!prop)
62 return;
63
64 prop->name = "compatible";
65 prop->value = compat;
66 prop->length = len;
67
68 of_update_property(node, prop);
69}
70
71static void __init omapdss_prefix_strcpy(char *dst, int dst_len,
72 const char *src, int src_len)
73{
74 size_t total = 0;
75
76 while (total < src_len) {
77 size_t l = strlen(src) + 1;
78
79 strcpy(dst, prefix);
80 dst += strlen(prefix);
81
82 strcpy(dst, src);
83 dst += l;
84
85 src += l;
86 total += l;
87 }
88}
89
90/* prepend compatible property strings with "omapdss," */
91static void __init omapdss_omapify_node(struct device_node *node)
92{
93 struct property *prop;
94 char *new_compat;
95 int num_strs;
96 int new_len;
97
98 prop = of_find_property(node, "compatible", NULL);
99
100 if (!prop || !prop->value)
101 return;
102
103 if (strnlen(prop->value, prop->length) >= prop->length)
104 return;
105
106 /* is it already prefixed? */
107 if (strncmp(prefix, prop->value, strlen(prefix)) == 0)
108 return;
109
110 num_strs = omapdss_count_strings(prop);
111
112 new_len = prop->length + strlen(prefix) * num_strs;
113 new_compat = kmalloc(new_len, GFP_KERNEL);
114
115 omapdss_prefix_strcpy(new_compat, new_len, prop->value, prop->length);
116
117 omapdss_update_prop(node, new_compat, new_len);
118}
119
120static void __init omapdss_add_to_list(struct device_node *node, bool root)
121{
122 struct dss_conv_node *n = kmalloc(sizeof(struct dss_conv_node),
123 GFP_KERNEL);
124 n->node = node;
125 n->root = root;
126 list_add(&n->list, &dss_conv_list);
127}
128
129static bool __init omapdss_list_contains(const struct device_node *node)
130{
131 struct dss_conv_node *n;
132
133 list_for_each_entry(n, &dss_conv_list, list) {
134 if (n->node == node)
135 return true;
136 }
137
138 return false;
139}
140
141static void __init omapdss_walk_device(struct device_node *node, bool root)
142{
143 struct device_node *n;
144
145 omapdss_add_to_list(node, root);
146
147 /*
148 * of_graph_get_remote_port_parent() prints an error if there is no
149 * port/ports node. To avoid that, check first that there's the node.
150 */
151 n = of_get_child_by_name(node, "ports");
152 if (!n)
153 n = of_get_child_by_name(node, "port");
154 if (!n)
155 return;
156
157 of_node_put(n);
158
159 n = NULL;
160 while ((n = of_graph_get_next_endpoint(node, n)) != NULL) {
161 struct device_node *pn;
162
163 pn = of_graph_get_remote_port_parent(n);
164
165 if (!pn) {
166 of_node_put(n);
167 continue;
168 }
169
170 if (!of_device_is_available(pn) || omapdss_list_contains(pn)) {
171 of_node_put(pn);
172 of_node_put(n);
173 continue;
174 }
175
176 omapdss_walk_device(pn, false);
177
178 of_node_put(n);
179 }
180}
181
182static const struct of_device_id omapdss_of_match[] __initconst = {
183 { .compatible = "ti,omap2-dss", },
184 { .compatible = "ti,omap3-dss", },
185 { .compatible = "ti,omap4-dss", },
186 { .compatible = "ti,omap5-dss", },
187 {},
188};
189
190static int __init omapdss_boot_init(void)
191{
192 struct device_node *dss, *child;
193
194 INIT_LIST_HEAD(&dss_conv_list);
195
196 dss = of_find_matching_node(NULL, omapdss_of_match);
197
198 if (dss == NULL || !of_device_is_available(dss))
199 return 0;
200
201 omapdss_walk_device(dss, true);
202
203 for_each_available_child_of_node(dss, child) {
204 if (!of_find_property(child, "compatible", NULL)) {
205 of_node_put(child);
206 continue;
207 }
208
209 omapdss_walk_device(child, true);
210 }
211
212 while (!list_empty(&dss_conv_list)) {
213 struct dss_conv_node *n;
214
215 n = list_first_entry(&dss_conv_list, struct dss_conv_node,
216 list);
217
218 if (!n->root)
219 omapdss_omapify_node(n->node);
220
221 list_del(&n->list);
222 of_node_put(n->node);
223 kfree(n);
224 }
225
226 return 0;
227}
228
229subsys_initcall(omapdss_boot_init);