+static const char *karo_panel_timing_props[] = {
+ "clock-frequency",
+ "hactive",
+ "vactive",
+ "hback-porch",
+ "hsync-len",
+ "hfront-porch",
+ "vback-porch",
+ "vsync-len",
+ "vfront-porch",
+ "hsync-active",
+ "vsync-active",
+ "de-active",
+ "pixelclk-active",
+};
+
+static int karo_fixup_panel_timing(void *fdt, int dest, int src)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(karo_panel_timing_props); i++) {
+ const char *name = karo_panel_timing_props[i];
+ int len;
+ int ret;
+ const void *val;
+ bool restart;
+
+ val = fdt_getprop(fdt, src, name, &len);
+ if (!val) {
+ if (fdt_getprop(fdt, dest, name, NULL)) {
+ printf("Removing '%s' from '%s'\n", name,
+ fdt_get_name(fdt, dest, NULL));
+ fdt_delprop(fdt, dest, name);
+ return -EAGAIN;
+ }
+ continue;
+ }
+ if (len != sizeof(u32)) {
+ printf("Property '%s' has invalid size %u\n",
+ name, len);
+ return -EINVAL;
+ }
+ debug("setting '%s' to <0x%08x>\n", name, be32_to_cpup(val));
+
+ restart = !fdt_getprop(fdt, dest, name, &len);
+ restart |= len != sizeof(u32);
+ /* DTB offsets will change when adding a new property */
+ if (restart) {
+ ret = fdt_increase_size(fdt, len);
+ if (ret) {
+ printf("Failed to increase FDT size by %u: %s\n", len,
+ fdt_strerror(ret));
+ return -ENOMEM;
+ }
+ printf("Adding new property '%s' to '%s'\n",
+ name, fdt_get_name(fdt, dest, NULL));
+ }
+ ret = fdt_setprop_u32(fdt, dest, name, be32_to_cpup(val));
+ if (ret) {
+ printf("Failed to set %s property: %s\n", name,
+ fdt_strerror(ret));
+ return -EINVAL;
+ }
+ if (restart)
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+int karo_fdt_update_fb_mode(void *blob, const char *name,
+ const char *panel_name)