drm/rockchip: vop: export rockchip_drm_register_notifier_to_dmc
authorFinley Xiao <finley.xiao@rock-chips.com>
Tue, 9 May 2017 13:34:24 +0000 (21:34 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 11 May 2017 06:47:15 +0000 (14:47 +0800)
This function registers a notifier to dmc devfreq, devfreq thread will
lock the mutex of vop when scaling frequency, so vop_crtc will not be
disabled when it is waiting for line flag.

Change-Id: I886e5dc5d36a0f14f35662cec3423a2c5550a7a6
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
include/soc/rockchip/rockchip_dmc.h

index 3871ca7c17a59ae3c9f3aaa96167d32bf9a315f7..5ff202b129fbc0fd4e81710f207d4421ca8c9b10 100644 (file)
@@ -19,6 +19,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
 
+#include <linux/devfreq.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -209,9 +210,14 @@ struct vop {
        /* vop dclk reset */
        struct reset_control *dclk_rst;
 
+       struct devfreq *devfreq;
+       struct notifier_block dmc_nb;
+
        struct vop_win win[];
 };
 
+struct vop *dmc_vop;
+
 static inline void vop_writel(struct vop *vop, uint32_t offset, uint32_t v)
 {
        writel(v, vop->regs + offset);
@@ -2444,6 +2450,30 @@ out:
 }
 EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
 
+static int dmc_notifier_call(struct notifier_block *nb, unsigned long event,
+                            void *data)
+{
+       if (event == DEVFREQ_PRECHANGE)
+               mutex_lock(&dmc_vop->vop_lock);
+       else if (event == DEVFREQ_POSTCHANGE)
+               mutex_unlock(&dmc_vop->vop_lock);
+
+       return NOTIFY_OK;
+}
+
+int rockchip_drm_register_notifier_to_dmc(struct devfreq *devfreq)
+{
+       if (!dmc_vop)
+               return -ENOMEM;
+
+       dmc_vop->devfreq = devfreq;
+       dmc_vop->dmc_nb.notifier_call = dmc_notifier_call;
+       devfreq_register_notifier(dmc_vop->devfreq, &dmc_vop->dmc_nb,
+                                 DEVFREQ_TRANSITION_NOTIFIER);
+       return 0;
+}
+EXPORT_SYMBOL(rockchip_drm_register_notifier_to_dmc);
+
 static int vop_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -2533,6 +2563,9 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
                return ret;
 
        pm_runtime_enable(&pdev->dev);
+
+       dmc_vop = vop;
+
        return 0;
 }
 
index f85073f1f59dd8bf058c4287243cdde09fec19c3..ef5fb47efab903bc04a1dd9b645cca274127d111 100644 (file)
 
 int rockchip_pm_register_notify_to_dmc(struct devfreq *devfreq);
 
+#ifdef CONFIG_DRM
+int rockchip_drm_register_notifier_to_dmc(struct devfreq *devfreq);
+#else
+static inline int rockchip_drm_register_notifier_to_dmc(struct devfreq *devfreq)
+{
+       return 0;
+}
+#endif
+
 #endif