1 /*
2  * OF helpers for parsing display timings
3  *
4  * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
5  *
6  * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
7  *
8  * This file is released under the GPLv2
9  */
10 #include <linux/export.h>
11 #include <linux/of.h>
12 #include <linux/slab.h>
13 #include <video/display_timing.h>
14 #include <video/of_display_timing.h>
15 
16 /**
17  * parse_timing_property - parse timing_entry from device_node
18  * @np: device_node with the property
19  * @name: name of the property
20  * @result: will be set to the return value
21  *
22  * DESCRIPTION:
23  * Every display_timing can be specified with either just the typical value or
24  * a range consisting of min/typ/max. This function helps handling this
25  **/
26 static int parse_timing_property(struct device_node *np, const char *name,
27 			  struct timing_entry *result)
28 {
29 	struct property *prop;
30 	int length, cells, ret;
31 
32 	prop = of_find_property(np, name, &length);
33 	if (!prop) {
34 		pr_err("%s: could not find property %s\n",
35 			of_node_full_name(np), name);
36 		return -EINVAL;
37 	}
38 
39 	cells = length / sizeof(u32);
40 	if (cells == 1) {
41 		ret = of_property_read_u32(np, name, &result->typ);
42 		result->min = result->typ;
43 		result->max = result->typ;
44 	} else if (cells == 3) {
45 		ret = of_property_read_u32_array(np, name, &result->min, cells);
46 	} else {
47 		pr_err("%s: illegal timing specification in %s\n",
48 			of_node_full_name(np), name);
49 		return -EINVAL;
50 	}
51 
52 	return ret;
53 }
54 
55 /**
56  * of_get_display_timing - parse display_timing entry from device_node
57  * @np: device_node with the properties
58  **/
59 static struct display_timing *of_get_display_timing(struct device_node *np)
60 {
61 	struct display_timing *dt;
62 	u32 val = 0;
63 	int ret = 0;
64 
65 	dt = kzalloc(sizeof(*dt), GFP_KERNEL);
66 	if (!dt) {
67 		pr_err("%s: could not allocate display_timing struct\n",
68 			of_node_full_name(np));
69 		return NULL;
70 	}
71 
72 	ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
73 	ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
74 	ret |= parse_timing_property(np, "hactive", &dt->hactive);
75 	ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
76 	ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
77 	ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
78 	ret |= parse_timing_property(np, "vactive", &dt->vactive);
79 	ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
80 	ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
81 
82 	dt->flags = 0;
83 	if (!of_property_read_u32(np, "vsync-active", &val))
84 		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
85 				DISPLAY_FLAGS_VSYNC_LOW;
86 	if (!of_property_read_u32(np, "hsync-active", &val))
87 		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
88 				DISPLAY_FLAGS_HSYNC_LOW;
89 	if (!of_property_read_u32(np, "de-active", &val))
90 		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
91 				DISPLAY_FLAGS_DE_LOW;
92 	if (!of_property_read_u32(np, "pixelclk-active", &val))
93 		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
94 				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
95 
96 	if (of_property_read_bool(np, "interlaced"))
97 		dt->flags |= DISPLAY_FLAGS_INTERLACED;
98 	if (of_property_read_bool(np, "doublescan"))
99 		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
100 
101 	if (ret) {
102 		pr_err("%s: error reading timing properties\n",
103 			of_node_full_name(np));
104 		kfree(dt);
105 		return NULL;
106 	}
107 
108 	return dt;
109 }
110 
111 /**
112  * of_get_display_timings - parse all display_timing entries from a device_node
113  * @np: device_node with the subnodes
114  **/
115 struct display_timings *of_get_display_timings(struct device_node *np)
116 {
117 	struct device_node *timings_np;
118 	struct device_node *entry;
119 	struct device_node *native_mode;
120 	struct display_timings *disp;
121 
122 	if (!np) {
123 		pr_err("%s: no devicenode given\n", of_node_full_name(np));
124 		return NULL;
125 	}
126 
127 	timings_np = of_find_node_by_name(np, "display-timings");
128 	if (!timings_np) {
129 		pr_err("%s: could not find display-timings node\n",
130 			of_node_full_name(np));
131 		return NULL;
132 	}
133 
134 	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
135 	if (!disp) {
136 		pr_err("%s: could not allocate struct disp'\n",
137 			of_node_full_name(np));
138 		goto dispfail;
139 	}
140 
141 	entry = of_parse_phandle(timings_np, "native-mode", 0);
142 	/* assume first child as native mode if none provided */
143 	if (!entry)
144 		entry = of_get_next_child(np, NULL);
145 	/* if there is no child, it is useless to go on */
146 	if (!entry) {
147 		pr_err("%s: no timing specifications given\n",
148 			of_node_full_name(np));
149 		goto entryfail;
150 	}
151 
152 	pr_debug("%s: using %s as default timing\n",
153 		of_node_full_name(np), entry->name);
154 
155 	native_mode = entry;
156 
157 	disp->num_timings = of_get_child_count(timings_np);
158 	if (disp->num_timings == 0) {
159 		/* should never happen, as entry was already found above */
160 		pr_err("%s: no timings specified\n", of_node_full_name(np));
161 		goto entryfail;
162 	}
163 
164 	disp->timings = kzalloc(sizeof(struct display_timing *) *
165 				disp->num_timings, GFP_KERNEL);
166 	if (!disp->timings) {
167 		pr_err("%s: could not allocate timings array\n",
168 			of_node_full_name(np));
169 		goto entryfail;
170 	}
171 
172 	disp->num_timings = 0;
173 	disp->native_mode = 0;
174 
175 	for_each_child_of_node(timings_np, entry) {
176 		struct display_timing *dt;
177 
178 		dt = of_get_display_timing(entry);
179 		if (!dt) {
180 			/*
181 			 * to not encourage wrong devicetrees, fail in case of
182 			 * an error
183 			 */
184 			pr_err("%s: error in timing %d\n",
185 				of_node_full_name(np), disp->num_timings + 1);
186 			goto timingfail;
187 		}
188 
189 		if (native_mode == entry)
190 			disp->native_mode = disp->num_timings;
191 
192 		disp->timings[disp->num_timings] = dt;
193 		disp->num_timings++;
194 	}
195 	of_node_put(timings_np);
196 	/*
197 	 * native_mode points to the device_node returned by of_parse_phandle
198 	 * therefore call of_node_put on it
199 	 */
200 	of_node_put(native_mode);
201 
202 	pr_debug("%s: got %d timings. Using timing #%d as default\n",
203 		of_node_full_name(np), disp->num_timings,
204 		disp->native_mode + 1);
205 
206 	return disp;
207 
208 timingfail:
209 	if (native_mode)
210 		of_node_put(native_mode);
211 	display_timings_release(disp);
212 entryfail:
213 	kfree(disp);
214 dispfail:
215 	of_node_put(timings_np);
216 	return NULL;
217 }
218 EXPORT_SYMBOL_GPL(of_get_display_timings);
219 
220 /**
221  * of_display_timings_exist - check if a display-timings node is provided
222  * @np: device_node with the timing
223  **/
224 int of_display_timings_exist(struct device_node *np)
225 {
226 	struct device_node *timings_np;
227 
228 	if (!np)
229 		return -EINVAL;
230 
231 	timings_np = of_parse_phandle(np, "display-timings", 0);
232 	if (!timings_np)
233 		return -EINVAL;
234 
235 	of_node_put(timings_np);
236 	return 1;
237 }
238 EXPORT_SYMBOL_GPL(of_display_timings_exist);
239