static int exynos_dp_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm_dev = data; struct resource *res; struct exynos_dp_device *dp = exynos_dp_display.ctx; unsigned int irq_flags; int ret = 0; dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); if (IS_ERR(dp->video_info)) return PTR_ERR(dp->video_info); ret = exynos_dp_dt_parse_phydata(dp); if (ret) return ret; if (!dp->panel) { ret = exynos_dp_dt_parse_panel(dp); if (ret) return ret; } dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); return PTR_ERR(dp->clock); } clk_prepare_enable(dp->clock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dp->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dp->reg_base)) return PTR_ERR(dp->reg_base); dp->hpd_gpio = of_get_named_gpio(dev->of_node, "samsung,hpd-gpio", 0); if (gpio_is_valid(dp->hpd_gpio)) { /* * Set up the hotplug GPIO from the device tree as an interrupt. * Simply specifying a different interrupt in the device tree * doesn't work since we handle hotplug rather differently when * using a GPIO. We also need the actual GPIO specifier so * that we can get the current state of the GPIO. */ ret = devm_gpio_request_one(&pdev->dev, dp->hpd_gpio, GPIOF_IN, "hpd_gpio"); if (ret) { dev_err(&pdev->dev, "failed to get hpd gpio\n"); return ret; } dp->irq = gpio_to_irq(dp->hpd_gpio); irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; } else { dp->hpd_gpio = -ENODEV; dp->irq = platform_get_irq(pdev, 0); irq_flags = 0; } if (dp->irq == -ENXIO) { dev_err(&pdev->dev, "failed to get irq\n"); return -ENODEV; } INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); exynos_dp_phy_init(dp); exynos_dp_init_dp(dp); ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, irq_flags, "exynos-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; } disable_irq(dp->irq); dp->drm_dev = drm_dev; platform_set_drvdata(pdev, &exynos_dp_display); return exynos_drm_create_enc_conn(drm_dev, &exynos_dp_display); }
static int exynos_dp_probe(struct platform_device *pdev) { struct resource *res; struct exynos_dp_device *dp; struct exynos_dp_platdata *pdata; int ret = 0; dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), GFP_KERNEL); if (!dp) { dev_err(&pdev->dev, "no memory for device data\n"); return -ENOMEM; } dp->dev = &pdev->dev; if (pdev->dev.of_node) { pdata = exynos_dp_dt_parse_pdata(&pdev->dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); ret = exynos_dp_dt_parse_phydata(dp); if (ret) return ret; } else { pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; } } dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); return PTR_ERR(dp->clock); } clk_prepare_enable(dp->clock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dp->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dp->reg_base)) return PTR_ERR(dp->reg_base); dp->irq = platform_get_irq(pdev, 0); if (dp->irq == -ENXIO) { dev_err(&pdev->dev, "failed to get irq\n"); return -ENODEV; } INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); dp->video_info = pdata->video_info; if (pdev->dev.of_node) { if (dp->phy_addr) exynos_dp_phy_init(dp); } else { if (pdata->phy_init) pdata->phy_init(); } exynos_dp_init_dp(dp); ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0, "exynos-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; } platform_set_drvdata(pdev, dp); schedule_work(&dp->hotplug_work); return 0; }