This pull-request includes some bug fixes and code cleanups. Especially, this fixes the bind failure issue occurred when it tries to re-bind Exynos drm driver after unbound, and the modetest failure issue incurred by not having a pair to vblank on and off requests. * 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: drm/exynos: correct connector->dpms field before resuming drm/exynos: enable vblank after DPMS on drm/exynos: init kms poll at the end of initialization drm/exynos: propagate plane initialization errors drm/exynos: vidi: fix build warning drm/exynos: remove explicit encoder/connector de-initialization drm/exynos: init vblank with real number of crtcs
Unified · Split
| @@ -1355,13 +1355,8 @@ static void exynos_dp_unbind(struct device *dev, struct device *master, · 1354 unmodified lines | ||
| 1355 | 1355 | void *data) |
| 1356 | 1356 | { |
| 1357 | 1357 | struct exynos_drm_display *display = dev_get_drvdata(dev); |
| 1358 | − struct exynos_dp_device *dp = display->ctx; | |
| 1359 | − struct drm_encoder *encoder = dp->encoder; | |
| 1360 | 1358 | |
| 1361 | 1359 | exynos_dp_dpms(display, DRM_MODE_DPMS_OFF); |
| 1362 | − | |
| 1363 | − exynos_dp_connector_destroy(&dp->connector); | |
| 1364 | − encoder->funcs->destroy(encoder); | |
| 1365 | 1360 | } |
| 1366 | 1361 | |
| 1367 | 1362 | static const struct component_ops exynos_dp_ops = { |
| @@ -71,13 +71,16 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) · 70 unmodified lines | ||
| 71 | 71 | !atomic_read(&exynos_crtc->pending_flip), |
| 72 | 72 | HZ/20)) |
| 73 | 73 | atomic_set(&exynos_crtc->pending_flip, 0); |
| 74 | − drm_vblank_off(crtc->dev, exynos_crtc->pipe); | |
| 74 | + drm_crtc_vblank_off(crtc); | |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | if (manager->ops->dpms) |
| 78 | 78 | manager->ops->dpms(manager, mode); |
| 79 | 79 | |
| 80 | 80 | exynos_crtc->dpms = mode; |
| 81 | + | |
| 82 | + if (mode == DRM_MODE_DPMS_ON) | |
| 83 | + drm_crtc_vblank_on(crtc); | |
| 81 | 84 | } |
| 82 | 85 | |
| 83 | 86 | static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) |
| @@ -338,14 +338,10 @@ err_del_component: · 337 unmodified lines | ||
| 338 | 338 | |
| 339 | 339 | int exynos_dpi_remove(struct device *dev) |
| 340 | 340 | { |
| 341 | − struct drm_encoder *encoder = exynos_dpi_display.encoder; | |
| 342 | 341 | struct exynos_dpi *ctx = exynos_dpi_display.ctx; |
| 343 | 342 | |
| 344 | 343 | exynos_dpi_dpms(&exynos_dpi_display, DRM_MODE_DPMS_OFF); |
| 345 | 344 | |
| 346 | − exynos_dpi_connector_destroy(&ctx->connector); | |
| 347 | − encoder->funcs->destroy(encoder); | |
| 348 | − | |
| 349 | 345 | if (ctx->panel) |
| 350 | 346 | drm_panel_detach(ctx->panel); |
| 351 | 347 | |
| @@ -87,16 +87,12 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) · 86 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | plane = exynos_plane_init(dev, possible_crtcs, |
| 89 | 89 | DRM_PLANE_TYPE_OVERLAY); |
| 90 | − if (IS_ERR(plane)) | |
| 91 | − goto err_mode_config_cleanup; | |
| 92 | − } | |
| 93 | − | |
| 94 | − /* init kms poll for handling hpd */ | |
| 95 | − drm_kms_helper_poll_init(dev); | |
| 90 | + if (!IS_ERR(plane)) | |
| 91 | + continue; | |
| 96 | 92 | |
| 97 | − ret = drm_vblank_init(dev, MAX_CRTC); | |
| 98 | − if (ret) | |
| 93 | + ret = PTR_ERR(plane); | |
| 99 | 94 | goto err_mode_config_cleanup; |
| 95 | + } | |
| 100 | 96 | |
| 101 | 97 | /* setup possible_clones. */ |
| 102 | 98 | exynos_drm_encoder_setup(dev); |
| @@ -106,15 +102,16 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) · 3 unmodified lines | ||
| 106 | 102 | /* Try to bind all sub drivers. */ |
| 107 | 103 | ret = component_bind_all(dev->dev, dev); |
| 108 | 104 | if (ret) |
| 109 | − goto err_cleanup_vblank; | |
| 105 | + goto err_mode_config_cleanup; | |
| 110 | 106 | |
| 111 | − /* Probe non kms sub drivers and virtual display driver. */ | |
| 112 | − ret = exynos_drm_device_subdrv_probe(dev); | |
| 107 | + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); | |
| 113 | 108 | if (ret) |
| 114 | 109 | goto err_unbind_all; |
| 115 | 110 | |
| 116 | − /* force connectors detection */ | |
| 117 | − drm_helper_hpd_irq_event(dev); | |
| 111 | + /* Probe non kms sub drivers and virtual display driver. */ | |
| 112 | + ret = exynos_drm_device_subdrv_probe(dev); | |
| 113 | + if (ret) | |
| 114 | + goto err_cleanup_vblank; | |
| 118 | 115 | |
| 119 | 116 | /* |
| 120 | 117 | * enable drm irq mode. |
| @@ -133,12 +130,18 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) · 12 unmodified lines | ||
| 133 | 130 | */ |
| 134 | 131 | dev->vblank_disable_allowed = true; |
| 135 | 132 | |
| 133 | + /* init kms poll for handling hpd */ | |
| 134 | + drm_kms_helper_poll_init(dev); | |
| 135 | + | |
| 136 | + /* force connectors detection */ | |
| 137 | + drm_helper_hpd_irq_event(dev); | |
| 138 | + | |
| 136 | 139 | return 0; |
| 137 | 140 | |
| 138 | −err_unbind_all: | |
| 139 | − component_unbind_all(dev->dev, dev); | |
| 140 | 141 | err_cleanup_vblank: |
| 141 | 142 | drm_vblank_cleanup(dev); |
| 143 | +err_unbind_all: | |
| 144 | + component_unbind_all(dev->dev, dev); | |
| 142 | 145 | err_mode_config_cleanup: |
| 143 | 146 | drm_mode_config_cleanup(dev); |
| 144 | 147 | drm_release_iommu_mapping(dev); |
| @@ -155,8 +158,8 @@ static int exynos_drm_unload(struct drm_device *dev) · 10 unmodified lines | ||
| 155 | 158 | exynos_drm_fbdev_fini(dev); |
| 156 | 159 | drm_kms_helper_poll_fini(dev); |
| 157 | 160 | |
| 158 | − component_unbind_all(dev->dev, dev); | |
| 159 | 161 | drm_vblank_cleanup(dev); |
| 162 | + component_unbind_all(dev->dev, dev); | |
| 160 | 163 | drm_mode_config_cleanup(dev); |
| 161 | 164 | drm_release_iommu_mapping(dev); |
| 162 | 165 | |
| @@ -191,8 +194,12 @@ static int exynos_drm_resume(struct drm_device *dev) · 28 unmodified lines | ||
| 191 | 194 | |
| 192 | 195 | drm_modeset_lock_all(dev); |
| 193 | 196 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 194 | − if (connector->funcs->dpms) | |
| 195 | − connector->funcs->dpms(connector, connector->dpms); | |
| 197 | + if (connector->funcs->dpms) { | |
| 198 | + int dpms = connector->dpms; | |
| 199 | + | |
| 200 | + connector->dpms = DRM_MODE_DPMS_OFF; | |
| 201 | + connector->funcs->dpms(connector, dpms); | |
| 202 | + } | |
| 196 | 203 | } |
| 197 | 204 | drm_modeset_unlock_all(dev); |
| 198 | 205 | |
| @@ -1660,13 +1660,9 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master, · 1659 unmodified lines | ||
| 1660 | 1660 | void *data) |
| 1661 | 1661 | { |
| 1662 | 1662 | struct exynos_dsi *dsi = exynos_dsi_display.ctx; |
| 1663 | − struct drm_encoder *encoder = dsi->encoder; | |
| 1664 | 1663 | |
| 1665 | 1664 | exynos_dsi_dpms(&exynos_dsi_display, DRM_MODE_DPMS_OFF); |
| 1666 | 1665 | |
| 1667 | − exynos_dsi_connector_destroy(&dsi->connector); | |
| 1668 | − encoder->funcs->destroy(encoder); | |
| 1669 | − | |
| 1670 | 1666 | mipi_dsi_host_unregister(&dsi->dsi_host); |
| 1671 | 1667 | } |
| 1672 | 1668 | |
| @@ -630,7 +630,6 @@ static int vidi_remove(struct platform_device *pdev) · 629 unmodified lines | ||
| 630 | 630 | { |
| 631 | 631 | struct exynos_drm_manager *mgr = platform_get_drvdata(pdev); |
| 632 | 632 | struct vidi_context *ctx = mgr->ctx; |
| 633 | − struct drm_encoder *encoder = ctx->encoder; | |
| 634 | 633 | |
| 635 | 634 | if (ctx->raw_edid != (struct edid *)fake_edid_info) { |
| 636 | 635 | kfree(ctx->raw_edid); |
| @@ -639,9 +638,6 @@ static int vidi_remove(struct platform_device *pdev) · 2 unmodified lines | ||
| 639 | 638 | return -EINVAL; |
| 640 | 639 | } |
| 641 | 640 | |
| 642 | − encoder->funcs->destroy(encoder); | |
| 643 | − drm_connector_cleanup(&ctx->connector); | |
| 644 | − | |
| 645 | 641 | return 0; |
| 646 | 642 | } |
| 647 | 643 | |
| @@ -2312,12 +2312,6 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) · 2311 unmodified lines | ||
| 2312 | 2312 | |
| 2313 | 2313 | static void hdmi_unbind(struct device *dev, struct device *master, void *data) |
| 2314 | 2314 | { |
| 2315 | − struct exynos_drm_display *display = get_hdmi_display(dev); | |
| 2316 | − struct drm_encoder *encoder = display->encoder; | |
| 2317 | − struct hdmi_context *hdata = display->ctx; | |
| 2318 | − | |
| 2319 | − hdmi_connector_destroy(&hdata->connector); | |
| 2320 | − encoder->funcs->destroy(encoder); | |
| 2321 | 2315 | } |
| 2322 | 2316 | |
| 2323 | 2317 | static const struct component_ops hdmi_component_ops = { |