diff options
Diffstat (limited to 'drivers/gpu/drm/rockchip/rockchip_drm_vop.c')
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 101 |
1 files changed, 82 insertions, 19 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 76c79ac57df0..3f7a82d1e095 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -19,6 +19,9 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_flip_work.h> #include <drm/drm_plane_helper.h> +#ifdef CONFIG_DRM_ANALOGIX_DP +#include <drm/bridge/analogix_dp.h> +#endif #include <linux/kernel.h> #include <linux/module.h> @@ -503,7 +506,7 @@ static int vop_enable(struct drm_crtc *crtc) ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); - goto err_put_pm_runtime; + return ret; } ret = clk_enable(vop->hclk); @@ -857,11 +860,6 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) spin_unlock_irqrestore(&vop->irq_lock, flags); } -static const struct rockchip_crtc_funcs private_crtc_funcs = { - .enable_vblank = vop_crtc_enable_vblank, - .disable_vblank = vop_crtc_disable_vblank, -}; - static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -937,10 +935,10 @@ static void vop_crtc_enable(struct drm_crtc *crtc) } pin_pol = BIT(DCLK_INVERT); - pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? - 0 : BIT(HSYNC_POSITIVE); - pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? - 0 : BIT(VSYNC_POSITIVE); + pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ? + BIT(HSYNC_POSITIVE) : 0; + pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ? + BIT(VSYNC_POSITIVE) : 0; VOP_CTRL_SET(vop, pin_pol, pin_pol); switch (s->output_type) { @@ -1116,6 +1114,53 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc, kfree(s); } +#ifdef CONFIG_DRM_ANALOGIX_DP +static struct drm_connector *vop_get_edp_connector(struct vop *vop) +{ + struct drm_crtc *crtc = &vop->crtc; + struct drm_connector *connector; + + mutex_lock(&crtc->dev->mode_config.mutex); + drm_for_each_connector(connector, crtc->dev) + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + mutex_unlock(&crtc->dev->mode_config.mutex); + return connector; + } + mutex_unlock(&crtc->dev->mode_config.mutex); + + return NULL; +} + +static int vop_crtc_set_crc_source(struct drm_crtc *crtc, + const char *source_name, size_t *values_cnt) +{ + struct vop *vop = to_vop(crtc); + struct drm_connector *connector; + int ret; + + connector = vop_get_edp_connector(vop); + if (!connector) + return -EINVAL; + + *values_cnt = 3; + + if (source_name && strcmp(source_name, "auto") == 0) + ret = analogix_dp_start_crc(connector); + else if (!source_name) + ret = analogix_dp_stop_crc(connector); + else + ret = -EINVAL; + + return ret; +} +#else +static int vop_crtc_set_crc_source(struct drm_crtc *crtc, + const char *source_name, size_t *values_cnt) +{ + return -ENODEV; +} +#endif + static const struct drm_crtc_funcs vop_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, @@ -1123,6 +1168,9 @@ static const struct drm_crtc_funcs vop_crtc_funcs = { .reset = vop_crtc_reset, .atomic_duplicate_state = vop_crtc_duplicate_state, .atomic_destroy_state = vop_crtc_destroy_state, + .enable_vblank = vop_crtc_enable_vblank, + .disable_vblank = vop_crtc_disable_vblank, + .set_crc_source = vop_crtc_set_crc_source, }; static void vop_fb_unref_worker(struct drm_flip_work *work, void *val) @@ -1294,7 +1342,6 @@ static int vop_create_crtc(struct vop *vop) init_completion(&vop->dsp_hold_completion); init_completion(&vop->line_flag_completion); crtc->port = port; - rockchip_register_crtc_funcs(crtc, &private_crtc_funcs); return 0; @@ -1313,7 +1360,6 @@ static void vop_destroy_crtc(struct vop *vop) struct drm_device *drm_dev = vop->drm_dev; struct drm_plane *plane, *tmp; - rockchip_unregister_crtc_funcs(crtc); of_node_put(crtc->port); /* @@ -1359,10 +1405,16 @@ static int vop_initial(struct vop *vop) return PTR_ERR(vop->dclk); } + ret = pm_runtime_get_sync(vop->dev); + if (ret < 0) { + dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + return ret; + } + ret = clk_prepare(vop->dclk); if (ret < 0) { dev_err(vop->dev, "failed to prepare dclk\n"); - return ret; + goto err_put_pm_runtime; } /* Enable both the hclk and aclk to setup the vop */ @@ -1422,6 +1474,8 @@ static int vop_initial(struct vop *vop) vop->is_enabled = false; + pm_runtime_put_sync(vop->dev); + return 0; err_disable_aclk: @@ -1430,6 +1484,8 @@ err_disable_hclk: clk_disable_unprepare(vop->hclk); err_unprepare_dclk: clk_unprepare(vop->dclk); +err_put_pm_runtime: + pm_runtime_put_sync(vop->dev); return ret; } @@ -1530,12 +1586,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data) if (!vop->regsbak) return -ENOMEM; - ret = vop_initial(vop); - if (ret < 0) { - dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); - return ret; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "cannot find irq for vop\n"); @@ -1562,8 +1612,17 @@ static int vop_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(&pdev->dev); + ret = vop_initial(vop); + if (ret < 0) { + dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); + goto err_disable_pm_runtime; + } + return 0; +err_disable_pm_runtime: + pm_runtime_disable(&pdev->dev); + vop_destroy_crtc(vop); err_enable_irq: enable_irq(vop->irq); /* To balance out the disable_irq above */ return ret; @@ -1575,6 +1634,10 @@ static void vop_unbind(struct device *dev, struct device *master, void *data) pm_runtime_disable(dev); vop_destroy_crtc(vop); + + clk_unprepare(vop->aclk); + clk_unprepare(vop->hclk); + clk_unprepare(vop->dclk); } const struct component_ops vop_component_ops = { |