diff options
Diffstat (limited to 'drivers/video/of_display_timing.c')
| -rw-r--r-- | drivers/video/of_display_timing.c | 113 |
1 files changed, 47 insertions, 66 deletions
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c index 171821ddd78d..bebd371c6b93 100644 --- a/drivers/video/of_display_timing.c +++ b/drivers/video/of_display_timing.c @@ -1,11 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * OF helpers for parsing display timings * * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix * * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de> - * - * This file is released under the GPLv2 */ #include <linux/export.h> #include <linux/of.h> @@ -31,8 +30,7 @@ static int parse_timing_property(const struct device_node *np, const char *name, prop = of_find_property(np, name, &length); if (!prop) { - pr_err("%s: could not find property %s\n", - of_node_full_name(np), name); + pr_err("%pOF: could not find property %s\n", np, name); return -EINVAL; } @@ -44,8 +42,7 @@ static int parse_timing_property(const struct device_node *np, const char *name, } else if (cells == 3) { ret = of_property_read_u32_array(np, name, &result->min, cells); } else { - pr_err("%s: illegal timing specification in %s\n", - of_node_full_name(np), name); + pr_err("%pOF: illegal timing specification in %s\n", np, name); return -EINVAL; } @@ -55,6 +52,7 @@ static int parse_timing_property(const struct device_node *np, const char *name, /** * of_parse_display_timing - parse display_timing entry from device_node * @np: device_node with the properties + * @dt: display_timing that contains the result. I may be partially written in case of errors **/ static int of_parse_display_timing(const struct device_node *np, struct display_timing *dt) @@ -88,6 +86,15 @@ static int of_parse_display_timing(const struct device_node *np, dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : DISPLAY_FLAGS_PIXDATA_NEGEDGE; + if (!of_property_read_u32(np, "syncclk-active", &val)) + dt->flags |= val ? DISPLAY_FLAGS_SYNC_POSEDGE : + DISPLAY_FLAGS_SYNC_NEGEDGE; + else if (dt->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE | + DISPLAY_FLAGS_PIXDATA_NEGEDGE)) + dt->flags |= dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? + DISPLAY_FLAGS_SYNC_POSEDGE : + DISPLAY_FLAGS_SYNC_NEGEDGE; + if (of_property_read_bool(np, "interlaced")) dt->flags |= DISPLAY_FLAGS_INTERLACED; if (of_property_read_bool(np, "doublescan")) @@ -96,8 +103,7 @@ static int of_parse_display_timing(const struct device_node *np, dt->flags |= DISPLAY_FLAGS_DOUBLECLK; if (ret) { - pr_err("%s: error reading timing properties\n", - of_node_full_name(np)); + pr_err("%pOF: error reading timing properties\n", np); return -EINVAL; } @@ -110,24 +116,24 @@ static int of_parse_display_timing(const struct device_node *np, * @name: name of the timing node * @dt: display_timing struct to fill **/ -int of_get_display_timing(struct device_node *np, const char *name, +int of_get_display_timing(const struct device_node *np, const char *name, struct display_timing *dt) { struct device_node *timing_np; + int ret; - if (!np) { - pr_err("%s: no devicenode given\n", of_node_full_name(np)); + if (!np) return -EINVAL; - } - timing_np = of_find_node_by_name(np, name); - if (!timing_np) { - pr_err("%s: could not find node '%s'\n", - of_node_full_name(np), name); + timing_np = of_get_child_by_name(np, name); + if (!timing_np) return -ENOENT; - } - return of_parse_display_timing(timing_np, dt); + ret = of_parse_display_timing(timing_np, dt); + + of_node_put(timing_np); + + return ret; } EXPORT_SYMBOL_GPL(of_get_display_timing); @@ -135,60 +141,54 @@ EXPORT_SYMBOL_GPL(of_get_display_timing); * of_get_display_timings - parse all display_timing entries from a device_node * @np: device_node with the subnodes **/ -struct display_timings *of_get_display_timings(struct device_node *np) +struct display_timings *of_get_display_timings(const struct device_node *np) { struct device_node *timings_np; struct device_node *entry; struct device_node *native_mode; struct display_timings *disp; - if (!np) { - pr_err("%s: no devicenode given\n", of_node_full_name(np)); + if (!np) return NULL; - } - timings_np = of_find_node_by_name(np, "display-timings"); + timings_np = of_get_child_by_name(np, "display-timings"); if (!timings_np) { - pr_err("%s: could not find display-timings node\n", - of_node_full_name(np)); + pr_err("%pOF: could not find display-timings node\n", np); return NULL; } disp = kzalloc(sizeof(*disp), GFP_KERNEL); if (!disp) { - pr_err("%s: could not allocate struct disp'\n", - of_node_full_name(np)); + pr_err("%pOF: could not allocate struct disp'\n", np); goto dispfail; } entry = of_parse_phandle(timings_np, "native-mode", 0); /* assume first child as native mode if none provided */ if (!entry) - entry = of_get_next_child(np, NULL); + entry = of_get_next_child(timings_np, NULL); /* if there is no child, it is useless to go on */ if (!entry) { - pr_err("%s: no timing specifications given\n", - of_node_full_name(np)); + pr_err("%pOF: no timing specifications given\n", np); goto entryfail; } - pr_debug("%s: using %s as default timing\n", - of_node_full_name(np), entry->name); + pr_debug("%pOF: using %pOFn as default timing\n", np, entry); native_mode = entry; disp->num_timings = of_get_child_count(timings_np); if (disp->num_timings == 0) { /* should never happen, as entry was already found above */ - pr_err("%s: no timings specified\n", of_node_full_name(np)); + pr_err("%pOF: no timings specified\n", np); goto entryfail; } - disp->timings = kzalloc(sizeof(struct display_timing *) * - disp->num_timings, GFP_KERNEL); + disp->timings = kcalloc(disp->num_timings, + sizeof(struct display_timing *), + GFP_KERNEL); if (!disp->timings) { - pr_err("%s: could not allocate timings array\n", - of_node_full_name(np)); + pr_err("%pOF: could not allocate timings array\n", np); goto entryfail; } @@ -199,10 +199,10 @@ struct display_timings *of_get_display_timings(struct device_node *np) struct display_timing *dt; int r; - dt = kzalloc(sizeof(*dt), GFP_KERNEL); + dt = kmalloc(sizeof(*dt), GFP_KERNEL); if (!dt) { - pr_err("%s: could not allocate display_timing struct\n", - of_node_full_name(np)); + pr_err("%pOF: could not allocate display_timing struct\n", + np); goto timingfail; } @@ -212,8 +212,9 @@ struct display_timings *of_get_display_timings(struct device_node *np) * to not encourage wrong devicetrees, fail in case of * an error */ - pr_err("%s: error in timing %d\n", - of_node_full_name(np), disp->num_timings + 1); + pr_err("%pOF: error in timing %d\n", + np, disp->num_timings + 1); + kfree(dt); goto timingfail; } @@ -230,16 +231,16 @@ struct display_timings *of_get_display_timings(struct device_node *np) */ of_node_put(native_mode); - pr_debug("%s: got %d timings. Using timing #%d as default\n", - of_node_full_name(np), disp->num_timings, + pr_debug("%pOF: got %d timings. Using timing #%d as default\n", + np, disp->num_timings, disp->native_mode + 1); return disp; timingfail: - if (native_mode) - of_node_put(native_mode); + of_node_put(native_mode); display_timings_release(disp); + disp = NULL; entryfail: kfree(disp); dispfail: @@ -247,23 +248,3 @@ dispfail: return NULL; } EXPORT_SYMBOL_GPL(of_get_display_timings); - -/** - * of_display_timings_exist - check if a display-timings node is provided - * @np: device_node with the timing - **/ -int of_display_timings_exist(struct device_node *np) -{ - struct device_node *timings_np; - - if (!np) - return -EINVAL; - - timings_np = of_parse_phandle(np, "display-timings", 0); - if (!timings_np) - return -EINVAL; - - of_node_put(timings_np); - return 1; -} -EXPORT_SYMBOL_GPL(of_display_timings_exist); |
