--- zzzz-none-000/linux-3.10.107/drivers/video/of_display_timing.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/video/of_display_timing.c 2021-02-04 17:41:59.000000000 +0000 @@ -23,7 +23,7 @@ * Every display_timing can be specified with either just the typical value or * a range consisting of min/typ/max. This function helps handling this **/ -static int parse_timing_property(struct device_node *np, const char *name, +static int parse_timing_property(const struct device_node *np, const char *name, struct timing_entry *result) { struct property *prop; @@ -53,21 +53,16 @@ } /** - * of_get_display_timing - parse display_timing entry from device_node + * of_parse_display_timing - parse display_timing entry from device_node * @np: device_node with the properties **/ -static struct display_timing *of_get_display_timing(struct device_node *np) +static int of_parse_display_timing(const struct device_node *np, + struct display_timing *dt) { - struct display_timing *dt; u32 val = 0; int ret = 0; - dt = kzalloc(sizeof(*dt), GFP_KERNEL); - if (!dt) { - pr_err("%s: could not allocate display_timing struct\n", - of_node_full_name(np)); - return NULL; - } + memset(dt, 0, sizeof(*dt)); ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch); ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch); @@ -97,18 +92,44 @@ dt->flags |= DISPLAY_FLAGS_INTERLACED; if (of_property_read_bool(np, "doublescan")) dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; + if (of_property_read_bool(np, "doubleclk")) + dt->flags |= DISPLAY_FLAGS_DOUBLECLK; if (ret) { pr_err("%s: error reading timing properties\n", of_node_full_name(np)); - kfree(dt); - return NULL; + return -EINVAL; } - return dt; + return 0; } /** + * of_get_display_timing - parse a display_timing entry + * @np: device_node with the timing subnode + * @name: name of the timing node + * @dt: display_timing struct to fill + **/ +int of_get_display_timing(struct device_node *np, const char *name, + struct display_timing *dt) +{ + struct device_node *timing_np; + + if (!np) + return -EINVAL; + + timing_np = of_get_child_by_name(np, name); + if (!timing_np) { + pr_err("%s: could not find node '%s'\n", + of_node_full_name(np), name); + return -ENOENT; + } + + return of_parse_display_timing(timing_np, dt); +} +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 **/ @@ -119,12 +140,10 @@ 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)); @@ -141,7 +160,7 @@ 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", @@ -174,15 +193,24 @@ for_each_child_of_node(timings_np, entry) { struct display_timing *dt; + int r; - dt = of_get_display_timing(entry); + dt = kzalloc(sizeof(*dt), GFP_KERNEL); if (!dt) { + pr_err("%s: could not allocate display_timing struct\n", + of_node_full_name(np)); + goto timingfail; + } + + r = of_parse_display_timing(entry, dt); + if (r) { /* * 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); + kfree(dt); goto timingfail; } @@ -206,9 +234,9 @@ 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: