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; struct exynos_dp_device *dp; int ret; ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR, exynos_dp_display.type); if (ret) return ret; dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), GFP_KERNEL); if (!dp) return -ENOMEM; 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; } exynos_dp_display.ctx = dp; ret = component_add(&pdev->dev, &exynos_dp_ops); if (ret) exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR); return ret; }
/* 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; }
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 int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct dw_mipi_dsi *dsi = host_to_dsi(host); if (device->lanes > dsi->pdata->max_data_lanes) { dev_err(dsi->dev, "the number of data lanes(%u) is too many\n", device->lanes); return -EINVAL; } if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) || !(device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) { dev_err(dsi->dev, "device mode is unsupported\n"); return -EINVAL; } dsi->lanes = device->lanes; dsi->channel = device->channel; dsi->format = device->format; dsi->panel = of_drm_find_panel(device->dev.of_node); if (dsi->panel) return drm_panel_attach(dsi->panel, &dsi->connector); return -EINVAL; }
static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); unsigned long pc = mdp4_lcdc_encoder->pixclock; struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel; uint32_t config; int i, ret; if (WARN_ON(mdp4_lcdc_encoder->enabled)) return; /* TODO: hard-coded for 18bpp: */ config = MDP4_DMA_CONFIG_R_BPC(BPC6) | MDP4_DMA_CONFIG_G_BPC(BPC6) | MDP4_DMA_CONFIG_B_BPC(BPC6) | MDP4_DMA_CONFIG_PACK(0x21) | MDP4_DMA_CONFIG_DEFLKR_EN | MDP4_DMA_CONFIG_DITHER_EN; if (!of_property_read_bool(dev->dev->of_node, "qcom,lcdc-align-lsb")) config |= MDP4_DMA_CONFIG_PACK_ALIGN_MSB; mdp4_crtc_set_config(encoder->crtc, config); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); bs_set(mdp4_lcdc_encoder, 1); for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable regulator: %d\n", ret); } DBG("setting lcdc_clk=%lu", pc); ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); if (ret) DRM_DEV_ERROR(dev->dev, "failed to configure lcdc_clk: %d\n", ret); ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk); if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret); panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); if (!IS_ERR(panel)) { drm_panel_prepare(panel); drm_panel_enable(panel); } setup_phy(encoder); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); mdp4_lcdc_encoder->enabled = true; }
static int imx_pd_bind(struct device *dev, struct device *master, void *data) { struct drm_device *drm = data; struct device_node *np = dev->of_node; struct device_node *port; const u8 *edidp; struct imx_parallel_display *imxpd; int ret; const char *fmt; imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL); if (!imxpd) return -ENOMEM; edidp = of_get_property(np, "edid", &imxpd->edid_len); if (edidp) imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL); ret = of_property_read_string(np, "interface-pix-fmt", &fmt); if (!ret) { if (!strcmp(fmt, "rgb24")) imxpd->bus_format = MEDIA_BUS_FMT_RGB888_1X24; else if (!strcmp(fmt, "rgb565")) imxpd->bus_format = MEDIA_BUS_FMT_RGB565_1X16; else if (!strcmp(fmt, "bgr666")) imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X18; else if (!strcmp(fmt, "lvds666")) imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; } /* port@1 is the output port */ port = of_graph_get_port_by_id(np, 1); if (port) { struct device_node *endpoint, *remote; endpoint = of_get_child_by_name(port, "endpoint"); if (endpoint) { remote = of_graph_get_remote_port_parent(endpoint); if (remote) imxpd->panel = of_drm_find_panel(remote); if (!imxpd->panel) return -EPROBE_DEFER; } } imxpd->dev = dev; ret = imx_pd_register(drm, imxpd); if (ret) return ret; dev_set_drvdata(dev, imxpd); return 0; }
static int rockchip_dp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *panel_node, *port, *endpoint; struct rockchip_dp_device *dp; struct drm_panel *panel; port = of_graph_get_port_by_id(dev->of_node, 1); if (!port) { dev_err(dev, "can't find output port\n"); return -EINVAL; } endpoint = of_get_child_by_name(port, "endpoint"); of_node_put(port); if (!endpoint) { dev_err(dev, "no output endpoint found\n"); return -EINVAL; } panel_node = of_graph_get_remote_port_parent(endpoint); of_node_put(endpoint); if (!panel_node) { dev_err(dev, "no output node found\n"); return -EINVAL; } panel = of_drm_find_panel(panel_node); if (!panel) { DRM_ERROR("failed to find panel\n"); of_node_put(panel_node); return -EPROBE_DEFER; } of_node_put(panel_node); dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); if (!dp) return -ENOMEM; dp->dev = dev; dp->plat_data.panel = panel; /* * 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 could take charge of the drvdata. */ platform_set_drvdata(pdev, dp); return component_add(dev, &rockchip_dp_component_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 enum drm_connector_status mdp4_lvds_connector_detect( struct drm_connector *connector, bool force) { struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector); if (!mdp4_lvds_connector->panel) { mdp4_lvds_connector->panel = of_drm_find_panel(mdp4_lvds_connector->panel_node); if (IS_ERR(mdp4_lvds_connector->panel)) mdp4_lvds_connector->panel = NULL; } return mdp4_lvds_connector->panel ? connector_status_connected : connector_status_disconnected; }
static int imx_pd_bind(struct device *dev, struct device *master, void *data) { struct drm_device *drm = data; struct device_node *np = dev->of_node; struct device_node *panel_node; const u8 *edidp; struct imx_parallel_display *imxpd; int ret; const char *fmt; imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL); if (!imxpd) return -ENOMEM; edidp = of_get_property(np, "edid", &imxpd->edid_len); if (edidp) imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL); ret = of_property_read_string(np, "interface-pix-fmt", &fmt); if (!ret) { if (!strcmp(fmt, "rgb24")) imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB24; else if (!strcmp(fmt, "rgb565")) imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565; else if (!strcmp(fmt, "bgr666")) imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666; else if (!strcmp(fmt, "lvds666")) imxpd->interface_pix_fmt = v4l2_fourcc('L', 'V', 'D', '6'); } panel_node = of_parse_phandle(np, "fsl,panel", 0); if (panel_node) imxpd->panel = of_drm_find_panel(panel_node); imxpd->dev = dev; ret = imx_pd_register(drm, imxpd); if (ret) return ret; dev_set_drvdata(dev, imxpd); return 0; }
static int exynos_dp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np; struct exynos_dp_device *dp; struct drm_panel *panel; struct drm_bridge *bridge; int ret; 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 (IS_ERR(dp->plat_data.panel)) return PTR_ERR(dp->plat_data.panel); goto out; } ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge); if (ret) return ret; /* The remote port can be either a panel or a bridge */ dp->plat_data.panel = panel; dp->plat_data.skip_connector = !!bridge; dp->ptn_bridge = bridge; out: return component_add(&pdev->dev, &exynos_dp_ops); }
static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel; int i, ret; if (WARN_ON(!mdp4_lcdc_encoder->enabled)) return; mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); if (!IS_ERR(panel)) { drm_panel_disable(panel); drm_panel_unprepare(panel); } /* * Wait for a vsync so we know the ENABLE=0 latched before * the (connector) source of the vsync's gets disabled, * otherwise we end up in a funny state if we re-enable * before the disable latches, which results that some of * the settings changes for the new modeset (like new * scanout buffer) don't latch properly.. */ mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC); clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk); for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_disable(mdp4_lcdc_encoder->regs[i]); if (ret) DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret); } bs_set(mdp4_lcdc_encoder, 0); mdp4_lcdc_encoder->enabled = false; }
static enum drm_connector_status exynos_dpi_detect(struct drm_connector *connector, bool force) { struct exynos_dpi *ctx = connector_to_dpi(connector); /* panels supported only by boot-loader are always connected */ if (!ctx->panel_node) return connector_status_connected; if (!ctx->panel) { ctx->panel = of_drm_find_panel(ctx->panel_node); if (ctx->panel) drm_panel_attach(ctx->panel, &ctx->connector); } if (ctx->panel) return connector_status_connected; return connector_status_disconnected; }
static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct dw_mipi_dsi *dsi = host_to_dsi(host); if (device->lanes > dsi->pdata->max_data_lanes) { DRM_DEV_ERROR(dsi->dev, "the number of data lanes(%u) is too many\n", device->lanes); return -EINVAL; } dsi->lanes = device->lanes; dsi->channel = device->channel; dsi->format = device->format; dsi->mode_flags = device->mode_flags; dsi->panel = of_drm_find_panel(device->dev.of_node); if (dsi->panel) return drm_panel_attach(dsi->panel, &dsi->connector); return -EINVAL; }
static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev, const struct of_endpoint *ep) { struct drm_bridge *bridge; struct device_node *np; np = of_graph_get_remote_port_parent(ep->local_node); fsl_dev->connector.panel = of_drm_find_panel(np); if (fsl_dev->connector.panel) { of_node_put(np); return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); } bridge = of_drm_find_bridge(np); of_node_put(np); if (!bridge) return -ENODEV; fsl_dev->encoder.bridge = bridge; bridge->encoder = &fsl_dev->encoder; return drm_bridge_attach(fsl_dev->drm, bridge); }
static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) { struct device_node *local_output = NULL; struct device_node *remote_input = NULL; struct device_node *remote = NULL; struct device_node *node; bool is_bridge = false; int ret = 0; local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0); if (!local_output) { dev_dbg(lvds->dev, "unconnected port@1\n"); return -ENODEV; } /* * Locate the connected entity and infer its type from the number of * endpoints. */ remote = of_graph_get_remote_port_parent(local_output); if (!remote) { dev_dbg(lvds->dev, "unconnected endpoint %pOF\n", local_output); ret = -ENODEV; goto done; } if (!of_device_is_available(remote)) { dev_dbg(lvds->dev, "connected entity %pOF is disabled\n", remote); ret = -ENODEV; goto done; } remote_input = of_graph_get_remote_endpoint(local_output); for_each_endpoint_of_node(remote, node) { if (node != remote_input) { /* * We've found one endpoint other than the input, this * must be a bridge. */ is_bridge = true; of_node_put(node); break; } } if (is_bridge) { lvds->next_bridge = of_drm_find_bridge(remote); if (!lvds->next_bridge) ret = -EPROBE_DEFER; } else { lvds->panel = of_drm_find_panel(remote); if (!lvds->panel) ret = -EPROBE_DEFER; } done: of_node_put(local_output); of_node_put(remote_input); of_node_put(remote); return ret; }
static int imx_ldb_bind(struct device *dev, struct device *master, void *data) { struct drm_device *drm = data; struct device_node *np = dev->of_node; const struct of_device_id *of_id = of_match_device(imx_ldb_dt_ids, dev); struct device_node *child; const u8 *edidp; struct imx_ldb *imx_ldb; int datawidth; int mapping; int dual; int ret; int i; imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL); if (!imx_ldb) return -ENOMEM; imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); if (IS_ERR(imx_ldb->regmap)) { dev_err(dev, "failed to get parent regmap\n"); return PTR_ERR(imx_ldb->regmap); } imx_ldb->dev = dev; if (of_id) imx_ldb->lvds_mux = of_id->data; dual = of_property_read_bool(np, "fsl,dual-channel"); if (dual) imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN; /* * There are three different possible clock mux configurations: * i.MX53: ipu1_di0_sel, ipu1_di1_sel * i.MX6q: ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel * Map them all to di0_sel...di3_sel. */ for (i = 0; i < 4; i++) { char clkname[16]; sprintf(clkname, "di%d_sel", i); imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname); if (IS_ERR(imx_ldb->clk_sel[i])) { ret = PTR_ERR(imx_ldb->clk_sel[i]); imx_ldb->clk_sel[i] = NULL; break; } } if (i == 0) return ret; for_each_child_of_node(np, child) { struct imx_ldb_channel *channel; struct device_node *panel_node; ret = of_property_read_u32(child, "reg", &i); if (ret || i < 0 || i > 1) return -EINVAL; if (dual && i > 0) { dev_warn(dev, "dual-channel mode, ignoring second output\n"); continue; } if (!of_device_is_available(child)) continue; channel = &imx_ldb->channel[i]; channel->ldb = imx_ldb; channel->chno = i; channel->child = child; edidp = of_get_property(child, "edid", &channel->edid_len); if (edidp) { channel->edid = kmemdup(edidp, channel->edid_len, GFP_KERNEL); } else { ret = of_get_drm_display_mode(child, &channel->mode, 0); if (!ret) channel->mode_valid = 1; } ret = of_property_read_u32(child, "fsl,data-width", &datawidth); if (ret) datawidth = 0; else if (datawidth != 18 && datawidth != 24) return -EINVAL; mapping = of_get_data_mapping(child); switch (mapping) { case LVDS_BIT_MAP_SPWG: if (datawidth == 24) { if (i == 0 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24; if (i == 1 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24; } break; case LVDS_BIT_MAP_JEIDA: if (datawidth == 18) { dev_err(dev, "JEIDA standard only supported in 24 bit\n"); return -EINVAL; } if (i == 0 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | LDB_BIT_MAP_CH0_JEIDA; if (i == 1 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA; break; default: dev_err(dev, "data mapping not specified or invalid\n"); return -EINVAL; } panel_node = of_parse_phandle(child, "fsl,panel", 0); if (panel_node) channel->panel = of_drm_find_panel(panel_node); ret = imx_ldb_register(drm, channel); if (ret) return ret; } dev_set_drvdata(dev, imx_ldb); return 0; }
int tegra_output_probe(struct tegra_output *output) { struct device_node *ddc, *panel; enum of_gpio_flags flags; int err, size; if (!output->of_node) output->of_node = output->dev->of_node; panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); if (panel) { output->panel = of_drm_find_panel(panel); if (!output->panel) return -EPROBE_DEFER; of_node_put(panel); } output->edid = of_get_property(output->of_node, "nvidia,edid", &size); ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); if (ddc) { output->ddc = of_find_i2c_adapter_by_node(ddc); if (!output->ddc) { err = -EPROBE_DEFER; of_node_put(ddc); return err; } of_node_put(ddc); } output->hpd_gpio = of_get_named_gpio_flags(output->of_node, "nvidia,hpd-gpio", 0, &flags); if (gpio_is_valid(output->hpd_gpio)) { unsigned long flags; err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN, "HDMI hotplug detect"); if (err < 0) { dev_err(output->dev, "gpio_request_one(): %d\n", err); return err; } err = gpio_to_irq(output->hpd_gpio); if (err < 0) { dev_err(output->dev, "gpio_to_irq(): %d\n", err); gpio_free(output->hpd_gpio); return err; } output->hpd_irq = err; flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT; err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq, flags, "hpd", output); if (err < 0) { dev_err(output->dev, "failed to request IRQ#%u: %d\n", output->hpd_irq, err); gpio_free(output->hpd_gpio); return err; } output->connector.polled = DRM_CONNECTOR_POLL_HPD; /* * Disable the interrupt until the connector has been * initialized to avoid a race in the hotplug interrupt * handler. */ disable_irq(output->hpd_irq); } return 0; }
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; }