Commit b74d921b authored by Rex-BC Chen's avatar Rex-BC Chen Committed by Chun-Kuang Hu
Browse files

drm/mediatek: Add vblank register/unregister callback functions

We encountered a kernel panic issue that callback data will be NULL when
it's using in ovl irq handler. There is a timing issue between
mtk_disp_ovl_irq_handler() and mtk_ovl_disable_vblank().

To resolve this issue, we use the flow to register/unregister vblank cb:
- Register callback function and callback data when crtc creates.
- Unregister callback function and callback data when crtc destroies.

With this solution, we can assure callback data will not be NULL when
vblank is disable.

Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20220321072320.15019-1-rex-bc.chen@mediatek.com/


Fixes: 9b070498 ("drm/mediatek: Register vblank callback function")
Signed-off-by: default avatarRex-BC Chen <rex-bc.chen@mediatek.com>
Reviewed-by: default avatarjason-jh.lin <jason-jh.lin@mediatek.com>
Signed-off-by: default avatarChun-Kuang Hu <chunkuang.hu@kernel.org>
parent 07fb1e5b
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -76,9 +76,11 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
void mtk_ovl_start(struct device *dev);
void mtk_ovl_stop(struct device *dev);
unsigned int mtk_ovl_supported_rotations(struct device *dev);
void mtk_ovl_enable_vblank(struct device *dev,
void mtk_ovl_register_vblank_cb(struct device *dev,
				void (*vblank_cb)(void *),
				void *vblank_cb_data);
void mtk_ovl_unregister_vblank_cb(struct device *dev);
void mtk_ovl_enable_vblank(struct device *dev);
void mtk_ovl_disable_vblank(struct device *dev);

void mtk_rdma_bypass_shadow(struct device *dev);
@@ -93,9 +95,11 @@ void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
			   struct cmdq_pkt *cmdq_pkt);
void mtk_rdma_start(struct device *dev);
void mtk_rdma_stop(struct device *dev);
void mtk_rdma_enable_vblank(struct device *dev,
void mtk_rdma_register_vblank_cb(struct device *dev,
				 void (*vblank_cb)(void *),
				 void *vblank_cb_data);
void mtk_rdma_unregister_vblank_cb(struct device *dev);
void mtk_rdma_enable_vblank(struct device *dev);
void mtk_rdma_disable_vblank(struct device *dev);

#endif
+17 −5
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
	return IRQ_HANDLED;
}

void mtk_ovl_enable_vblank(struct device *dev,
void mtk_ovl_register_vblank_cb(struct device *dev,
				void (*vblank_cb)(void *),
				void *vblank_cb_data)
{
@@ -105,6 +105,20 @@ void mtk_ovl_enable_vblank(struct device *dev,

	ovl->vblank_cb = vblank_cb;
	ovl->vblank_cb_data = vblank_cb_data;
}

void mtk_ovl_unregister_vblank_cb(struct device *dev)
{
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);

	ovl->vblank_cb = NULL;
	ovl->vblank_cb_data = NULL;
}

void mtk_ovl_enable_vblank(struct device *dev)
{
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);

	writel(0x0, ovl->regs + DISP_REG_OVL_INTSTA);
	writel_relaxed(OVL_FME_CPL_INT, ovl->regs + DISP_REG_OVL_INTEN);
}
@@ -113,8 +127,6 @@ void mtk_ovl_disable_vblank(struct device *dev)
{
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);

	ovl->vblank_cb = NULL;
	ovl->vblank_cb_data = NULL;
	writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN);
}

+14 −6
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ static void rdma_update_bits(struct device *dev, unsigned int reg,
	writel(tmp, rdma->regs + reg);
}

void mtk_rdma_enable_vblank(struct device *dev,
void mtk_rdma_register_vblank_cb(struct device *dev,
				 void (*vblank_cb)(void *),
				 void *vblank_cb_data)
{
@@ -103,16 +103,24 @@ void mtk_rdma_enable_vblank(struct device *dev,

	rdma->vblank_cb = vblank_cb;
	rdma->vblank_cb_data = vblank_cb_data;
	rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
			 RDMA_FRAME_END_INT);
}

void mtk_rdma_disable_vblank(struct device *dev)
void mtk_rdma_unregister_vblank_cb(struct device *dev)
{
	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);

	rdma->vblank_cb = NULL;
	rdma->vblank_cb_data = NULL;
}

void mtk_rdma_enable_vblank(struct device *dev)
{
	rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
			 RDMA_FRAME_END_INT);
}

void mtk_rdma_disable_vblank(struct device *dev)
{
	rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
}

+13 −1
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
{
	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
	int i;

	mtk_mutex_put(mtk_crtc->mutex);
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
@@ -162,6 +163,14 @@ static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
		mtk_crtc->cmdq_client.chan = NULL;
	}
#endif

	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
		struct mtk_ddp_comp *comp;

		comp = mtk_crtc->ddp_comp[i];
		mtk_ddp_comp_unregister_vblank_cb(comp);
	}

	drm_crtc_cleanup(crtc);
}

@@ -618,7 +627,7 @@ static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];

	mtk_ddp_comp_enable_vblank(comp, mtk_crtc_ddp_irq, &mtk_crtc->base);
	mtk_ddp_comp_enable_vblank(comp);

	return 0;
}
@@ -927,6 +936,9 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
			if (comp->funcs->ctm_set)
				has_ctm = true;
		}

		mtk_ddp_comp_register_vblank_cb(comp, mtk_crtc_ddp_irq,
						&mtk_crtc->base);
	}

	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+4 −0
Original line number Diff line number Diff line
@@ -297,6 +297,8 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
	.config = mtk_ovl_config,
	.start = mtk_ovl_start,
	.stop = mtk_ovl_stop,
	.register_vblank_cb = mtk_ovl_register_vblank_cb,
	.unregister_vblank_cb = mtk_ovl_unregister_vblank_cb,
	.enable_vblank = mtk_ovl_enable_vblank,
	.disable_vblank = mtk_ovl_disable_vblank,
	.supported_rotations = mtk_ovl_supported_rotations,
@@ -321,6 +323,8 @@ static const struct mtk_ddp_comp_funcs ddp_rdma = {
	.config = mtk_rdma_config,
	.start = mtk_rdma_start,
	.stop = mtk_rdma_stop,
	.register_vblank_cb = mtk_rdma_register_vblank_cb,
	.unregister_vblank_cb = mtk_rdma_unregister_vblank_cb,
	.enable_vblank = mtk_rdma_enable_vblank,
	.disable_vblank = mtk_rdma_disable_vblank,
	.layer_nr = mtk_rdma_layer_nr,
Loading