eDP:RK3288 check format for rk32_dp.c rk32_dp.h
[firefly-linux-kernel-4.4.55.git] / drivers / video / of_display_timing.c
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 #if defined(CONFIG_FB_ROCKCHIP) || defined(CONFIG_DRM_ROCKCHIP)
65         struct property *prop;
66         int length;
67 #endif
68         dt = kzalloc(sizeof(*dt), GFP_KERNEL);
69         if (!dt) {
70                 pr_err("%s: could not allocate display_timing struct\n",
71                         of_node_full_name(np));
72                 return NULL;
73         }
74
75         ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
76         ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
77         ret |= parse_timing_property(np, "hactive", &dt->hactive);
78         ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
79         ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
80         ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
81         ret |= parse_timing_property(np, "vactive", &dt->vactive);
82         ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
83         ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
84
85         dt->flags = 0;
86         if (!of_property_read_u32(np, "vsync-active", &val))
87                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
88                                 DISPLAY_FLAGS_VSYNC_LOW;
89         if (!of_property_read_u32(np, "hsync-active", &val))
90                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
91                                 DISPLAY_FLAGS_HSYNC_LOW;
92         if (!of_property_read_u32(np, "de-active", &val))
93                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
94                                 DISPLAY_FLAGS_DE_LOW;
95         if (!of_property_read_u32(np, "pixelclk-active", &val))
96                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
97                                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
98
99         if (of_property_read_bool(np, "interlaced"))
100                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
101         if (of_property_read_bool(np, "doublescan"))
102                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
103
104 #if defined(CONFIG_FB_ROCKCHIP) || defined(CONFIG_DRM_ROCKCHIP)
105         if (!of_property_read_u32(np, "swap-rg", &val))
106                 dt->flags |= val ? DISPLAY_FLAGS_SWAP_RG : 0;
107         if (!of_property_read_u32(np, "swap-gb", &val))
108                 dt->flags |= val ? DISPLAY_FLAGS_SWAP_GB : 0;
109         if (!of_property_read_u32(np, "swap-rb", &val))
110                 dt->flags |= val ? DISPLAY_FLAGS_SWAP_RB : 0;
111         if (!of_property_read_u32(np, "screen-type", &val))
112                 dt->screen_type = val;
113         if (!of_property_read_u32(np, "lvds-format", &val))
114                 dt->lvds_format = val;
115         if (!of_property_read_u32(np, "out-face", &val))
116                 dt->face = val;
117         if (!of_property_read_u32(np, "color-mode", &val))
118                 dt->color_mode = val;
119         prop = of_find_property(np, "dsp-lut", &length);
120         if (prop) {
121                 dt->dsp_lut = kzalloc(length, GFP_KERNEL);
122                 if (dt->dsp_lut)
123                         ret = of_property_read_u32_array(np,
124                                 "dsp-lut",dt->dsp_lut, length >> 2);
125         }
126         prop = of_find_property(np, "cabc-lut", &length);
127         if (prop) {
128                 dt->cabc_lut = kzalloc(length, GFP_KERNEL);
129                 if (dt->cabc_lut)
130                         ret = of_property_read_u32_array(np,
131                                                          "cabc-lut",
132                                                          dt->cabc_lut,
133                                                          length >> 2);
134         }
135
136         prop = of_find_property(np, "cabc-gamma-base", &length);
137         if (prop) {
138                 dt->cabc_gamma_base = kzalloc(length, GFP_KERNEL);
139                 if (dt->cabc_gamma_base)
140                         ret = of_property_read_u32_array(np,
141                                                          "cabc-gamma-base",
142                                                          dt->cabc_gamma_base,
143                                                          length >> 2);
144         }
145 #endif
146
147         if (ret) {
148                 pr_err("%s: error reading timing properties\n",
149                         of_node_full_name(np));
150                 kfree(dt);
151                 return NULL;
152         }
153
154         return dt;
155 }
156
157 /**
158  * of_get_display_timings - parse all display_timing entries from a device_node
159  * @np: device_node with the subnodes
160  **/
161 struct display_timings *of_get_display_timings(struct device_node *np)
162 {
163         struct device_node *timings_np;
164         struct device_node *entry;
165         struct device_node *native_mode;
166         struct display_timings *disp;
167
168         if (!np) {
169                 pr_err("%s: no devicenode given\n", of_node_full_name(np));
170                 return NULL;
171         }
172
173         timings_np = of_find_node_by_name(np, "display-timings");
174         if (!timings_np) {
175                 pr_err("%s: could not find display-timings node\n",
176                         of_node_full_name(np));
177                 return NULL;
178         }
179
180         disp = kzalloc(sizeof(*disp), GFP_KERNEL);
181         if (!disp) {
182                 pr_err("%s: could not allocate struct disp'\n",
183                         of_node_full_name(np));
184                 goto dispfail;
185         }
186
187         entry = of_parse_phandle(timings_np, "native-mode", 0);
188         /* assume first child as native mode if none provided */
189         if (!entry)
190                 entry = of_get_next_child(np, NULL);
191         /* if there is no child, it is useless to go on */
192         if (!entry) {
193                 pr_err("%s: no timing specifications given\n",
194                         of_node_full_name(np));
195                 goto entryfail;
196         }
197
198         pr_debug("%s: using %s as default timing\n",
199                 of_node_full_name(np), entry->name);
200
201         native_mode = entry;
202
203         disp->num_timings = of_get_child_count(timings_np);
204         if (disp->num_timings == 0) {
205                 /* should never happen, as entry was already found above */
206                 pr_err("%s: no timings specified\n", of_node_full_name(np));
207                 goto entryfail;
208         }
209
210         disp->timings = kzalloc(sizeof(struct display_timing *) *
211                                 disp->num_timings, GFP_KERNEL);
212         if (!disp->timings) {
213                 pr_err("%s: could not allocate timings array\n",
214                         of_node_full_name(np));
215                 goto entryfail;
216         }
217
218         disp->num_timings = 0;
219         disp->native_mode = 0;
220
221         for_each_child_of_node(timings_np, entry) {
222                 struct display_timing *dt;
223
224                 dt = of_get_display_timing(entry);
225                 if (!dt) {
226                         /*
227                          * to not encourage wrong devicetrees, fail in case of
228                          * an error
229                          */
230                         pr_err("%s: error in timing %d\n",
231                                 of_node_full_name(np), disp->num_timings + 1);
232                         goto timingfail;
233                 }
234
235                 if (native_mode == entry)
236                         disp->native_mode = disp->num_timings;
237
238                 disp->timings[disp->num_timings] = dt;
239                 disp->num_timings++;
240         }
241         of_node_put(timings_np);
242         /*
243          * native_mode points to the device_node returned by of_parse_phandle
244          * therefore call of_node_put on it
245          */
246         of_node_put(native_mode);
247
248         pr_debug("%s: got %d timings. Using timing #%d as default\n",
249                 of_node_full_name(np), disp->num_timings,
250                 disp->native_mode + 1);
251
252         return disp;
253
254 timingfail:
255         if (native_mode)
256                 of_node_put(native_mode);
257         display_timings_release(disp);
258 entryfail:
259         kfree(disp);
260 dispfail:
261         of_node_put(timings_np);
262         return NULL;
263 }
264 EXPORT_SYMBOL_GPL(of_get_display_timings);
265
266 /**
267  * of_display_timings_exist - check if a display-timings node is provided
268  * @np: device_node with the timing
269  **/
270 int of_display_timings_exist(struct device_node *np)
271 {
272         struct device_node *timings_np;
273
274         if (!np)
275                 return -EINVAL;
276
277         timings_np = of_parse_phandle(np, "display-timings", 0);
278         if (!timings_np)
279                 return -EINVAL;
280
281         of_node_put(timings_np);
282         return 1;
283 }
284 EXPORT_SYMBOL_GPL(of_display_timings_exist);