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 int exynos_dp_create_connector(struct exynos_drm_display *display, struct drm_encoder *encoder) { struct exynos_dp_device *dp = display_to_dp(display); struct drm_connector *connector = &dp->connector; int ret; dp->encoder = encoder; /* Pre-empt DP connector creation if there's a bridge */ ret = exynos_drm_attach_lcd_bridge(dp->drm_dev, encoder); if (ret) return 0; connector->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(dp->drm_dev, connector, &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); if (ret) { DRM_ERROR("Failed to initialize connector with drm\n"); return ret; } drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); if (dp->panel) ret = drm_panel_attach(dp->panel, &dp->connector); return ret; }
static int imx_pd_register(struct drm_device *drm, struct imx_parallel_display *imxpd) { int ret; ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder, imxpd->dev->of_node); if (ret) return ret; /* set the connector's dpms to OFF so that * drm_helper_connector_dpms() won't return * immediately since the current state is ON * at this point. */ imxpd->connector.dpms = DRM_MODE_DPMS_OFF; drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs); drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs, DRM_MODE_CONNECTOR_VGA); if (imxpd->panel) drm_panel_attach(imxpd->panel, &imxpd->connector); drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); return 0; }
static int rcar_lvds_attach(struct drm_bridge *bridge) { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); struct drm_connector *connector = &lvds->connector; struct drm_encoder *encoder = bridge->encoder; int ret; /* If we have a next bridge just attach it. */ if (lvds->next_bridge) return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge); /* Otherwise we have a panel, create a connector. */ ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs, DRM_MODE_CONNECTOR_LVDS); if (ret < 0) return ret; drm_connector_helper_add(connector, &rcar_lvds_conn_helper_funcs); ret = drm_mode_connector_attach_encoder(connector, encoder); if (ret < 0) return ret; return drm_panel_attach(lvds->panel, connector); }
static int imx_pd_register(struct drm_device *drm, struct imx_parallel_display *imxpd) { int ret; ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder, imxpd->dev->of_node); if (ret) return ret; drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs, DRM_MODE_ENCODER_NONE); drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs); drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs, DRM_MODE_CONNECTOR_VGA); if (imxpd->panel) drm_panel_attach(imxpd->panel, &imxpd->connector); drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); imxpd->connector.encoder = &imxpd->encoder; return 0; }
static int exynos_dp_bridge_attach(struct drm_bridge *bridge) { struct exynos_dp_device *dp = bridge->driver_private; struct drm_encoder *encoder = &dp->encoder; struct drm_connector *connector = &dp->connector; int ret; /* Pre-empt DP connector creation if there's a bridge */ if (dp->ptn_bridge) { ret = exynos_drm_attach_lcd_bridge(dp, encoder); if (!ret) return 0; } connector->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(dp->drm_dev, connector, &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); if (ret) { DRM_ERROR("Failed to initialize connector with drm\n"); return ret; } drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); if (dp->panel) ret = drm_panel_attach(dp->panel, &dp->connector); return ret; }
int tegra_output_init(struct drm_device *drm, struct tegra_output *output) { int connector, encoder; switch (output->type) { case TEGRA_OUTPUT_RGB: connector = DRM_MODE_CONNECTOR_LVDS; encoder = DRM_MODE_ENCODER_LVDS; break; case TEGRA_OUTPUT_HDMI: connector = DRM_MODE_CONNECTOR_HDMIA; encoder = DRM_MODE_ENCODER_TMDS; break; case TEGRA_OUTPUT_DSI: connector = DRM_MODE_CONNECTOR_DSI; encoder = DRM_MODE_ENCODER_DSI; break; case TEGRA_OUTPUT_EDP: connector = DRM_MODE_CONNECTOR_eDP; encoder = DRM_MODE_ENCODER_TMDS; break; default: connector = DRM_MODE_CONNECTOR_Unknown; encoder = DRM_MODE_ENCODER_NONE; break; } drm_connector_init(drm, &output->connector, &connector_funcs, connector); drm_connector_helper_add(&output->connector, &connector_helper_funcs); output->connector.dpms = DRM_MODE_DPMS_OFF; if (output->panel) drm_panel_attach(output->panel, &output->connector); drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder); drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); drm_mode_connector_attach_encoder(&output->connector, &output->encoder); drm_connector_register(&output->connector); output->encoder.possible_crtcs = 0x3; /* * The connector is now registered and ready to receive hotplug events * so the hotplug interrupt can be enabled. */ if (gpio_is_valid(output->hpd_gpio)) enable_irq(output->hpd_irq); return 0; }
static enum drm_connector_status exynos_dpi_detect(struct drm_connector *connector, bool force) { struct exynos_dpi *ctx = connector_to_dpi(connector); if (ctx->panel && !ctx->panel->connector) drm_panel_attach(ctx->panel, &ctx->connector); return connector_status_connected; }
static int analogix_dp_bridge_attach(struct drm_bridge *bridge) { struct analogix_dp_device *dp = bridge->driver_private; struct drm_encoder *encoder = dp->encoder; struct drm_connector *connector = &dp->connector; int ret; if (!bridge->encoder) { DRM_ERROR("Parent encoder object not found"); return -ENODEV; } connector->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(dp->drm_dev, connector, &analogix_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); if (ret) { DRM_ERROR("Failed to initialize connector with drm\n"); return ret; } drm_connector_helper_add(connector, &analogix_dp_connector_helper_funcs); drm_mode_connector_attach_encoder(connector, encoder); /* * NOTE: the connector registration is implemented in analogix * platform driver, that to say connector would be exist after * plat_data->attch return, that's why we record the connector * point after plat attached. */ if (dp->plat_data->attach) { ret = dp->plat_data->attach(dp->plat_data, bridge, connector); if (ret) { DRM_ERROR("Failed at platform attch func\n"); return ret; } } if (dp->plat_data->panel) { ret = drm_panel_attach(dp->plat_data->panel, &dp->connector); if (ret) { DRM_ERROR("Failed to attach panel\n"); return ret; } } return 0; }
int pl111_connector_init(struct drm_device *dev) { struct pl111_drm_dev_private *priv = dev->dev_private; struct pl111_drm_connector *pl111_connector = &priv->connector; struct drm_connector *connector = &pl111_connector->connector; drm_connector_init(dev, connector, &connector_funcs, DRM_MODE_CONNECTOR_DPI); drm_connector_helper_add(connector, &connector_helper_funcs); pl111_connector->panel = pl111_get_panel(dev->dev); if (pl111_connector->panel) drm_panel_attach(pl111_connector->panel, connector); return 0; }
static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) { struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector); struct drm_panel *panel = mdp4_lvds_connector->panel; int ret = 0; if (panel) { drm_panel_attach(panel, connector); ret = panel->funcs->get_modes(panel); drm_panel_detach(panel); } return ret; }
static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev, struct drm_panel *panel) { struct drm_encoder *encoder = &fsl_dev->encoder; struct drm_connector *connector = &fsl_dev->connector.base; struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config; int ret; fsl_dev->connector.encoder = encoder; ret = drm_connector_init(fsl_dev->drm, connector, &fsl_dcu_drm_connector_funcs, DRM_MODE_CONNECTOR_LVDS); if (ret < 0) return ret; drm_connector_helper_add(connector, &connector_helper_funcs); ret = drm_connector_register(connector); if (ret < 0) goto err_cleanup; ret = drm_mode_connector_attach_encoder(connector, encoder); if (ret < 0) goto err_sysfs; drm_object_property_set_value(&connector->base, mode_config->dpms_property, DRM_MODE_DPMS_OFF); ret = drm_panel_attach(panel, connector); if (ret) { dev_err(fsl_dev->dev, "failed to attach panel\n"); goto err_sysfs; } return 0; err_sysfs: drm_connector_unregister(connector); err_cleanup: drm_connector_cleanup(connector); return ret; }
/* initialize connector */ struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, struct drm_panel *panel, struct drm_encoder *encoder) { struct drm_connector *connector = NULL; struct mdp4_lvds_connector *mdp4_lvds_connector; int ret; mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL); if (!mdp4_lvds_connector) { ret = -ENOMEM; goto fail; } mdp4_lvds_connector->encoder = encoder; mdp4_lvds_connector->panel = panel; connector = &mdp4_lvds_connector->base; drm_connector_init(dev, connector, &mdp4_lvds_connector_funcs, DRM_MODE_CONNECTOR_LVDS); drm_connector_helper_add(connector, &mdp4_lvds_connector_helper_funcs); connector->polled = 0; connector->interlace_allowed = 0; connector->doublescan_allowed = 0; drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); if (panel) drm_panel_attach(panel, connector); return connector; fail: if (connector) mdp4_lvds_connector_destroy(connector); return ERR_PTR(ret); }
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 dsi_mgr_connector_get_modes(struct drm_connector *connector) { int id = dsi_mgr_connector_get_id(connector); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_panel *panel = msm_dsi->panel; int num; if (!panel) return 0; /* * In dual DSI mode, we have one connector that can be * attached to the drm_panel. */ drm_panel_attach(panel, connector); num = drm_panel_get_modes(panel); if (!num) return 0; return num; }
static int imx_ldb_register(struct drm_device *drm, struct imx_ldb_channel *imx_ldb_ch) { struct imx_ldb *ldb = imx_ldb_ch->ldb; int ret; ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder, imx_ldb_ch->child); if (ret) return ret; ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno); if (ret) return ret; if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) { ret = imx_ldb_get_clk(ldb, 1); if (ret) return ret; } drm_encoder_helper_add(&imx_ldb_ch->encoder, &imx_ldb_encoder_helper_funcs); drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs, DRM_MODE_ENCODER_LVDS); drm_connector_helper_add(&imx_ldb_ch->connector, &imx_ldb_connector_helper_funcs); drm_connector_init(drm, &imx_ldb_ch->connector, &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS); if (imx_ldb_ch->panel) drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector); drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, &imx_ldb_ch->encoder); return 0; }
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 mxsfb_load(struct drm_device *drm, unsigned long flags) { struct platform_device *pdev = to_platform_device(drm->dev); struct mxsfb_drm_private *mxsfb; struct resource *res; int ret; mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL); if (!mxsfb) return -ENOMEM; drm->dev_private = mxsfb; mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mxsfb->base = devm_ioremap_resource(drm->dev, res); if (IS_ERR(mxsfb->base)) return PTR_ERR(mxsfb->base); mxsfb->clk = devm_clk_get(drm->dev, NULL); if (IS_ERR(mxsfb->clk)) return PTR_ERR(mxsfb->clk); mxsfb->clk_axi = devm_clk_get(drm->dev, "axi"); if (IS_ERR(mxsfb->clk_axi)) mxsfb->clk_axi = NULL; mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi"); if (IS_ERR(mxsfb->clk_disp_axi)) mxsfb->clk_disp_axi = NULL; ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)); if (ret) return ret; pm_runtime_enable(drm->dev); ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) { dev_err(drm->dev, "Failed to initialise vblank\n"); goto err_vblank; } /* Modeset init */ drm_mode_config_init(drm); ret = mxsfb_create_output(drm); if (ret < 0) { dev_err(drm->dev, "Failed to create outputs\n"); goto err_vblank; } ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs, mxsfb_formats, ARRAY_SIZE(mxsfb_formats), &mxsfb->connector); if (ret < 0) { dev_err(drm->dev, "Cannot setup simple display pipe\n"); goto err_vblank; } ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector); if (ret) { dev_err(drm->dev, "Cannot connect panel\n"); goto err_vblank; } drm->mode_config.min_width = MXSFB_MIN_XRES; drm->mode_config.min_height = MXSFB_MIN_YRES; drm->mode_config.max_width = MXSFB_MAX_XRES; drm->mode_config.max_height = MXSFB_MAX_YRES; drm->mode_config.funcs = &mxsfb_mode_config_funcs; drm_mode_config_reset(drm); pm_runtime_get_sync(drm->dev); ret = drm_irq_install(drm, platform_get_irq(pdev, 0)); pm_runtime_put_sync(drm->dev); if (ret < 0) { dev_err(drm->dev, "Failed to install IRQ handler\n"); goto err_irq; } drm_kms_helper_poll_init(drm); mxsfb->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, drm->mode_config.num_connector); if (IS_ERR(mxsfb->fbdev)) { mxsfb->fbdev = NULL; dev_err(drm->dev, "Failed to init FB CMA area\n"); goto err_cma; } platform_set_drvdata(pdev, drm); drm_helper_hpd_irq_event(drm); return 0; err_cma: drm_irq_uninstall(drm); err_irq: drm_panel_detach(mxsfb->panel); err_vblank: pm_runtime_disable(drm->dev); return ret; }