static int hdac_component_master_bind(struct device *dev) { struct i915_audio_component *acomp = hdac_acomp; int ret; ret = component_bind_all(dev, acomp); if (ret < 0) return ret; if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power && acomp->ops->put_power && acomp->ops->get_cdclk_freq))) { ret = -EINVAL; goto out_unbind; } /* * Atm, we don't support dynamic unbinding initiated by the child * component, so pin its containing module until we unbind. */ if (!try_module_get(acomp->ops->owner)) { ret = -ENODEV; goto out_unbind; } return 0; out_unbind: component_unbind_all(dev, acomp); return ret; }
static int sti_tvout_bind(struct device *dev, struct device *master, void *data) { struct sti_tvout *tvout = dev_get_drvdata(dev); struct drm_device *drm_dev = data; unsigned int i; int ret; tvout->drm_dev = drm_dev; /* set preformatter matrix */ for (i = 0; i < 8; i++) { tvout_write(tvout, rgb_to_ycbcr_601[i], TVO_CSC_MAIN_M0 + (i * 4)); tvout_write(tvout, rgb_to_ycbcr_601[i], TVO_CSC_AUX_M0 + (i * 4)); } sti_tvout_create_encoders(drm_dev, tvout); ret = component_bind_all(dev, drm_dev); if (ret) sti_tvout_destroy_encoders(tvout); return ret; }
static int kirin_drm_kms_init(struct drm_device *dev) { struct kirin_drm_private *priv; int ret; priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; dev->dev_private = priv; dev_set_drvdata(dev->dev, dev); /* dev->mode_config initialization */ drm_mode_config_init(dev); kirin_drm_mode_config_init(dev); /* display controller init */ ret = dc_ops->init(to_platform_device(dev->dev)); if (ret) goto err_mode_config_cleanup; /* bind and init sub drivers */ ret = component_bind_all(dev->dev, dev); if (ret) { DRM_ERROR("failed to bind all component.\n"); goto err_dc_cleanup; } /* vblank init */ ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) { DRM_ERROR("failed to initialize vblank.\n"); goto err_unbind_all; } /* with irq_enabled = true, we can use the vblank feature. */ dev->irq_enabled = true; /* reset all the states of crtc/plane/encoder/connector */ drm_mode_config_reset(dev); /* init kms poll for handling hpd */ drm_kms_helper_poll_init(dev); /* force detection after connectors init */ (void)drm_helper_hpd_irq_event(dev); return 0; err_unbind_all: component_unbind_all(dev->dev, dev); err_dc_cleanup: dc_ops->cleanup(to_platform_device(dev->dev)); err_mode_config_cleanup: drm_mode_config_cleanup(dev); devm_kfree(dev->dev, priv); dev->dev_private = NULL; return ret; }
/* * Platform driver: */ static int etnaviv_bind(struct device *dev) { struct etnaviv_drm_private *priv; struct drm_device *drm; int ret; drm = drm_dev_alloc(&etnaviv_drm_driver, dev); if (!drm) return -ENOMEM; drm->platformdev = to_platform_device(dev); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(dev, "failed to allocate private data\n"); ret = -ENOMEM; goto out_unref; } drm->dev_private = priv; priv->wq = alloc_ordered_workqueue("etnaviv", 0); if (!priv->wq) { ret = -ENOMEM; goto out_wq; } mutex_init(&priv->gem_lock); INIT_LIST_HEAD(&priv->gem_list); priv->num_gpus = 0; dev_set_drvdata(dev, drm); ret = component_bind_all(dev, drm); if (ret < 0) goto out_bind; load_gpu(drm); ret = drm_dev_register(drm, 0); if (ret) goto out_register; return 0; out_register: component_unbind_all(dev, drm); out_bind: flush_workqueue(priv->wq); destroy_workqueue(priv->wq); out_wq: kfree(priv); out_unref: drm_dev_unref(drm); return ret; }
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev) { struct komeda_kms_dev *kms = kzalloc(sizeof(*kms), GFP_KERNEL); struct drm_device *drm; int err; if (!kms) return ERR_PTR(-ENOMEM); drm = &kms->base; err = drm_dev_init(drm, &komeda_kms_driver, mdev->dev); if (err) goto free_kms; drm->dev_private = mdev; komeda_kms_mode_config_init(kms, mdev); err = komeda_kms_add_private_objs(kms, mdev); if (err) goto cleanup_mode_config; err = komeda_kms_add_planes(kms, mdev); if (err) goto cleanup_mode_config; err = drm_vblank_init(drm, kms->n_crtcs); if (err) goto cleanup_mode_config; err = komeda_kms_add_crtcs(kms, mdev); if (err) goto cleanup_mode_config; err = component_bind_all(mdev->dev, kms); if (err) goto cleanup_mode_config; drm_mode_config_reset(drm); err = drm_dev_register(drm, 0); if (err) goto cleanup_mode_config; return kms; cleanup_mode_config: drm_mode_config_cleanup(drm); free_kms: kfree(kms); return ERR_PTR(err); }
static int vc4_drm_bind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm; struct vc4_dev *vc4; int ret = 0; dev->coherent_dma_mask = DMA_BIT_MASK(32); vc4 = devm_kzalloc(dev, sizeof(*vc4), GFP_KERNEL); if (!vc4) return -ENOMEM; drm = drm_dev_alloc(&vc4_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); platform_set_drvdata(pdev, drm); vc4->dev = drm; drm->dev_private = vc4; ret = vc4_bo_cache_init(drm); if (ret) goto dev_unref; drm_mode_config_init(drm); vc4_gem_init(drm); ret = component_bind_all(dev, drm); if (ret) goto gem_destroy; vc4_kick_out_firmware_fb(); ret = drm_dev_register(drm, 0); if (ret < 0) goto unbind_all; vc4_kms_load(drm); return 0; unbind_all: component_unbind_all(dev, drm); gem_destroy: vc4_gem_destroy(drm); vc4_bo_cache_destroy(drm); dev_unref: drm_dev_unref(drm); return ret; }
/* * Platform driver: */ static int etnaviv_bind(struct device *dev) { struct etnaviv_drm_private *priv; struct drm_device *drm; int ret; drm = drm_dev_alloc(&etnaviv_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(dev, "failed to allocate private data\n"); ret = -ENOMEM; goto out_unref; } drm->dev_private = priv; mutex_init(&priv->gem_lock); INIT_LIST_HEAD(&priv->gem_list); priv->num_gpus = 0; dev_set_drvdata(dev, drm); ret = component_bind_all(dev, drm); if (ret < 0) goto out_bind; load_gpu(drm); ret = drm_dev_register(drm, 0); if (ret) goto out_register; return 0; out_register: component_unbind_all(dev, drm); out_bind: kfree(priv); out_unref: drm_dev_unref(drm); return ret; }
static int hdac_component_master_bind(struct device *dev) { struct drm_audio_component *acomp = hdac_get_acomp(dev); int ret; if (WARN_ON(!acomp)) return -EINVAL; ret = component_bind_all(dev, acomp); if (ret < 0) return ret; if (WARN_ON(!(acomp->dev && acomp->ops))) { ret = -EINVAL; goto out_unbind; } /* pin the module to avoid dynamic unbinding, but only if given */ if (!try_module_get(acomp->ops->owner)) { ret = -ENODEV; goto out_unbind; } if (acomp->audio_ops && acomp->audio_ops->master_bind) { ret = acomp->audio_ops->master_bind(dev, acomp); if (ret < 0) goto module_put; } return 0; module_put: module_put(acomp->ops->owner); out_unbind: component_unbind_all(dev, acomp); return ret; }
static int armada_drm_load(struct drm_device *dev, unsigned long flags) { const struct platform_device_id *id; const struct armada_variant *variant; struct armada_private *priv; struct resource *res[ARRAY_SIZE(priv->dcrtc)]; struct resource *mem = NULL; int ret, n, i; memset(res, 0, sizeof(res)); for (n = i = 0; ; n++) { struct resource *r = platform_get_resource(dev->platformdev, IORESOURCE_MEM, n); if (!r) break; /* Resources above 64K are graphics memory */ if (resource_size(r) > SZ_64K) mem = r; else if (i < ARRAY_SIZE(priv->dcrtc)) res[i++] = r; else return -EINVAL; } if (!mem) return -ENXIO; if (!devm_request_mem_region(dev->dev, mem->start, resource_size(mem), "armada-drm")) return -EBUSY; priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { DRM_ERROR("failed to allocate private\n"); return -ENOMEM; } platform_set_drvdata(dev->platformdev, dev); dev->dev_private = priv; /* Get the implementation specific driver data. */ id = platform_get_device_id(dev->platformdev); if (!id) return -ENXIO; variant = (const struct armada_variant *)id->driver_data; INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); INIT_KFIFO(priv->fb_unref); /* Mode setting support */ drm_mode_config_init(dev); dev->mode_config.min_width = 320; dev->mode_config.min_height = 200; /* * With vscale enabled, the maximum width is 1920 due to the * 1920 by 3 lines RAM */ dev->mode_config.max_width = 1920; dev->mode_config.max_height = 2048; dev->mode_config.preferred_depth = 24; dev->mode_config.funcs = &armada_drm_mode_config_funcs; drm_mm_init(&priv->linear, mem->start, resource_size(mem)); /* Create all LCD controllers */ for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { int irq; if (!res[n]) break; irq = platform_get_irq(dev->platformdev, n); if (irq < 0) goto err_kms; ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq, variant, NULL); if (ret) goto err_kms; } if (is_componentized(dev->dev)) { ret = component_bind_all(dev->dev, dev); if (ret) goto err_kms; } else { #ifdef CONFIG_DRM_ARMADA_TDA1998X ret = armada_drm_connector_slave_create(dev, &tda19988_config); if (ret) goto err_kms; #endif } ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) goto err_comp; dev->irq_enabled = true; dev->vblank_disable_allowed = 1; ret = armada_fbdev_init(dev); if (ret) goto err_comp; drm_kms_helper_poll_init(dev); return 0; err_comp: if (is_componentized(dev->dev)) component_unbind_all(dev->dev, dev); err_kms: drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); flush_work(&priv->fb_unref_work); return ret; }
static int armada_drm_load(struct drm_device *dev, unsigned long flags) { struct armada_private *priv; struct resource *mem = NULL; int ret, n; for (n = 0; ; n++) { struct resource *r = platform_get_resource(dev->platformdev, IORESOURCE_MEM, n); if (!r) break; /* Resources above 64K are graphics memory */ if (resource_size(r) > SZ_64K) mem = r; else return -EINVAL; } if (!mem) return -ENXIO; if (!devm_request_mem_region(dev->dev, mem->start, resource_size(mem), "armada-drm")) return -EBUSY; priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { DRM_ERROR("failed to allocate private\n"); return -ENOMEM; } platform_set_drvdata(dev->platformdev, dev); dev->dev_private = priv; INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); INIT_KFIFO(priv->fb_unref); /* Mode setting support */ drm_mode_config_init(dev); dev->mode_config.min_width = 320; dev->mode_config.min_height = 200; /* * With vscale enabled, the maximum width is 1920 due to the * 1920 by 3 lines RAM */ dev->mode_config.max_width = 1920; dev->mode_config.max_height = 2048; dev->mode_config.preferred_depth = 24; dev->mode_config.funcs = &armada_drm_mode_config_funcs; drm_mm_init(&priv->linear, mem->start, resource_size(mem)); mutex_init(&priv->linear_lock); ret = component_bind_all(dev->dev, dev); if (ret) goto err_kms; ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) goto err_comp; dev->irq_enabled = true; dev->vblank_disable_allowed = 1; ret = armada_fbdev_init(dev); if (ret) goto err_comp; drm_kms_helper_poll_init(dev); return 0; err_comp: component_unbind_all(dev->dev, dev); err_kms: drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); flush_work(&priv->fb_unref_work); return ret; }
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; }
static int sun4i_drv_bind(struct device *dev) { struct drm_device *drm; struct sun4i_drv *drv; int ret; drm = drm_dev_alloc(&sun4i_drv_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) { ret = -ENOMEM; goto free_drm; } drm->dev_private = drv; ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) { dev_err(drm->dev, "Couldn't claim our memory region\n"); goto free_drm; } /* drm_vblank_init calls kcalloc, which can fail */ ret = drm_vblank_init(drm, 1); if (ret) goto free_mem_region; drm_mode_config_init(drm); ret = component_bind_all(drm->dev, drm); if (ret) { dev_err(drm->dev, "Couldn't bind all pipelines components\n"); goto cleanup_mode_config; } drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ sun4i_remove_framebuffers(); /* Create our framebuffer */ drv->fbdev = sun4i_framebuffer_init(drm); if (IS_ERR(drv->fbdev)) { dev_err(drm->dev, "Couldn't create our framebuffer\n"); ret = PTR_ERR(drv->fbdev); goto cleanup_mode_config; } /* Enable connectors polling */ drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto finish_poll; return 0; finish_poll: drm_kms_helper_poll_fini(drm); sun4i_framebuffer_free(drm); cleanup_mode_config: drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); free_mem_region: of_reserved_mem_device_release(dev); free_drm: drm_dev_unref(drm); return ret; }
static int hdlcd_drm_bind(struct device *dev) { struct drm_device *drm; struct hdlcd_drm_private *hdlcd; int ret; hdlcd = devm_kzalloc(dev, sizeof(*hdlcd), GFP_KERNEL); if (!hdlcd) return -ENOMEM; drm = drm_dev_alloc(&hdlcd_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); drm->dev_private = hdlcd; dev_set_drvdata(dev, drm); hdlcd_setup_mode_config(drm); ret = hdlcd_load(drm, 0); if (ret) goto err_free; ret = drm_dev_register(drm, 0); if (ret) goto err_unload; ret = component_bind_all(dev, drm); if (ret) { DRM_ERROR("Failed to bind all components\n"); goto err_unregister; } ret = pm_runtime_set_active(dev); if (ret) goto err_pm_active; pm_runtime_enable(dev); ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) { DRM_ERROR("failed to initialise vblank\n"); goto err_vblank; } drm_mode_config_reset(drm); drm_kms_helper_poll_init(drm); hdlcd->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, drm->mode_config.num_connector); if (IS_ERR(hdlcd->fbdev)) { ret = PTR_ERR(hdlcd->fbdev); hdlcd->fbdev = NULL; goto err_fbdev; } return 0; err_fbdev: drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); err_vblank: pm_runtime_disable(drm->dev); err_pm_active: component_unbind_all(dev, drm); err_unregister: drm_dev_unregister(drm); err_unload: drm_irq_uninstall(drm); of_reserved_mem_device_release(drm->dev); err_free: dev_set_drvdata(dev, NULL); drm_dev_unref(drm); return ret; }
static int sun4i_drv_bind(struct device *dev) { struct drm_device *drm; struct sun4i_drv *drv; int ret; drm = drm_dev_alloc(&sun4i_drv_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) { ret = -ENOMEM; goto free_drm; } dev_set_drvdata(dev, drm); drm->dev_private = drv; INIT_LIST_HEAD(&drv->frontend_list); INIT_LIST_HEAD(&drv->engine_list); INIT_LIST_HEAD(&drv->tcon_list); ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) { dev_err(drm->dev, "Couldn't claim our memory region\n"); goto free_drm; } drm_mode_config_init(drm); drm->mode_config.allow_fb_modifiers = true; ret = component_bind_all(drm->dev, drm); if (ret) { dev_err(drm->dev, "Couldn't bind all pipelines components\n"); goto cleanup_mode_config; } /* drm_vblank_init calls kcalloc, which can fail */ ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret) goto cleanup_mode_config; drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ drm_fb_helper_remove_conflicting_framebuffers(NULL, "sun4i-drm-fb", false); sun4i_framebuffer_init(drm); /* Enable connectors polling */ drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto finish_poll; drm_fbdev_generic_setup(drm, 32); return 0; finish_poll: drm_kms_helper_poll_fini(drm); cleanup_mode_config: drm_mode_config_cleanup(drm); of_reserved_mem_device_release(dev); free_drm: drm_dev_put(drm); return ret; }
static int sun4i_drv_bind(struct device *dev) { struct drm_device *drm; struct sun4i_drv *drv; int ret; drm = drm_dev_alloc(&sun4i_drv_driver, dev); if (!drm) return -ENOMEM; drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) { ret = -ENOMEM; goto free_drm; } drm->dev_private = drv; drm_vblank_init(drm, 1); drm_mode_config_init(drm); ret = component_bind_all(drm->dev, drm); if (ret) { dev_err(drm->dev, "Couldn't bind all pipelines components\n"); goto free_drm; } /* Create our layers */ drv->layers = sun4i_layers_init(drm); if (!drv->layers) { dev_err(drm->dev, "Couldn't create the planes\n"); ret = -EINVAL; goto free_drm; } /* Create our CRTC */ drv->crtc = sun4i_crtc_init(drm); if (!drv->crtc) { dev_err(drm->dev, "Couldn't create the CRTC\n"); ret = -EINVAL; goto free_drm; } drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ sun4i_remove_framebuffers(); /* Create our framebuffer */ drv->fbdev = sun4i_framebuffer_init(drm); if (IS_ERR(drv->fbdev)) { dev_err(drm->dev, "Couldn't create our framebuffer\n"); ret = PTR_ERR(drv->fbdev); goto free_drm; } /* Enable connectors polling */ drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto free_drm; return 0; free_drm: drm_dev_unref(drm); return ret; }
static int imx_drm_bind(struct device *dev) { struct drm_device *drm; int ret; drm = drm_dev_alloc(&imx_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); /* * enable drm irq mode. * - with irq_enabled = true, we can use the vblank feature. * * P.S. note that we wouldn't use drm irq handler but * just specific driver own one instead because * drm framework supports only one irq handler and * drivers can well take care of their interrupts */ drm->irq_enabled = true; /* * set max width and height as default value(4096x4096). * this value would be used to check framebuffer size limitation * at drm_mode_addfb(). */ drm->mode_config.min_width = 1; drm->mode_config.min_height = 1; drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; drm->mode_config.funcs = &imx_drm_mode_config_funcs; drm->mode_config.helper_private = &imx_drm_mode_config_helpers; drm->mode_config.allow_fb_modifiers = true; drm_mode_config_init(drm); ret = drm_vblank_init(drm, MAX_CRTC); if (ret) goto err_kms; dev_set_drvdata(dev, drm); /* Now try and bind all our sub-components */ ret = component_bind_all(dev, drm); if (ret) goto err_kms; drm_mode_config_reset(drm); /* * All components are now initialised, so setup the fb helper. * The fb helper takes copies of key hardware information, so the * crtcs/connectors/encoders must not change after this point. */ if (legacyfb_depth != 16 && legacyfb_depth != 32) { dev_warn(dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); legacyfb_depth = 16; } drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto err_poll_fini; drm_fbdev_generic_setup(drm, legacyfb_depth); return 0; err_poll_fini: drm_kms_helper_poll_fini(drm); component_unbind_all(drm->dev, drm); err_kms: drm_mode_config_cleanup(drm); drm_dev_put(drm); return ret; }