diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 65 |
1 files changed, 27 insertions, 38 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 1ff6ab6371e8..0109ff40b1db 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata) } ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, - &hdata->current_mode); + &hdata->current_mode, false); if (!ret) ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf)); if (ret > 0) { @@ -835,7 +835,6 @@ static void hdmi_connector_destroy(struct drm_connector *connector) } static const struct drm_connector_funcs hdmi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .detect = hdmi_detect, .destroy = hdmi_connector_destroy, @@ -945,22 +944,27 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_connector *connector; struct drm_display_mode *m; + struct drm_connector_list_iter conn_iter; int mode_ok; drm_mode_set_crtcinfo(adjusted_mode, 0); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder == encoder) break; } + if (connector) + drm_connector_get(connector); + drm_connector_list_iter_end(&conn_iter); - if (connector->encoder != encoder) + if (!connector) return true; mode_ok = hdmi_mode_valid(connector, adjusted_mode); if (mode_ok == MODE_OK) - return true; + goto cleanup; /* * Find the most suitable mode and copy it to adjusted_mode. @@ -980,6 +984,9 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder, } } +cleanup: + drm_connector_put(connector); + return true; } @@ -1486,8 +1493,6 @@ static void hdmi_enable(struct drm_encoder *encoder) static void hdmi_disable(struct drm_encoder *encoder) { struct hdmi_context *hdata = encoder_to_hdmi(encoder); - struct drm_crtc *crtc = encoder->crtc; - const struct drm_crtc_helper_funcs *funcs = NULL; if (!hdata->powered) return; @@ -1498,18 +1503,11 @@ static void hdmi_disable(struct drm_encoder *encoder) * to disable TV Subsystem should be as following, * VP -> Mixer -> HDMI * - * Below codes will try to disable Mixer and VP(if used) - * prior to disabling HDMI. + * To achieve such sequence HDMI is disabled together with HDMI PHY, via + * pipe clock callback. */ - if (crtc) - funcs = crtc->helper_private; - if (funcs && funcs->disable) - (*funcs->disable)(crtc); - - cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID); cancel_delayed_work(&hdata->hotplug_work); - - hdmiphy_disable(hdata); + cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID); } static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = { @@ -1683,7 +1681,7 @@ static int hdmi_resources_init(struct hdmi_context *hdata) return hdmi_bridge_init(hdata); } -static struct of_device_id hdmi_match_types[] = { +static const struct of_device_id hdmi_match_types[] = { { .compatible = "samsung,exynos4210-hdmi", .data = &exynos4210_hdmi_driver_data, @@ -1707,32 +1705,25 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) struct drm_device *drm_dev = data; struct hdmi_context *hdata = dev_get_drvdata(dev); struct drm_encoder *encoder = &hdata->encoder; - struct exynos_drm_crtc *exynos_crtc; - struct drm_crtc *crtc; - int ret, pipe; + struct exynos_drm_crtc *crtc; + int ret; hdata->drm_dev = drm_dev; - pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev, - EXYNOS_DISPLAY_TYPE_HDMI); - if (pipe < 0) - return pipe; - hdata->phy_clk.enable = hdmiphy_clk_enable; - crtc = drm_crtc_from_index(drm_dev, pipe); - exynos_crtc = to_exynos_crtc(crtc); - exynos_crtc->pipe_clk = &hdata->phy_clk; - - encoder->possible_crtcs = 1 << pipe; - - DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); - drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs); + ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_HDMI); + if (ret < 0) + return ret; + + crtc = exynos_drm_crtc_get_by_type(drm_dev, EXYNOS_DISPLAY_TYPE_HDMI); + crtc->pipe_clk = &hdata->phy_clk; + ret = hdmi_create_connector(encoder); if (ret) { DRM_ERROR("failed to create connector ret = %d\n", ret); @@ -1941,8 +1932,7 @@ static int hdmi_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int exynos_hdmi_suspend(struct device *dev) +static int __maybe_unused exynos_hdmi_suspend(struct device *dev) { struct hdmi_context *hdata = dev_get_drvdata(dev); @@ -1951,7 +1941,7 @@ static int exynos_hdmi_suspend(struct device *dev) return 0; } -static int exynos_hdmi_resume(struct device *dev) +static int __maybe_unused exynos_hdmi_resume(struct device *dev) { struct hdmi_context *hdata = dev_get_drvdata(dev); int ret; @@ -1962,7 +1952,6 @@ static int exynos_hdmi_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops exynos_hdmi_pm_ops = { SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL) |