static struct device_node *kirin_get_remote_node(struct device_node *np) { struct device_node *endpoint, *remote; /* get the first endpoint, in our case only one remote node * is connected to display controller. */ endpoint = of_graph_get_next_endpoint(np, NULL); if (!endpoint) { DRM_ERROR("no valid endpoint node\n"); return ERR_PTR(-ENODEV); } remote = of_graph_get_remote_port_parent(endpoint); of_node_put(endpoint); if (!remote) { DRM_ERROR("no valid remote node\n"); return ERR_PTR(-ENODEV); } if (!of_device_is_available(remote)) { DRM_ERROR("not available for remote node\n"); return ERR_PTR(-ENODEV); } return remote; }
/* Walks the OF graph to find the panel node and then asks DRM to look * up the panel. */ static struct drm_panel *pl111_get_panel(struct device *dev) { struct device_node *endpoint, *panel_node; struct device_node *np = dev->of_node; struct drm_panel *panel; endpoint = of_graph_get_next_endpoint(np, NULL); if (!endpoint) { dev_err(dev, "no endpoint to fetch panel\n"); return NULL; } /* don't proceed if we have an endpoint but no panel_node tied to it */ panel_node = of_graph_get_remote_port_parent(endpoint); of_node_put(endpoint); if (!panel_node) { dev_err(dev, "no valid panel node\n"); return NULL; } panel = of_drm_find_panel(panel_node); of_node_put(panel_node); return panel; }
static int malidp_platform_probe(struct platform_device *pdev) { struct device_node *port, *ep; struct component_match *match = NULL; if (!pdev->dev.of_node) return -ENODEV; /* there is only one output port inside each device, find it */ ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); if (!ep) return -ENODEV; if (!of_device_is_available(ep)) { of_node_put(ep); return -ENODEV; } /* add the remote encoder port as component */ port = of_graph_get_remote_port_parent(ep); of_node_put(ep); if (!port || !of_device_is_available(port)) { of_node_put(port); return -EAGAIN; } component_match_add(&pdev->dev, &match, malidp_compare_dev, port); return component_master_add_with_match(&pdev->dev, &malidp_master_ops, match); }
int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev) { struct of_endpoint ep; struct device_node *ep_node, *panel_node; int ret; /* This is for backward compatibility */ panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0); if (panel_node) { fsl_dev->connector.panel = of_drm_find_panel(panel_node); of_node_put(panel_node); if (!fsl_dev->connector.panel) return -EPROBE_DEFER; return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); } ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL); if (!ep_node) return -ENODEV; ret = of_graph_parse_endpoint(ep_node, &ep); of_node_put(ep_node); if (ret) return -ENODEV; return fsl_dcu_attach_endpoint(fsl_dev, &ep); }
static inline int of_coresight_count_ports(struct device_node *port_parent) { int i = 0; struct device_node *ep = NULL; while ((ep = of_graph_get_next_endpoint(port_parent, ep))) i++; return i; }
static int exynos_dp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = NULL, *endpoint = NULL; struct exynos_dp_device *dp; dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), GFP_KERNEL); if (!dp) return -ENOMEM; /* * We just use the drvdata until driver run into component * add function, and then we would set drvdata to null, so * that analogix dp driver would take charge of the drvdata. */ platform_set_drvdata(pdev, dp); /* This is for the backward compatibility. */ np = of_parse_phandle(dev->of_node, "panel", 0); if (np) { dp->plat_data.panel = of_drm_find_panel(np); of_node_put(np); if (!dp->plat_data.panel) return -EPROBE_DEFER; goto out; } endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); if (endpoint) { np = of_graph_get_remote_port_parent(endpoint); if (np) { /* The remote port can be either a panel or a bridge */ dp->plat_data.panel = of_drm_find_panel(np); if (!dp->plat_data.panel) { dp->ptn_bridge = of_drm_find_bridge(np); if (!dp->ptn_bridge) { of_node_put(np); return -EPROBE_DEFER; } } of_node_put(np); } else { DRM_ERROR("no remote endpoint device node found.\n"); return -EINVAL; } } else { DRM_ERROR("no port endpoint subnode found.\n"); return -EINVAL; } out: return component_add(&pdev->dev, &exynos_dp_ops); }
static int exynos_dp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *panel_node, *bridge_node, *endpoint; struct exynos_dp_device *dp; int ret; dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), GFP_KERNEL); if (!dp) return -ENOMEM; dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; dp->display.ops = &exynos_dp_display_ops; platform_set_drvdata(pdev, dp); ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR, dp->display.type); if (ret) return ret; panel_node = of_parse_phandle(dev->of_node, "panel", 0); if (panel_node) { dp->panel = of_drm_find_panel(panel_node); of_node_put(panel_node); if (!dp->panel) return -EPROBE_DEFER; } endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); if (endpoint) { bridge_node = of_graph_get_remote_port_parent(endpoint); if (bridge_node) { dp->bridge = of_drm_find_bridge(bridge_node); of_node_put(bridge_node); if (!dp->bridge) return -EPROBE_DEFER; } else return -EPROBE_DEFER; } ret = component_add(&pdev->dev, &exynos_dp_ops); if (ret) exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR); return ret; }
static struct device_node *tilcdc_get_remote_node(struct device_node *node) { struct device_node *ep; struct device_node *parent; if (!tilcdc_node_has_port(node)) return NULL; ep = of_graph_get_next_endpoint(node, NULL); if (!ep) return NULL; parent = of_graph_get_remote_port_parent(ep); of_node_put(ep); return parent; }
static int rvin_parse_dt(struct rvin_dev *vin) { const struct of_device_id *match; struct v4l2_of_endpoint ep; struct device_node *np; int ret; match = of_match_device(of_match_ptr(rvin_of_id_table), vin->dev); if (!match) return -ENODEV; vin->chip = (enum chip_id)match->data; np = of_graph_get_next_endpoint(vin->dev->of_node, NULL); if (!np) { vin_err(vin, "Could not find endpoint\n"); return -EINVAL; } ret = v4l2_of_parse_endpoint(np, &ep); if (ret) { vin_err(vin, "Could not parse endpoint\n"); return ret; } of_node_put(np); vin->mbus_cfg.type = ep.bus_type; switch (vin->mbus_cfg.type) { case V4L2_MBUS_PARALLEL: vin->mbus_cfg.flags = ep.bus.parallel.flags; break; case V4L2_MBUS_BT656: vin->mbus_cfg.flags = 0; break; default: vin_err(vin, "Unknown media bus type\n"); return -EINVAL; } return 0; }
static int rvin_graph_parse(struct rvin_dev *vin, struct device_node *node) { struct device_node *remote; struct device_node *ep = NULL; struct device_node *next; int ret = 0; while (1) { next = of_graph_get_next_endpoint(node, ep); if (!next) break; of_node_put(ep); ep = next; remote = of_graph_get_remote_port_parent(ep); if (!remote) { ret = -EINVAL; break; } /* Skip entities that we have already processed. */ if (remote == vin->dev->of_node) { of_node_put(remote); continue; } /* Remote node to connect */ if (!vin->entity.node) { vin->entity.node = remote; vin->entity.asd.match_type = V4L2_ASYNC_MATCH_OF; vin->entity.asd.match.of.node = remote; ret++; } } of_node_put(ep); return ret; }
static void of_coresight_get_ports(struct device_node *node, int *nr_inport, int *nr_outport) { struct device_node *ep = NULL; int in = 0, out = 0; do { ep = of_graph_get_next_endpoint(node, ep); if (!ep) break; if (of_property_read_bool(ep, "slave-mode")) in++; else out++; } while (ep); *nr_inport = in; *nr_outport = out; }
static void of_coresight_get_ports_legacy(const struct device_node *node, int *nr_inport, int *nr_outport) { struct device_node *ep = NULL; int in = 0, out = 0; do { ep = of_graph_get_next_endpoint(node, ep); if (!ep) break; if (of_coresight_legacy_ep_is_input(ep)) in++; else out++; } while (ep); *nr_inport = in; *nr_outport = out; }
static struct device_node *mdp4_detect_lcdc_panel(struct drm_device *dev) { struct device_node *endpoint, *panel_node; struct device_node *np = dev->dev->of_node; endpoint = of_graph_get_next_endpoint(np, NULL); if (!endpoint) { DBG("no endpoint in MDP4 to fetch LVDS panel\n"); return NULL; } /* don't proceed if we have an endpoint but no panel_node tied to it */ panel_node = of_graph_get_remote_port_parent(endpoint); if (!panel_node) { dev_err(dev->dev, "no valid panel node\n"); of_node_put(endpoint); return ERR_PTR(-ENODEV); } of_node_put(endpoint); return panel_node; }
int tilcdc_get_external_components(struct device *dev, struct component_match **match) { struct device_node *node; struct device_node *ep = NULL; int count = 0; int ret = 0; if (!tilcdc_node_has_port(dev->of_node)) return 0; while ((ep = of_graph_get_next_endpoint(dev->of_node, ep))) { node = of_graph_get_remote_port_parent(ep); if (!node || !of_device_is_available(node)) { of_node_put(node); continue; } dev_dbg(dev, "Subdevice node '%s' found\n", node->name); if (of_device_is_compatible(node, "nxp,tda998x")) { if (match) drm_of_component_match_add(dev, match, dev_match_of, node); ret = 1; } of_node_put(node); if (count++ > 1) { dev_err(dev, "Only one port is supported\n"); return -EINVAL; } } return ret; }
struct coresight_platform_data *of_get_coresight_platform_data( struct device *dev, struct device_node *node) { int i = 0, ret = 0, cpu; struct coresight_platform_data *pdata; struct of_endpoint endpoint, rendpoint; struct device *rdev; struct device_node *dn; struct device_node *ep = NULL; struct device_node *rparent = NULL; struct device_node *rport = NULL; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return ERR_PTR(-ENOMEM); /* Use device name as sysfs handle */ pdata->name = dev_name(dev); /* Get the number of input and output port for this component */ of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport); if (pdata->nr_outport) { ret = of_coresight_alloc_memory(dev, pdata); if (ret) return ERR_PTR(ret); /* Iterate through each port to discover topology */ do { /* Get a handle on a port */ ep = of_graph_get_next_endpoint(node, ep); if (!ep) break; /* * No need to deal with input ports, processing for as * processing for output ports will deal with them. */ if (of_find_property(ep, "slave-mode", NULL)) continue; /* Get a handle on the local endpoint */ ret = of_graph_parse_endpoint(ep, &endpoint); if (ret) continue; /* The local out port number */ pdata->outports[i] = endpoint.id; /* * Get a handle on the remote port and parent * attached to it. */ rparent = of_graph_get_remote_port_parent(ep); rport = of_graph_get_remote_port(ep); if (!rparent || !rport) continue; if (of_graph_parse_endpoint(rport, &rendpoint)) continue; rdev = of_coresight_get_endpoint_device(rparent); if (!rdev) continue; pdata->child_names[i] = dev_name(rdev); pdata->child_ports[i] = rendpoint.id; i++; } while (ep); } /* Affinity defaults to CPU0 */ pdata->cpu = 0; dn = of_parse_phandle(node, "cpu", 0); for (cpu = 0; dn && cpu < nr_cpu_ids; cpu++) { if (dn == of_get_cpu_node(cpu, NULL)) { pdata->cpu = cpu; break; } } return pdata; }
static int pl111_init_clock_divider(struct drm_device *drm) { struct pl111_drm_dev_private *priv = drm->dev_private; struct clk *parent = devm_clk_get(drm->dev, "clcdclk"); struct clk_hw *div = &priv->clk_div; const char *parent_name; struct clk_init_data init = { .name = "pl111_div", .ops = &pl111_clk_div_ops, .parent_names = &parent_name, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }; int ret; if (IS_ERR(parent)) { dev_err(drm->dev, "CLCD: unable to get clcdclk.\n"); return PTR_ERR(parent); } /* If the clock divider is broken, use the parent directly */ if (priv->variant->broken_clockdivider) { priv->clk = parent; return 0; } parent_name = __clk_get_name(parent); spin_lock_init(&priv->tim2_lock); div->init = &init; ret = devm_clk_hw_register(drm->dev, div); priv->clk = div->clk; return ret; } int pl111_display_init(struct drm_device *drm) { struct pl111_drm_dev_private *priv = drm->dev_private; struct device *dev = drm->dev; struct device_node *endpoint; u32 tft_r0b0g0[3]; int ret; endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); if (!endpoint) return -ENODEV; if (of_property_read_u32_array(endpoint, "arm,pl11x,tft-r0g0b0-pads", tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0) { dev_err(dev, "arm,pl11x,tft-r0g0b0-pads should be 3 ints\n"); of_node_put(endpoint); return -ENOENT; } of_node_put(endpoint); ret = pl111_init_clock_divider(drm); if (ret) return ret; if (!priv->variant->broken_vblank) { pl111_display_funcs.enable_vblank = pl111_display_enable_vblank; pl111_display_funcs.disable_vblank = pl111_display_disable_vblank; } ret = drm_simple_display_pipe_init(drm, &priv->pipe, &pl111_display_funcs, priv->variant->formats, priv->variant->nformats, NULL, priv->connector); if (ret) return ret; return 0; }
static int vpif_probe(struct platform_device *pdev) { static struct resource *res, *res_irq; struct platform_device *pdev_capture, *pdev_display; struct device_node *endpoint = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); vpif_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(vpif_base)) return PTR_ERR(vpif_base); pm_runtime_enable(&pdev->dev); pm_runtime_get(&pdev->dev); spin_lock_init(&vpif_lock); dev_info(&pdev->dev, "vpif probe success\n"); /* * If VPIF Node has endpoints, assume "new" DT support, * where capture and display drivers don't have DT nodes * so their devices need to be registered manually here * for their legacy platform_drivers to work. */ endpoint = of_graph_get_next_endpoint(pdev->dev.of_node, endpoint); if (!endpoint) return 0; /* * For DT platforms, manually create platform_devices for * capture/display drivers. */ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res_irq) { dev_warn(&pdev->dev, "Missing IRQ resource.\n"); return -EINVAL; } pdev_capture = devm_kzalloc(&pdev->dev, sizeof(*pdev_capture), GFP_KERNEL); if (pdev_capture) { pdev_capture->name = "vpif_capture"; pdev_capture->id = -1; pdev_capture->resource = res_irq; pdev_capture->num_resources = 1; pdev_capture->dev.dma_mask = pdev->dev.dma_mask; pdev_capture->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; pdev_capture->dev.parent = &pdev->dev; platform_device_register(pdev_capture); } else { dev_warn(&pdev->dev, "Unable to allocate memory for pdev_capture.\n"); } pdev_display = devm_kzalloc(&pdev->dev, sizeof(*pdev_display), GFP_KERNEL); if (pdev_display) { pdev_display->name = "vpif_display"; pdev_display->id = -1; pdev_display->resource = res_irq; pdev_display->num_resources = 1; pdev_display->dev.dma_mask = pdev->dev.dma_mask; pdev_display->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; pdev_display->dev.parent = &pdev->dev; platform_device_register(pdev_display); } else { dev_warn(&pdev->dev, "Unable to allocate memory for pdev_display.\n"); } return 0; }
static int malidp_bind(struct device *dev) { struct resource *res; struct drm_device *drm; struct device_node *ep; struct malidp_drm *malidp; struct malidp_hw_device *hwdev; struct platform_device *pdev = to_platform_device(dev); /* number of lines for the R, G and B output */ u8 output_width[MAX_OUTPUT_CHANNELS]; int ret = 0, i; u32 version, out_depth = 0; malidp = devm_kzalloc(dev, sizeof(*malidp), GFP_KERNEL); if (!malidp) return -ENOMEM; hwdev = devm_kzalloc(dev, sizeof(*hwdev), GFP_KERNEL); if (!hwdev) return -ENOMEM; /* * copy the associated data from malidp_drm_of_match to avoid * having to keep a reference to the OF node after binding */ memcpy(hwdev, of_device_get_match_data(dev), sizeof(*hwdev)); malidp->dev = hwdev; INIT_LIST_HEAD(&malidp->event_list); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hwdev->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hwdev->regs)) return PTR_ERR(hwdev->regs); hwdev->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(hwdev->pclk)) return PTR_ERR(hwdev->pclk); hwdev->aclk = devm_clk_get(dev, "aclk"); if (IS_ERR(hwdev->aclk)) return PTR_ERR(hwdev->aclk); hwdev->mclk = devm_clk_get(dev, "mclk"); if (IS_ERR(hwdev->mclk)) return PTR_ERR(hwdev->mclk); hwdev->pxlclk = devm_clk_get(dev, "pxlclk"); if (IS_ERR(hwdev->pxlclk)) return PTR_ERR(hwdev->pxlclk); /* Get the optional framebuffer memory resource */ ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) return ret; drm = drm_dev_alloc(&malidp_driver, dev); if (IS_ERR(drm)) { ret = PTR_ERR(drm); goto alloc_fail; } /* Enable APB clock in order to get access to the registers */ clk_prepare_enable(hwdev->pclk); /* * Enable AXI clock and main clock so that prefetch can start once * the registers are set */ clk_prepare_enable(hwdev->aclk); clk_prepare_enable(hwdev->mclk); ret = hwdev->query_hw(hwdev); if (ret) { DRM_ERROR("Invalid HW configuration\n"); goto query_hw_fail; } version = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_DE_CORE_ID); DRM_INFO("found ARM Mali-DP%3x version r%dp%d\n", version >> 16, (version >> 12) & 0xf, (version >> 8) & 0xf); /* set the number of lines used for output of RGB data */ ret = of_property_read_u8_array(dev->of_node, "arm,malidp-output-port-lines", output_width, MAX_OUTPUT_CHANNELS); if (ret) goto query_hw_fail; for (i = 0; i < MAX_OUTPUT_CHANNELS; i++) out_depth = (out_depth << 8) | (output_width[i] & 0xf); malidp_hw_write(hwdev, out_depth, hwdev->map.out_depth_base); drm->dev_private = malidp; dev_set_drvdata(dev, drm); atomic_set(&malidp->config_valid, 0); init_waitqueue_head(&malidp->wq); ret = malidp_init(drm); if (ret < 0) goto init_fail; ret = drm_dev_register(drm, 0); if (ret) goto register_fail; /* Set the CRTC's port so that the encoder component can find it */ ep = of_graph_get_next_endpoint(dev->of_node, NULL); if (!ep) { ret = -EINVAL; goto port_fail; } malidp->crtc.port = of_get_next_parent(ep); ret = component_bind_all(dev, drm); if (ret) { DRM_ERROR("Failed to bind all components\n"); goto bind_fail; } ret = malidp_irq_init(pdev); if (ret < 0) goto irq_init_fail; ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) { DRM_ERROR("failed to initialise vblank\n"); goto vblank_fail; } drm_mode_config_reset(drm); malidp->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, drm->mode_config.num_connector); if (IS_ERR(malidp->fbdev)) { ret = PTR_ERR(malidp->fbdev); malidp->fbdev = NULL; goto fbdev_fail; } drm_kms_helper_poll_init(drm); return 0; fbdev_fail: drm_vblank_cleanup(drm); vblank_fail: malidp_se_irq_fini(drm); malidp_de_irq_fini(drm); irq_init_fail: component_unbind_all(dev, drm); bind_fail: of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; port_fail: drm_dev_unregister(drm); register_fail: malidp_de_planes_destroy(drm); drm_mode_config_cleanup(drm); init_fail: drm->dev_private = NULL; dev_set_drvdata(dev, NULL); query_hw_fail: clk_disable_unprepare(hwdev->mclk); clk_disable_unprepare(hwdev->aclk); clk_disable_unprepare(hwdev->pclk); drm_dev_unref(drm); alloc_fail: of_reserved_mem_device_release(dev); return ret; }
struct coresight_platform_data * of_get_coresight_platform_data(struct device *dev, const struct device_node *node) { int ret = 0; struct coresight_platform_data *pdata; struct coresight_connection *conn; struct device_node *ep = NULL; const struct device_node *parent = NULL; bool legacy_binding = false; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return ERR_PTR(-ENOMEM); /* Use device name as sysfs handle */ pdata->name = dev_name(dev); pdata->cpu = of_coresight_get_cpu(node); /* Get the number of input and output port for this component */ of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport); /* If there are no output connections, we are done */ if (!pdata->nr_outport) return pdata; ret = of_coresight_alloc_memory(dev, pdata); if (ret) return ERR_PTR(ret); parent = of_coresight_get_output_ports_node(node); /* * If the DT uses obsoleted bindings, the ports are listed * under the device and we need to filter out the input * ports. */ if (!parent) { legacy_binding = true; parent = node; dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n"); } conn = pdata->conns; /* Iterate through each output port to discover topology */ while ((ep = of_graph_get_next_endpoint(parent, ep))) { /* * Legacy binding mixes input/output ports under the * same parent. So, skip the input ports if we are dealing * with legacy binding, as they processed with their * connected output ports. */ if (legacy_binding && of_coresight_legacy_ep_is_input(ep)) continue; ret = of_coresight_parse_endpoint(dev, ep, conn); switch (ret) { case 1: conn++; /* Fall through */ case 0: break; default: return ERR_PTR(ret); } } return pdata; }
static int exynos_dp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = NULL, *endpoint = NULL; struct exynos_dp_device *dp; int ret; dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), GFP_KERNEL); if (!dp) return -ENOMEM; platform_set_drvdata(pdev, dp); /* This is for the backward compatibility. */ np = of_parse_phandle(dev->of_node, "panel", 0); if (np) { dp->panel = of_drm_find_panel(np); of_node_put(np); if (!dp->panel) return -EPROBE_DEFER; goto out; } endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); if (endpoint) { np = of_graph_get_remote_port_parent(endpoint); if (np) { /* The remote port can be either a panel or a bridge */ dp->panel = of_drm_find_panel(np); if (!dp->panel) { dp->ptn_bridge = of_drm_find_bridge(np); if (!dp->ptn_bridge) { of_node_put(np); return -EPROBE_DEFER; } } of_node_put(np); } else { DRM_ERROR("no remote endpoint device node found.\n"); return -EINVAL; } } else { DRM_ERROR("no port endpoint subnode found.\n"); return -EINVAL; } out: pm_runtime_enable(dev); ret = component_add(&pdev->dev, &exynos_dp_ops); if (ret) goto err_disable_pm_runtime; return ret; err_disable_pm_runtime: pm_runtime_disable(dev); return ret; }